eclipse에 embedded tomcat 연결
eclipse에서 웹 애플리케이션을 개발할 때 Web Tools Platform(이하 WTP)을 사용하는 경우가 일반적이다. 그런데 WTP를 사용하는 경우 불편한 점이 한 두 가지가 아니다. WTP 기반으로 웹 애플리케이션을 개발할 때 내가 겪은 문제점은 다음과 같다.
- Context Path를 "/"로 설정하는 경우 JSP를 수정했을 때 jsp 컴파일 에러가 발생하는 경우이다. 이 경우 소스 코드에 문제가 있는 것이 아니라 WTP의 버그이다. 서버를 재시작하면 문제를 해결할 수 있다. 하지만 웹 애플리케이션을 처음 개발하는 경우 소스 코드에 문제가 없음에도 불구하고 소스 코드에 문제가 있는 것으로 생각해 디버깅하느라 시간을 낭비하는 경우가 많다.
- WTP의 경우 eclipse 프로젝트를 주기적으로 배포하는 구조로 동작한다. 그런데 WTP 버그로 인해 소스 코드가 변경되었음에도 불구하고 소스 코드가 정상적으로 배포되지 않아 낭비하는 시간이 많다.
- 가장 황당한 경우는 배포한 디렉토리가 삭제되는 경우이다. clean과 같은 작업으로 한번 디렉토리가 삭제될 경우 프로젝트를 정상적으로 배포하지 않아 테스트를 할 수 없는 경우이다. 이 경우 해결 방법을 찾기도 힘들다. 가장 많은 시간을 소비하는 경우이다.
<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>
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에 등록되어 있지 않아서 직접 설치해야 한다. 설치 과정은 다음과 같다.
- https://bitbucket.org/mantis78/relaunch-plugin/downloads 에서 플러그인을 다운로드 한다.
- 다운로드한 파일의 압축을 풀면 jar 파일이 있다. 이 jar 파일을 eclipse 설치 디렉토리 > plugins 디렉토리에 복사한다.
- eclipse를 재시작한다.
설치를 완료한 후 활용 방법은 다음과 같다.
- 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을 각 프로젝트에서 직접 제어할 수 있도록 개발 환경을 구성할 것을 추천한다.