Child pages
  • embedded tomcat으로 로컬 개발 환경 구축하기
Skip to end of metadata
Go to start of metadata

eclipse에 embedded tomcat 연결

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

  • Context Path를 "/"로 설정하는 경우 JSP를 수정했을 때 jsp 컴파일 에러가 발생하는 경우이다. 이 경우 소스 코드에 문제가 있는 것이 아니라 WTP의 버그이다. 서버를 재시작하면 문제를 해결할 수 있다. 하지만 웹 애플리케이션을 처음 개발하는 경우 소스 코드에 문제가 없음에도 불구하고 소스 코드에 문제가 있는 것으로 생각해 디버깅하느라 시간을 낭비하는 경우가 많다.
  • WTP의 경우 eclipse 프로젝트를 주기적으로 배포하는 구조로 동작한다. 그런데 WTP 버그로 인해 소스 코드가 변경되었음에도 불구하고 소스 코드가 정상적으로 배포되지 않아 낭비하는 시간이 많다.
  • 가장 황당한 경우는 배포한 디렉토리가 삭제되는 경우이다. clean과 같은 작업으로 한번 디렉토리가 삭제될 경우 프로젝트를 정상적으로 배포하지 않아 테스트를 할 수 없는 경우이다. 이 경우 해결 방법을 찾기도 힘들다. 가장 많은 시간을 소비하는 경우이다.
위 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 문서를 참고하기 바란다.

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

  • 기본 포트를 8080으로 사용하도록 설정
  • 웹 자원의 기본 디렉토리는 webapp
  • HTTP URL에 대한 기본 인코딩을 UTF-8로 설정.
  • 웹 애플리케이션의 기본 Context Path는 "/"로 설정

위와 같이 구현한 후 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 기준으로 설명한다.

  • Windows > Perferences > General > Keys로 이동한 후 terminate로 검색한다.
  • Terminate and Relaunch를 선택한 후 바딩할 단축키를 설정한다. When은 In Windows로 선택한다.

  • 자신이 친숙하게 생각하는데 perspective에 Debug View를 추가한다. 추가하는 방법은 Window > Show View > Other ... > Debug > Debug를 선택하면 Debug 창이 뜬다.
  • 자바 소스 코드(이 문서에서는 WebServerLauncher)를 활용해 embedded tomcat을 시작한다. 앞에서 띄운 Debug 창을 보면 다음과 같이 embedded tomcat이 실행되고 있음을 확인할 수 있다.

  • embedded tomcat을 재시작하고 싶으면 위 Debug View에서 현재 실행되고 있는 embedded tomcat을 선택한 후 앞에서 설정한 단축키(이 문서는 Ctrl + F2)를 실행하면 된다.

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

플로그인을 설치하는 방법

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

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

  • embedded tomcat을 시작한다.
  • ctrl + 6 단축키를 실행하면 embedded tomcat을 재시작한다.

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

  • Windows > Perferences > General > Keys로 이동한 후 relaunch로 검색하면 Relaunch Command가 검색된다. 이 명령에 바인딩 되어 있는 Ctrl + 6를 다른 단축키로 변경하면 된다.

마치며...

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