-
[Java] Spring 빌드 Jar, WarProgramming/Java 2024. 2. 29. 00:26728x90
Spring 프레임워크를 빌드하면 나오는 실행 파일 포맷은 Jar, War 두가지이다.
Gradle, Maven 같은 빌드 도구를 사용하여 빌드하면 하나의 산출물인 Jar, War파일이 생성된다.
Jar파일은 JVM위에서 실행되지만, War파일은 WAS위에서 실행된다.
Jar -> SpringBoot를 사용하는 경우
War -> JSP만으로 이루어져 있거나, 외부 WAS를 사용할 경우 사용하거나 필요에 맞게 배포(패키지)포맷을 정하면 된다.
● 외장 WAS를 사용하는 환경이라면 war배포
● 내장 WAS를 써야하는 환경이라면 jar배포
● jar와 달리 war는 WEB-INF 및 META-INF 디렉토리로 사전 정의된 구조를 사용하며, WAR파일을 실행하려면 Tomcat, Weblogic, Websphere 등의 웹서버(WEB) 또는 웹컨테이너(WAS)가 필요하다.
과거에는 자바로 웹 애플리케이션을 개발할 때 먼저 서버에 톰캣 같은 WAS를 설치했다.
그리고 WAS에서 동작하도록 서블릿 스펙에 맞춰 코드를 작성하고
WAR형식으로 빌드해서 WAR파일을 만들었다.
그리고 이렇게 만들어진 WAR파일을 WAS에 전달해서 배포하는 방식으로 전체 개발 주기가 동작했다.
이런 방식은 WAS기반 위에서 개발하고 실행해야 한다.
그렇기 때문에 IDE같은 개발 환경에서도 WAS와 연동해서 실행되도록 복잡한 추가 설정이 필요하다.
최근에는 스프링부트가 내장 톰캣을 포함하고 있다.
애플리케이션 코드 안에 톰캣 같은 WAS가 라이브러리로 내장되어 있다.
개발자는 코드를 작성하고 JAR로 빌드한 다음에 해당 JAR를 원하는 위치에서 실행하기만 하면 WAS도 함께 실행된다.
개발자는 main()메서드만 실행하면 되고, WAS설치나 IDE같은 개발 환경에서 WAS와 연동하는 복잡한 일은 수행하지 않아도 된다.
빌드
Gradle 빌드
- IntelliJ IDE를 사용한 방법.
Gradle 아이콘 > Tasks > build > bootJar를 더블 클릭한다.
- cmd창에서 하는 방법.
작업하는 프로젝트로 경로를 이동한다.
cd [Directory] //프로젝트 내부로 이동 gradlew.bat build // 빌드 실행
~[Project]/build/libs/[artifactId]-[version].jar 파일이 생성된다.
~[Project]/build/libs/[ artifactId ]-[version].war 파일이 생성된다.
Maven 빌드
- IntelliJ IDE를 사용한 방법.
Maven 아이콘 > Lifecycle > install를 더블 클릭한다.
~[Project]/target 디렉터리에 Jar파일이 생성된다.
실행
Jar파일 실행
cd ./build/libs //Jar파일이 있는 Directory로 이동 java -jar [File-Name] // Jar파일 실행
Spring Boot가 구동된다!
Jar파일만 실행했는데 웹 서버가 구동된다.
WAS가 없는데도 구동된다.
Why?
Spring Boot 프레임워크에는 톰캣 서버가 내장되어 있기 때문이다.
Spring Boot애플리케이션이 실행하면 톰캣이 생성되고 서블릿이 추가 되면서 애플리케이션이 정상적으로 작동한다.
그래서 Jar파일만 실행해도 서버가 동작한다.
War파일 실행
war파일을 jar파일처럼 실행하면 동작할까?
동작안한다. 못한다. 내장 서버가 없기 때문이다.
Was가 있어야 War파일을 실행할 수 있다.
Tomcat서버가 있어야 한다!
War파일을 톰캣에 배포해야 한다.
Tomcat
1. Tomcat의 server.xml 수정!
Tomcat설치 경로 > conf > server.xml
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="/" docBase="project name" reloadable="false" /> ... </Host>
<Context ~ /> 항목을 추가한다. war파일 이름도 적어준다. (.war확장자 빼고)
2. Tomcat의 webapps에 war파일 복붙
빌드한 war파일을 tomcat 설치 경로 > webapps 디렉토리 하위에 넣는다.
3. cmd에서 실행
Tomcat 설치 경로 > bin 디렉토리로 이동해서 startup.bat를 실행한다.
cd [tomcat설치 경로]/bin startup.bat
톰캣 서버를 통해 war파일이 구동된다!
문자가 깨진다면
Tomcat 설치 경로 > conf > logging.properties 파일에 인코딩 값을 "EUC-KR" 로 변경한다.
java.util.logging.ConsoleHandler.encoding = EUC-KR #UTF-8
Jar, War 파일 구조
Jar
example.jar | +-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-BOOT-INF +-classes | +-mycompany | +-project | +-YourClasses.class +-lib +-dependency1.jar +-dependency2.jar
● projectName.jar
ㄴ BOOT-INF : "개발한 소스 코드" 영역
ㄴ META-INF : "스프링부트" 와 "개발한 소스 코드"를 연결해주는 영역
ㄴ org : "스프링부트" 영역
● BOOT-INF
ㄴ classes : JVM이 읽을 수 있도록 컴파일된 클래스 파일 존재
ㄴ lib : 코드 실행에 필요한 디펜던시 라이브러리들이 존재
ㄴ classpath.idx : 스프링 부트가 lib에 있는 외부 라이브러리들이 찾을 수 있도록 클래스 패스 명시
ㄴ layers.idx : 도커에서 jar이미지를 만들 때 쓰는 정보. 도커는 하나의 이미지를 만들 때 이미지를 차곡차곡 쌓아서 최종 이미지를 만드는 레이어 구조인데 이때 필요한 레이어 정보.
● META-INF
ㄴ MANIFEST.MF : jar가 실행되면 가장 먼저 Main-Class인 JarLauncher가 호출된다.
JarLauncher에서 우리가 개발한 Start-Class를 호출하기 위해 필요한 경로 설정 파일이다.
● org
ㄴ /springframework/boot/loader
: 라이브러리
jar실행 시 spring-boot-loader가 "개발한 소스 코드"를 호출한다.
gradle이 빌드할 때 디폴트로 spring-boot-loader를 넣어준다.
기본 java에도 jar를 실행해주는 클래스가 있을텐데 굳이 spring-boot-loader를 통해 실행하는 이유는 무엇인가?
자바는 jar안의 jar(=nested jar)를 로드하는 방식을 제공하고 있지 않다.
그래서 스프링부트는 spring-boot-loader라는 자신만의 방식으로 nested jar까지 로드하는 방법을 제공한다.
War
example.war | +-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-WEB-INF +-classes | +-com | +-mycompany | +-project | +-YourClasses.class +-lib | +-dependency1.jar | +-dependency2.jar +-lib-provided +-servlet-api.jar +-dependency3.jar
Jar
Java Archive
class및 설정 파일들을 압축해서 만들어진 하나의 애플리케이션 혹은 라이브러리다.
Jar파일을 보면 우리가 생성하지 않은 폴더(META-INF)가 생성되어 있다.
이 프로젝트에는 build시에 사용한 pom.xml파일과 MANIFEST.MF파일이 있다.
즉, 해당 폴더에는 jar파일에 대한 메뉴얼이나 스펙에 대한 내용이 담겨있다.
WAR파일에서도 Web-resource와 같은 정적인 resource를 배포할 때도 META-INF폴더를 이용한다.
Jar실행 원리
1) "java -jar [Project].jar" 커맨드를 실행한다.
2) "MANIFEST.MF"의 "Main-Class"인 "JarLauncher"를 호출한다.
3) "JarLauncher"가 "MANIFEST.MF"의 Start-Class인 "ProjectApplication"을 호출한다.
=> 핵심! 개발한 main메소드를 스프링 프레임워크가 대신 호출하는 것이다!
Jar는 언제 사용하나?
JAR패키징은 클라우드 환경에 적합하다.
WAR파일은 기존의 자바 애플리케이션 서버에 배포할 때는 적합하지만 대부분의 클라우드 플랫폼을 구성하는데는 잘 맞지 않다.
일부 클라우드 플랫폼에서는 WAR파일을 배포하고 실행할 수 있다. 그러나 모든 자바 클라우드 플랫폼은 실행 가능한 JAR파일을 사용한다.
따라서 Spring Initializer에서도 JAR패키징을 기본값으로 사용하는 것이다.
스프링부트에서는 JSP를 지양한다.
JAR배포 시 JSP템플릿 프레임워크 작동하지 않는다고 한다.
jsp는 jar로 묶을 때 /src/main/webapp/WEB-INF/jsp에 위치하다보니 jar에 포함되지 않는다.
만약 jar배포를 하고 싶은데 jsp를 같이 넣고 싶다면 src/main/resources/META-INF/resources/WEB-INF/jsp에 jsp파일을 두면 jar에 포함되고, view도 잘 찾는다고 한다.
War
Web Application Archive
JSP나 Servlet등 WAS컨테이너 위에서 동작하게 빌드된 형태이다.
웹 애플리케이션을 어떻게 설정할 지에 대한 정의가 있는 web.xml파일을 포함하고 있다.
WAS가 동작하면 이 파일에서 설정들을 불러온다.
META-INF : 기본정보 및 static resource를 저장
WEB-INF : 개발된 application의 컴파일된 클래스파일이 위치
WEB-INF안에는 web.xml이라는 중요한 파일이 존재한다.
web.xml에는 필터, 서블렛, DB소스 등 web container가 구동하는데 이용되는 환경설정 파일이다.
즉, 서버가 처음 로딩될때 web.xml파일을 읽어들여 해당 환경설정에 대해 애플리케이션을 배치하게 된다.
참고
https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html
728x90'Programming > Java' 카테고리의 다른 글
[Java] Checked, Unchecked Exception (0) 2024.03.13 [Java] OOME, JVM8 메모리 (0) 2024.02.29 [Java] Garbage Collection (2) 2024.02.28 [Java] String 클래스 (1) 2024.02.06 [Java] Java, JVM 개념 정리 (0) 2023.04.27