eclipse에 embedded tomcat 연결

eclipse에서 웹 애플리케이션을 개발할 때 Web Tools Platform(이하 WTP)을 사용하는 경우가 일반적이다. 그런데 WTP를 사용하는 경우 불편한 점이 한 두 가지가 아니다. WTP 기반으로 웹 애플리케이션을 개발할 때 내가 겪은 문제점은 다음과 같다.

위 3가지 경우만 하더라도 상당히 짜증나는 개발 환경인데 소스 코드를 배포하면서 발생하는 자잘한 버그들을 생각하면 좋은 개발 환경이 아니다. 이런 이유 때문에 eclipse에서 WTP 기반으로 개발하는 것을 썩 좋아하지 않는다. 그런데 이번 학기에 NEXT에서 수업을 하는데 딱히 대안이 없어 WTP를 사용했는데 학생들이 위와 같은 상황을 겪으면서 많은 시간을 낭비하는 것을 보니 다른 대안을 찾아야겠다는 생각이 들었다. 그래서 찾은 대안이 embedded tomcat을 사용하는 것이다. 다른 Web Application Server(이하 WAS)를 사용하는 경우는 모르겠지만 Apache Tomcat을 WAS로 사용하는 경우 embedded tomcat이 좋은 대안이 될 수 있다고 생각한다.
eclipse에서 embedded tomcat을 사용하는 방법은 다음과 같다. maven을 빌드 도구로 사용한다고 했을 때의 설정 방법이다. 먼저 pom.xml 파일에 embedded tomcat에 대한 라이브러리 설정을 추가한다.

 

    <properties>
        <tomcat.version>7.0.34</tomcat.version>
    </properties>

    <dependencies>
        [...]
        
        <!-- embedded tomcat 설정 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper-el</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jsp-api</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
    </dependencies>
프로젝트에서 "mvn eclipse:clean eclipse:eclipse"를 실행해 프로젝트에 대한 의존 관계를 다시 설정하도록 한다.
embedded tomcat에 대한 라이브러리를 추가했으니 다음 작업은 embedded tomcat을 직접 실행할 수 있는 자바 소스 코드를 구현한다.

 

import java.io.File;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;

public class WebServerLauncher {
    public static void main(String[] args) throws Exception {
        String webappDirLocation = "webapp/";
        Tomcat tomcat = new Tomcat();
        String webPort = System.getenv("PORT");
        if(webPort == null || webPort.isEmpty()) {
            webPort = "8080";
        }
        
        tomcat.setPort(Integer.valueOf(webPort));
        Connector connector = tomcat.getConnector();
        connector.setURIEncoding("UTF-8");
        tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
        System.out.println("configuring app with basedir: " + new File("./" + webappDirLocation).getAbsolutePath());
        tomcat.start();
        tomcat.getServer().await();  
    }
}

embedded tomcat 라이브러리를 활용해 지금까지 tomcat에 설정했던 모든 내용을 자바 소스 코드로 설정하는 것이 가능하다. embedded tomcat과 관련한 더 자세한 내용은 Embedding Tomcat 문서를 참고하기 바란다.

위 소스 코드 구현 내용은 다음과 같다.

위와 같이 구현한 후 Ctrl + F11 > Java Application으로 실행하거나 Alt + Shift + X, J 단축키를 활용해 실행할 수 있다. 만약 embedded tomcat을 실행하는 중 다음과 같은 에러가 발생하는 경우 http://www.slipp.net/questions/208 문서를 참고해 해결할 수 있다. Servlet 버전이 3.x가 아니라 발생하는 경우가 있다.

10월 22, 2013 11:46:56 오전 org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/]]
  at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
  at java.util.concurrent.FutureTask.get(Unknown Source)
  at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)
  at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800)
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
  at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
  at java.util.concurrent.FutureTask.run(Unknown Source)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/]]
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
  ... 7 more
Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig()Ljavax/servlet/SessionCookieConfig;
  at org.apache.catalina.deploy.WebXml.configureContext(WebXml.java:1311)
  at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1352)
  at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:878)
  at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:369)
  at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
  at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
  at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5173)
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
  ... 7 more

단축키로 java application 재시작하기

위와 같이 설정한 후 가장 불편한 점 중의 하나는 embedded tomcat 서버를 재시작해야 하는 경우이다. 자바 기반으로 웹 애플리케이션을 개발하다보면 정말 많은 횟수로 WAS를 재시작해야 한다. 하지만 java의 main 메써드를 활용하는 경우 WAS를 재시작하려면 console로 이동해 terminate 명령을 실행해 서버를 종료한 후 자바 소스 코드로 이동해 서버를 재시작해야 한다. 여간 불편한 작업이 아니다. 이 작업을 단축키를 통해 할 수 있으면 좋겠다.

별도의 플러그인을 활용하지 않는 방법

eclipse는 기본적으로 java application으로 실행한 프로그램을 재시작하는 기능은 없다. 단, Debug View에서 현재 실행되고 있는 java application을 선택한 후 실행할 수 있다. 과정은 다음과 같다. Windows OS 기준으로 설명한다.

이 방식의 단점은 embedded tomcat을 재시작하기 위해 Debug View로 이동한 후에 현재 실행 중인 embedded tomcat을 선택한 후 단축키를 실행해야 한다는 것이다. 그럼 이 같은 단점을 보완할 수 있는 다른 방법을 찾아보자.

플로그인을 설치하는 방법

앞에서 제안한 방법으로 별도의 플러그인을 설치하지 않으면서 embedded tomcat을 재시작하는데 충분히 유용하게 사용할 수 있다. 하지만 재시작을 위해 Debug View로 이동하고, 실행 중인 embedded tocmat을 선택한다는 것이 좀 짜증난다. 이 같은 단점을 보완할 수 있는 정말 유용하면서도 작은 플러그인이 있다. 이 플러그인은 eclipse marketplace에 등록되어 있지 않아서 직접 설치해야 한다. 설치 과정은 다음과 같다.

설치를 완료한 후 활용 방법은 다음과 같다.

이 플러그인은 현재 eclipse에 실행 중인 java application을 재시작해 주는 역할을 한다. 만약 단축키가 마음에 들지 않는다면 다음과 같이 변경할 수 있다.

마치며...

지금까지 eclipse에서 embedded tomcat을 활용해 웹 애플리케이션을 개발하는 방법에 대해 살펴봤다. 지금까지 eclipse에서 웹 애플리케이션을 개발하면서의 경험으로 봤을 때 WTP와 같은 별도의 플러그인을 활용하는 것보다 embedded WAS를 사용할 경우 훨씬 안정적으로 개발할 수 있었다. 개인적으로 WTP를 활용하기 보다는 embedded tomcat을 각 프로젝트에서 직접 제어할 수 있도록 개발 환경을 구성할 것을 추천한다.