개발하지연
[maven] maven이란? (개념, 라이프사이클, 결과물) 본문
maven을 사용하기도 하고, 여러 글도 읽어봤지만 아직 감이 잘 안와서 필요한 부분들 정리해보려고 작성하는 글!
maven이란?
[개발 - 빌드 - 배포] 단계에서 프로젝트를 빌드해주는 도구!
https://maven.apache.org/what-is-maven.html
💡 빌드란?
소스 코드 → 실행파일(jar)로 변환하는 작업.
컴파일과 개념이 헷갈릴 수 있는데, 빌드 과정 안에 컴파일 단계가 포함되어 있다.
빌드과정을 명령어로 보면 아래와 같다.
# 소스 코드 컴파일
$ javac Hello.java
# 패키징 (jar 이름, main class, 컴파일 대상 파일 정의)
$ jar --create --file Hello.jar --main-class Hello -C java/main/ .
# 실행 (deploy)
$ java -jar Hello.jar
- 컴파일 (compile) : 소스코드 → 바이너리 파일로 변환
- 소스코드 컴파일해서 바이너리 파일(.class)로 변경
- 패키징 : 바이너리 파일이 참조하는 라이브러리들을 연결해주고, 실행파일로 패키징
- java의 경우 JVM에서 실행가능한 jar로 패키징한다.
- linking이라고도 하는듯
maven 장점
- 빌드 프로세스를 간편하게 해준다
- 프로젝트 라이브러리 관리가 쉬워진다
(pom.xml에 라이브러리를 리스팅해놓으면 참조된 라이브러리까지 다 찾아서 추가해준다)
maven 라이프사이클
라이프사이클이란, 메이븐이 정의하고 있는 빌드 순서이다.
라이프사이클을 구성하는 단계는 phase라고 하고, phase는 goal(가장 작은 태스크)을 실행한다
라이프사이클과 페이즈는 모두 개념이고, 실제 실행되는 작업은 goal에 정의되어있다.
각 페이즈에서 실행하는 plugin:goal 정보 참고 -> 공식문서
💡 maven goal, plugin
- goal은 maven에서 가장 작은 태스크 하나를 정의한다
- plugin은 maven 아티팩트로, 여러개의 goal이 하나의 plugin에 정의되어있다
- maven 내장된 전체 플러그인 정보 → 공식문서
아래는 각 라이프사이클에 대한 설명이다. -> 공식문서 참고
아래 문서에서 정의된 라이프사이클은 clean (빌드 결과물 정리) / default (빌드) / site (문서 생성) 세가지인데 각 라이프사이클 내 phase에서만 순서에 의존적이다. (= 특정 단계가 실패하면 다음 단계로 넘어가지 않는다)
보편적으로는 아래 7가지 라이프사이클로 정의되어서 사용되는 듯하고, intellij maven 플러그인에도 다음과 같이 정의되어있다!
1. clean : 빌드과정에서 생성된 파일들을 모두 삭제하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
maven clean 실행 시 실행되는 코드는 maven-clean-plugin 에 정의되어있고, 한 번 슬쩍 찾아본김에 첨부. -> git code
2. validate : 프로젝트가 필요한 모든 정보를 사용할 수 있는지 검증하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
3. compile : 소스코드를 컴파일 하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
소스코드를 컴파일, 리소스 복사해서 target/clasees에 생성한다.
4. test : 테스트코드가 컴파일되고 테스트를 수행하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
테스트 코드를 target/test-classes에 복사하고, 테스트를 수행한다
*mavn 빌드 시 특정 단계가 실패하면 이후 단계가 실행되지 않기 때문에 -Dmaven.test.skip=true 사용하여 테스트는 패스하기도 한다.
5. pacakge : 배포를 위한 패키지(jar, war,,)를 만드는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
컴파일된 소스코드와 리소스, 의존성 라이브러리들을 같이 패키징하여 실행파일로 만든다.
pom.xml에 어떤 파일로 패키징할지 정의하면 그에 맞게 패키징된다.
<packaging>jar</packaging>
6. verify : 통합 테스트 결과에 대한 검사를 실행하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
7. site : 현재 프로젝트에 대한 문서와 사이트를 생성하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
8. install : 생성한 패키지를 로컬 저장소에 추가하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
- .m2/repository 에 추가
9. deploy : 패키지를 원격 저장소에 추가하는 단계
해당 라이프사이클에서 실행하는 phase는 아래와 같다.
라이프사이클 결과물 까보기 (clean → compile → test → package)
1. clean - target 디렉토리 삭제
빌드 라이프사이클을 진행하면 target 디렉토리에 각 단계의 결과물이 생성되는데, 해당 디렉토리를 clear한다.
2. compile - src/main/java 아래의 코드들을 컴파일 후 target/classes에 클래스파일이 생성된다.
- target/classes : 소스코드가 복사되는 디렉토리.
- target/maven-status : 각 phase에서 필요한 빌드 상태나 정보를 저장해두는 디렉토리
- target/generated-sources : 코드 생성 라이브러리 혹은 annotation 프로세서에 의해 컴파일 타임에 생성되는 코드가 위치하는 디렉토리
(진행하는 프로젝트에서 아래와 같이 pom.xml의 generate-sources에 mapstruct Annotation Processor 작업을 정의해놨는데, 해당 디렉토리에 @Mapper 어노테이션으로 정의한 클래스의 구현체가 생성됐다. lombok이나 buidler도 동일하게 해당 디렉토리에 구현체가 생성되는 듯 하다.)
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
...
<execution>
<id>kapt</id>
<phase>generate-sources</phase>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<annotationProcessorPath>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</annotationProcessorPath>
...
</configuration>
</excution>
</plugin>
3. test - src/test 아래의 코드들을 컴파일 후 target/test-classes에 테스트코드가 생성되고 실행된다.
- target/generated-test-sources : 위와 동일하게 컴파일 타임에 생성되는 코드가 위치하는 디렉토리
- target/test-classes : 테스트 코드가 복사되는 디렉토리
- target/surefire-reports : 테스트 결과가 생성되는 디렉토리
4. package - target 디렉토리 하위에 최종적으로 패키징된 jar 파일이 생성된다.
JAR 파일을 열어보면 MANIFEST.MF에 정의되어있는 클래스 파일 path에 , 의존성 라이브러리 path에 실제 컴파일된 코드와 jar 파일들이 위치해있는데, jar 파일 구성은 나중에 한번 더 정리해야겠다.
Archive: hello.jar
Length Date Time Name
--------- ---------- ----- ----
0 01-04-2024 22:01 META-INF/
553 01-04-2024 22:01 META-INF/MANIFEST.MF
...
5871 02-01-1980 00:00 org/springframework/boot/loader/ClassPathIndexFile.class
6806 02-01-1980 00:00 org/springframework/boot/loader/ExecutableArchiveLauncher.class
3966 02-01-1980 00:00 org/springframework/boot/loader/JarLauncher.class
...
0 01-04-2024 22:01 BOOT-INF/
0 01-04-2024 22:01 BOOT-INF/classes/
0 01-04-2024 22:00 BOOT-INF/classes/com/
...
0 01-04-2024 22:01 BOOT-INF/lib/
30398 11-06-2023 18:20 BOOT-INF/lib/spring-session-data-redis-2.4.3.jar
...
--------- -------
92716267 279 files
참고로 META-INF/MANIFEST.MF 파일은 메타데이터를 저장하는 파일인데, 이것도 까보면 아래와 같다.
Manifest-Version: 1.0
Created-By: Apache Maven 3.8.1
Built-By:
Build-Jdk: 11.0.17
Implementation-Title: {pom.xml에 정의한 <artifactId>}
Implementation-Version: {pom.xml에 정의한 <version>}
Implementation-Vendor-Id: {pom.xml에 정의한 <groupId>}
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: {pom.xml에 정의한 <mainClass>}
Spring-Boot-Version: 2.4.4
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
- Main-Class: jar 파일 실행시 실행해야 하는 클래스들을 지정
- Manifest-Version: 사용 중인 특정 매니페스트 파일 형식을 설명한다.
maven 레포지토리
maven 빌드가 진행되면서 각 단계에서 필요한 라이브러리를 레포지토리에서 찾아서 로컬에 다운로드하고 사용한다.
찾는 순서는 로컬 → 중앙 → 원격 순.
- 로컬저장소 (local)
- 사용자 로컬 디렉토리
- 메이븐 처음 실행할 때 생성된다. -> USER_HOME/.m2/repository
- 매번 원격 저장소에 접근하는 오버헤드를 줄여준다
- 중앙저장소 (central)
- 메이븐 커뮤니티에 의해 운영되는 레포지토리
- https://mvnrepository.com/, https://central.sonatype.com
- 원격저장소 (remote)
- 우리는 nexus 저장소를 사용하는데, 무료로 사용가능한 maven repository이다.
- pom.xml에 아래처럼 정의해놓으면 된다.
<repositories>
<repository>
<id>~~~~~</id>
<url>https://~~~~~~~~ </url>
</repository>
<repositories>
'개발환경' 카테고리의 다른 글
[Intellij] 단축키 (mac) - 코드 포맷팅 formatting (2) | 2023.10.22 |
---|---|
[Intellij] 단축키 (mac) - 라인 복제, 삭제, 이동 (1) | 2023.10.22 |