# Maven Deep Dive
- 2004년 Maven 2 등장으로 라이프사이클/플러그인 모델 정착
- 대규모 자바 프로젝트에서 일관된 빌드·의존성 관리 표준 제공
- 선언적 구성(POM)과 재사용 가능한 플러그인 조합이 핵심
## Maven 핵심 개념 정리
- **Model**: `pom.xml`이 Project Object Model을 정의, 프로젝트 메타데이터·의존성·빌드 설정 관리
- **Lifecycle**: clean / default / site 세 가지 라이프사이클과 각 단계(phase)에 goal 연결
- **Plugin**: 실제 작업을 실행하는 단위, goal을 phase에 매핑하여 실행 흐름 구성
- **Repository**: Local(`~/.m2/repository`) ↔ Remote(Maven Central, 사내 Nexus 등) 캐시/배포 구조
## pom.xml 구조 심층 분석
```xml
4.0.0
...
...
...
...
jar|war|pom|ear ...
21
org.springframework.boot
spring-boot-starter-web
${spring.boot.version}
compile|test|provided|runtime|import
...
...
...
...
...
...
```
### parent vs dependencyManagement
- **parent**: 공통 속성/플러그인/의존성 버전 상속, `relativePath`로 부모 위치 지정 가능
- **dependencyManagement**: 하위 모듈이 버전 명시 없이 의존성 추가 가능하도록 버전 캡 정의
## Lifecycle Deep Dive
| Lifecycle | 주요 Phase | 설명 |
|-----------|-----------|------|
| clean | pre-clean → **clean** → post-clean | 이전 빌드 산출물 제거 |
| default | validate → compile → test → package → verify → **install** → deploy | 컴파일·테스트·배포 중심 기본 흐름 |
| site | pre-site → **site** → post-site → site-deploy | 프로젝트 문서 생성·배포 |
- `mvn ` 실행 시 해당 phase 이전 단계까지 순차 수행
- `mvn clean package`처럼 다른 라이프사이클 조합 가능
## Plugin & Goal 전략
- `maven-compiler-plugin`: `compile`, `testCompile` goal로 자바 소스 컴파일
- `maven-surefire-plugin`: 단위 테스트 실행, JUnit5 사용 시 `provider` 설정 주의
- `maven-failsafe-plugin`: 통합 테스트(`integration-test`, `verify`)에 goal 매핑
- `spring-boot-maven-plugin`: `repackage`, `spring-boot:run` 지원
- Goal 직접 실행: `mvn dependency:tree`, `mvn help:effective-pom`
## Profiles로 환경 분리
```xml
prod
env
prod
jdbc:postgresql://prod-host/db
```
- `mvn package -Pprod` 혹은 `-Denv=prod`로 활성화
- 환경별 리소스 필터링(`resources/filtering`), 플러그인 설정 분기, 다중 모듈 선택적 빌드 가능
## 의존성 관리 고급 기법
1. **BOM(Bill of Materials)**
- `scope import` + `type pom` 조합으로 플랫폼 버전 캡 고정
- 예) `spring-boot-dependencies`, `quarkus-bom`
2. **Optional Dependency**
- `true`로 전이 의존성 확산 제한
3. **Exclusion**
- 충돌 버전 제거 시 `dependency/exclusions` 활용
4. **Dependency Convergence**
- `mvn -Dverbose dependency:tree`로 충돌 탐지 후 관리
## Tomcat Embed 버전 지정
- Spring Boot 미사용 시 명시적으로 Tomcat Embed 버전 고정 필요
- 공통 속성 혹은 BOM을 통해 의존성 버전 일관성 유지
```xml
10.1.25
org.apache.tomcat.embed
tomcat-embed-core
${tomcat.embed.version}
org.apache.tomcat.embed
tomcat-embed-jasper
${tomcat.embed.version}
```
- 여러 모듈에서 공유한다면 parent POM의 ``에 동일 버전 선언 후 하위 모듈에서 버전 생략
- Spring Boot를 사용한다면 `spring-boot-starter-web`이 관리하는 Tomcat 버전을 우선 따르고, 커스터마이징은 `spring-boot-dependencies` BOM을 override하지 않는 선에서 `` 조정
## Offline 빌드
- 폐쇄망 등에서 로컬의 저장소에서 의존성만으로 빌드
- `mvn clean install -o`
- 또는, `~/.m2/settings.xml`에 `true` 설정
## Jetty Embed 대안
- Non-Blocking I/O 및 경량 서버가 필요하다면 Jetty Embed 선택
- Tomcat과 동일하게 버전 충돌을 피하려면 속성/관리 섹션으로 버전 고정
```xml
11.0.22
org.eclipse.jetty
jetty-server
${jetty.version}
org.eclipse.jetty
jetty-servlet
${jetty.version}
```
- JSP가 필요하다면 `apache-jsp`, `taglibs-standard-impl` 등 추가 고려
- Jetty BOM(`org.eclipse.jetty:jetty-bom`)을 ``에 추가하면 하위 모듈에서 버전 생략 가능
- Spring Boot에서 Jetty로 교체 시 `spring-boot-starter-web` 대신 `spring-boot-starter-jetty` 사용
## Repository & Distribution 전략
- **Local**: 최초 다운로드 후 캐시, `~/.m2/settings.xml`로 경로 변경 가능
- **Remote**: Maven Central → 사내 Nexus/Artifactory 프록시 구성해 속도·보안 확보
- **Distribution Management**: 스냅샷(`snapshotRepository`) vs 릴리스(`repository`) 경로 분리
- 사내 아티팩트 업로드: `mvn deploy -DskipTests`
## settings.xml 체크포인트
- 위치: `${maven.home}/conf/settings.xml` 또는 `~/.m2/settings.xml`
- 서버 인증정보: `corp-nexus...`
- 미러: ``로 중앙 저장소 대신 사내 저장소 우선 사용
- 프로파일 글로벌 적용: `` + `` 조합
## 빌드 성능 & 디버깅 팁
- 병렬 빌드: `mvn -T 1C clean package` (코어 수 기준)
- 의존성 해석 확인: `mvn -U`로 원격 스냅샷 강제 업데이트
- 디버깅: `mvn -X` (debug 로그), `mvn -e` (stacktrace)
- CI 최적화: `mvn --batch-mode -Dmaven.test.skip=true` (필요 시 테스트 생략)
- 다중 JVM 환경: `toolchains.xml` 활용해 JDK 버전 고정
## 표준 디렉터리 구조
```
maven-project/
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ ├── resources
│ │ └── webapp
│ └── test
│ ├── java
│ └── resources
├── target
├── .mvn/
│ ├── wrapper/
│ └── jvm.config
└── README.md
```
- `src/main/resources`: 프로퍼티·템플릿 등 빌드 시 클래스패스 포함 리소스
- `src/main/webapp`: WAR 패키징 시 정적 파일·WEB-INF 구성
- `.mvn/wrapper`: Maven Wrapper(`mvnw`, `mvnw.cmd`) 설정
## 참고 명령어
- `mvn help:effective-pom`: 상속/프로필 반영된 최종 POM 확인
- `mvn dependency:analyze`: 사용되지 않는 의존성/미선언 의존성 점검
- `mvn versions:display-dependency-updates`: 버전 업그레이드 후보 확인
## 더 읽을거리
- Maven 공식 가이드: https://maven.apache.org/guides/
- Repository 검색: https://mvnrepository.com
- Polyglot Maven (YAML/Groovy POM): https://github.com/takari/polyglot-maven