이번 글에서는 간략하게 Maven Standard Directory Layout와 plain jar, executable jar에 대해 소개하려 합니다.
Maven Standard Directory Layout
흔히 spring boot 프로젝트를 생성하면 아래와 같은 패키지 구조를 가지게 됩니다.
> tree src
src
├── main
│ ├── java
│ │ └── com
│ │ └── kukim
│ │ └── recipe
│ │ └── RecipeApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── com
└── kukim
└── recipe
└── RecipeApplicationTests.java
13 directories, 3 files
src/main, src/resources, /src/test ... 와 같은 구조는 어떤 형식을 따르는 것일까요? 왜 이렇게 사용하는 걸까요?
그 이유는 바로 Maven Standard Directory Layout을 따르는 것입니다. 표준 레이아웃을 따르기 때문에 컴파일과 jar 묶을 때 별다른 path 지정 없이 간편하게 빌드 할 수 있습니다. (gradle도 해당 레이아웃을 사용합니다.)
plain jar와 executable jar
Spring Boot2.5 이상에서 빌드하면 그 결과로 plain.jar와. jar 파일 두 개가 생성됩니다.
# gradle build
> ./gradlew clean build
BUILD SUCCESSFUL in 5s
8 actionable tasks: 8 executed
# build 결과, build/libs
> ls build/libs
recipe-0.0.1-SNAPSHOT-plain.jar recipe-0.0.1-SNAPSHOT.jar
두 파일의 차이는 무엇일까요?
plain.jar
src/main 하위의 컴파일된 소스코드(. class)들과 src/resources 파일들이 묶여있습니다.
이는 외부 의존성(tomcat, jackson, spring-boot)은 존재하지 않습니다. 말 그대로 plain jar이죠.
따라서 plain.jar 만으로는 spring boot를 실행할 수 없습니다.
# plain.jar 압축 해제
> unzip recipe-0.0.1-SNAPSHOT-plain.jar -d plain-jar
# plain.jar 압축 해제한 폴더 tree
> tree plain-jar
plain-jar
├── META-INF
│ └── MANIFEST.MF
├── application.properties
├── com
│ └── kukim
│ └── recipe
│ └── RecipeApplication.class
├── static
└── templates
6 directories, 3 files
executable-jar
plain.jar 가 아닌 다른 jar는 executable-jar(실행 가능한 jar)라고 합니다. 개발자가 작성한 소스코드에 추가적으로 외부 의존성이 포함되어 있습니다. 따라서 해당 jar는 내장 톰캣과 여러 의존성을 포함하고 있기 때문에 실행할 수 있게 됩니다.
# executable.jar 압축 해제
> unzip recipe-0.0.1-SNAPSHOT.jar -d plain-jar
# executable-jar 압축 해제한 파일 tree
> tree executable-jar
executable-jar
├── BOOT-INF
│ ├── classes
│ │ ├── application.properties
│ │ ├── com
│ │ │ └── kukim
│ │ │ └── recipe
│ │ │ └── RecipeApplication.class
│ │ ├── static
│ │ └── templates
│ ├── classpath.idx
│ ├── layers.idx
│ └── lib
│ ├── jackson-annotations-2.14.1.jar
│ ├── jackson-core-2.14.1.jar
│ ├── jackson-databind-2.14.1.jar
│ ├── jackson-datatype-jdk8-2.14.1.jar
│ ├── jackson-datatype-jsr310-2.14.1.jar
│ ├── jackson-module-parameter-names-2.14.1.jar
│ ├── jakarta.annotation-api-2.1.1.jar
### 생략
spring boot를 활용하여 jar나 docker image를 생성한다면 executable jar를 가지고 사용하게 됩니다.
+a) 두 파일이 이름이 비슷하게 생기기 때문에 배포 시 *. jar와 같이 경로를 넣게 된다면 executable jar가 아닌 plain jar가 배포되어 실행이 안될 수 있습니다. 이에 유의해야 합니다. gradle의 경우 옵션을 주어 plain 생성되지 않도록 설정할 수 있습니다. (ref : spring boot docs : Packaging Executable and Plain Archives)
Reference
- Maven Standard Directory Layout
- spring boot docs : Packaging Executable and Plain Archives
'☕️ JAVA > 🍃 Spring' 카테고리의 다른 글
스프링 부트 살펴보기 / 의존성 관리 간소화, 배포 간소화, 자동 설정 (0) | 2023.06.04 |
---|---|
Spring VS Spring Boot 몇 가지 차이점 (2) | 2022.09.23 |
./gradlew bootRun vs java -jar로 실행할 때의 차이점 (리소스 경로) (0) | 2022.03.19 |
Spring boot에서 H2 DB 3가지 모드 사용하기(embedded, In-Memory, Server) (0) | 2022.03.16 |
댓글