2018년 7월 9일 월요일

Spring Boot 프로젝트를 War로 패키징하기(생성하기)

 Spring Boot를 사용하는 이유를 나열해 본다면 많은 장점들이 있겠지만 그 중에서도 꽤나 큰 장점으로 Embedded Tomcat을 내장함으로써 Web 프로젝트 개발 시에 그리고 배포시에 매우 간단하게 작업할 수 있다는 간편함을 들 수 있겠다. 하지만 현업에서 실제 배포시에 Jar 파일을 그대로 실행해서 서비스를 하는 경우는 드물고 Apache + Tomcat 환경에서 War 파일 형태로 배포해야 하는 경우가 꽤 많다.

 그래서 하나의 웹 프로젝트를 생성해서, 개발중에는 Embedded Tomcat을 이용하여 개발 & 테스트를 수행하고, 배포는 간단하게 War로 패키징해서 배포하는 방법을 여기에 설명해 보려고 한다.

 Spring Boot 프로젝트를 생성하는 가장 간단한 방법은 Spring Initializr 사이트를 이용하는 것이다. Spring Initializr 에 접속해보자.


 사이트에 접속하면 위와 같은 페이지가 보이는데 화면 하단의 "Switch to the full version" 링크를 눌러서 화면을 Full version으로 전환해 보도록 하자. 


 화면을 전환하면 위와 같은 화면이 나오는데 Group, Artifact 같은 값들을 원하는 값으로 채워준다. 빨간색으로 표시한 부분의 값들은 원래 기본값이 있었으나 내가 바꿔준 것들이므로 간단히 설명하겠다. 필자는 개발툴로 IntelliJ IDEA를 사용할 예정인데 개인적으로 IntelliJ에서는 Maven보다 Gradle을 선호하기 때문에 일단 Gradle Project를 선택했다. 그리고 Package Name은 기본적으로 Group.Artifact 형태로 자동 입력되지만 필자는 package 이름에 대문자가 들어가는 걸 원치 않기 때문에 이 값은 적절히 바꿔주었다. 그리고 가장 중요한 Packaging값은 기본적으로 Jar지만 이 값을 War로 바꿔주도록 한다. 마지막으로 Dependencies 값은 Web 프로젝트를 만들 것이므로 간단하게 "Web"을 추가해준다. 

 인터넷에서 많은 개발자들이 Jar 프로젝트를 War로 바꾸는 방법을 설명하고 있지만 생성할 때 이렇게 Packaging값을 War로 지정해서 생성하면 프로젝트 설정을 바꾸지 않고도 Jar와 War의 장점을 모두 이용할 수 있으므로 꼭 War로 생성하길 바란다. 

 이제 설정이 끝났으면 Generate Project 버튼을 눌러보자. zip 파일을 하나 다운받게 되는데 이 파일을 원하는 곳에 풀고 IntelliJ로 열어보도록 하자. IntelliJ를 실행하고 Open 메뉴를 클릭한 후 압축을 푼 폴더를 선택하면 된다. 

 Open 메뉴를 실행하면 최초에 아래와 같은 Import 화면이 나오게 된다.


 기본값 그대로 사용해도 되지만 필자는 항상 빨간색으로 표시한 부분에 체크를 해준다. 체크박스의 라벨을 읽어보면 알겠지만 체크를 해주는 게 나중에 더 편리하기 때문에 항상 체크를 하고 넘어간다. 나중에라도 이 설정은 바꿀 수 있으므로 원하는 대로 해주고 OK를 누르면 된다. 

 OK를 눌러서 Open을 하고나면 IntelliJ가 수 초 동안 여러가지 작업을 하게되는 잠시 기다려 주도록 하자. 잠시 후 작업이 끝나고 Project뷰와 Gradle 뷰를 보면 아래와 같은 상태일 것이다.


 위 그림에서 빨간색으로 표시해 놓은 부분들을 자세히 보도록 하자. 이 부분들이 Packaging을 Jar로 해서 생성한 것과 비교했을 때 크게 다른 부분들이라고 할 수 있겠다. 일단 왼쪽의 Project 뷰를 보면 ServletInitializer 클래스가 추가되었다. War로 배포했을 때 web.xml 없이 configuration을 제공할 수 있도록 하는 클래스이다. 클래스의 내용을 열어봐도 HelloSpringBootApplication 클래스를 Configuration source로 지정하는 것 말고는 별 내용이 없다. 하지만 War로 배포할 때 반드시 필요하기 때문에 자동으로 생성이 된다.

 그 다음 오른쪽의 Gradle 뷰를 보면 Jar로 생성했을 때와는 달리 bootWar와 war 태스크들이 보인다. War 파일을 생성하고 싶다면 bootWar 태스크를 실행시키면 된다. build/libs 폴더 아래 War 파일이 생성되고 이 파일을 그대로 Tomcat의 webapps 폴더에 배포해주면 된다. Jar를 생성하고 싶다면 bootJar 태스크를 실행시키면 같은 위치(build/libs)에 Jar 파일이 생성된다. 이 Jar 파일도 터미널에서 직접 실행이 가능하다. 

 개발 중에는 프로젝트를 Jar로 생성했을 때와 마찬가지로 bootRun 태스크로 실행하면 Embedded Tomcat 환경에서 실행이 되므로 bootRun 태스크를 이용해서 Test & Debugging을 하면 된다. 

 참고로 IntelliJ와 관련하여 추가적으로 설정할 게 하나 있다. 아래 그림과 같이 build.gradle 파일을 열어서 eclipse 플러그인을 주석처리하고 idea 플러그인을 넣어주도록 하자.


 이제 IntelliJ 환경에서 Spring Boot로 Web 개발을 시작할 준비는 끝났다. 간단한 테스트를 위해서 web interface를 하나 추가하고 테스트를 해보자.

 아래 그림과 같이 HelloController 클래스를 하나 추가하고 bootRun 태스크를 실행해 보도록 하자.


 정확하게 입력했다면 위 그림의 하단에 보이는 로그가 출력되고 Embedded Tomcat 서버가 실행될 것이다. 이 상태에서 브라우저를 띄워서 "localhost:8080/hello"을 주소창에 입력해보면 아래 그림과 같은 페이지가 뜨게 된다. 


 Embedded Tomcat에 의해서 요청이 처리되고 있음을 알 수 있다. 참고로 bootRun 태스크를 실행하지 않고 bootJar를 실행해서 생성된 Jar파일을 터미널에서 직접 실행해도 같은 결과를 얻을 수 있다.

 이제 war로 배포를 해보자. 먼저 Gradle 뷰에서 bootWar 태스크를 실행한다. build/libs 폴더 아래 생성된 War 파일을 sample.war로 이름을 바꿔서 Tomcat의 webapps 폴더에 복사해 넣어보자. 로컬이 아닌 다른 장비에 Tomcat 환경이 구축되어있다면 테스트 결과가 더 명확하게 보일 것이므로 필자는 다른 장비에 있는 Tomcat에 배포를 하였다. Tomcat 설정을 auto deploy가 되도록 했다면 war 파일이 풀리고 바로 접근이 가능하게 된다.

 브라우저를 띄워서 주소창에 "서버주소:포트/sample/hello"를 입력해보자. 같은 페이지 내용이 보일 것이다. 보이지 않는다면 Tomcat의 deploy문제나 방화벽, 파일 접근 권한 등에 문제가 있는 것이므로 체크해보도록 하자. 


 여기서 한 가지 주의할 점은 sample.war로 배포했기 때문에 deploy가 되면서 webapps/sample 폴더에 deploy가 되고 접속 URL의 경로가 /sample/hello가 된다는 것이다. 이 부분은 Tomcat과 Spring을 좀 다루어 본 독자라면 잘 이해하고 있을 것이므로 따로 설명은 하지 않겠다.

 필자가 테스트를 수행한 Tomcat은 9 버전이다. 아마도 Tomcat 8 버전에서도 잘 될 것이라고 생각된다. 하지만 Tomcat 7 에서는 deploy가 되지 않는 현상이 있었다. 로그파일 확인 결과 javax.el-api의 버전이 낮아서 생기는 문제였다. Spring Boot 버전에 따라서 Embedded Tomcat의 버전이 달라지는데 Spring Boot 2.0.3 버전에서는 Tomcat 8.5.xx 버전을 사용하고 있기 때문에 Tomcat 7에서는 문제가 발생하는 것으로 보인다. 이것 말고도 Spring Boot가 사용하는 다른 여러 api의 버전 차이가 문제가 될 수 있으므로 만약 deploy가 되지 않으면 catalina.out 로그 파일을 체크하여 문제를 파악해 보는게 좋겠다.

 Spring Boot가 어떤 버전의 Tomcat을 사용하는 지 알아보는 법은 Maven Repository 사이트에 접속하여 spring-boot-starter-tomcat 라이브러리를 찾고 이 라이브러리의 Dependency를 체크해보면 dependency가 걸려있는 Tomcat의 버전을 알 수 있다.

 이렇게 모든 설명이 끝났다. 상당히 많은 양의 글을 썼지만 한 가지로 요약하자면 프로젝트를 생성할 때 Packaging값을 War로 설정하는 것이다. 이 점만 잊지말기를 바란다.


댓글 2개:

  1. Great content. I have bookmarked your blogspot. Best regards Veronica

    답글삭제
  2. Excellent content. I have bookmarked your page. Greetings Sonya

    답글삭제