Maven 개요
Apache Maven은 프로젝트 빌드, 의존성 관리, 문서 생성을 통합 관리하는 도구입니다. POM(Project Object Model) 구조를 중심으로 표준화된 디렉터리 구조와 빌드 라이프사이클을 제공하여 개발팀 간 협업을 용이하게 합니다.
핵심 설계 철학: 규약 우선
Maven은 "Convention over Configuration" 철학을 따릅니다. 개발자가 별도 설정 없이도 프로젝트를 구성할 수 있도록 합리적인 기본값을 제공합니다.
| 구성 요소 | 기본 경로 |
|---|---|
| 소스 코드 | ${project.basedir}/src/main/java |
| 리소스 | ${project.basedir}/src/main/resources |
| 테스트 코드 | ${project.basedir}/src/test/java |
| 컴파일 결과 | ${project.basedir}/target/classes |
| 배포 아티팩트 | ${project.basedir}/target |
POM 파일 구조
pom.xml은 Maven 프로젝트의 핵심 설정 파일입니다. 다음은 기본 구조입니다:
<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.example.team</groupId>
<artifactId>payment-service</artifactId>
<version>2.1.0</version>
<packaging>jar</packaging>
</project>
모든 POM은 암묵적으로 Super POM을 상속받습니다. 실제 적용되는 설정을 확인하려면 다음 명령을 실행합니다:
mvn help:effective-pom
빌드 라이프사이클
Maven은 세 가지 표준 라이프사이클을 제공합니다:
Clean 라이프사이클
- pre-clean: 빌드 결과 삭제 전 작업
- clean: 타 디렉터리 제거
- post-clean: 후속 정리 작업
Default (Build) 라이프사이클
| 단계 | 설명 |
|---|---|
| validate | 프로젝트 구조 및 정보 검증 |
| compile | 소스 코드 컴파일 |
| test | 단위 테스트 실행 |
| package | 배포 가능한 아티팩트 생성 |
| verify | 품질 기준 충족 여부 확인 |
| install | 로컬 저장소에 아티팩트 설치 |
| deploy | 원격 저장소에 아티팩트 배포 |
Site 라이프사이클
프로젝트 문서와 보고서를 생성합니다. mvn site 명령으로 실행하며, Doxia 엔진을 통해 XDoc, XHTML 등 다양한 형식을 처리합니다.
프로파일(Profile) 활용
프로파일은 빌드 환경별 설정 분리를 가능하게 합니다. 다음은 경별 데이터베이스 설정 예시입니다:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.url>jdbc:h2:mem:testdb</db.url>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<db.url>jdbc:postgresql://db.example.com:5432/prod</db.url>
</properties>
</profile>
</profiles>
프로파일 활성화 방법:
# 명시적 활성화
mvn package -Pprod
# 환경 변수 기반 활성화
mvn package -Denv=prod
# settings.xml에서 기본 활성화
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
저장소 체계
| 유형 | 위치/특성 |
|---|---|
| Local | 개발 머신의 ~/.m2/repository |
| Central | Maven 커뮤니티 관리, https://repo.maven.apache.org |
| Remote | 조직 내부 또는 제3자 저장소 (Nexus, Artifactory 등) |
의존성 검색 순서: Local → Central → Remote 순으로 탐색하며, 미처지 못한 의존성은 상위 저장소에서 다운로드받습니다.
SNAPSHOT 버전 관리
개발 중인 모듈 간 연동 시 SNAPSHOT 접미사를 사용하면 매 빌드마다 최신 버전을 자동으로 가져옵니다:
<dependency>
<groupId>io.example.team</groupId>
<artifactId>order-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
강제 최신 다운로드를 위해서는 -U 플래그를 사용합니다: mvn clean package -U
외부 의존성 처리
중앙 저장소에 없는 JAR 파일은 system 범위로 지정합니다:
<dependency>
<groupId>com.legacy.lib</groupId>
<artifactId>proprietary-sdk</artifactId>
<version>3.5</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/proprietary-sdk-3.5.jar</systemPath>
</dependency>
Web 애플리케이션 빌드
웹 프로젝트 생성 명령:
mvn archetype:generate \
-DgroupId=io.example.portal \
-DartifactId=customer-portal \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false
생성된 구조:
- src/main/webapp/ - JSP, HTML, 정적 리소스
- src/main/webapp/WEB-INF/web.xml - 배포 서술자
- src/main/resources/ - 설정 파일
빌드 및 실행:
mvn clean package
# target/customer-portal.war 생성됨
의존성 전이 및 충돌 해결
Maven은 직접 선언하지 않은 전이 의존성도 자동으로 처리합니다. 충돌 발생 시 "가까운 거리의 첫 번째 선언" 원칙이 적용됩니다.
<!-- 전이 의존성 제외 -->
<dependency>
<groupId>io.example.framework</groupId>
<artifactId>web-framework</artifactId>
<version>2.0</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 선택적 의존성 선언 -->
<dependency>
<groupId>io.example.util</groupId>
<artifactId>advanced-cache</artifactId>
<version>1.2</version>
<optional>true</optional>
</dependency>
릴리스 자동화
maven-release-plugin을 활용한 배포 파이프라인:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<tagBase>https://svn.example.com/tags</tagBase>
<releaseProfiles>production</releaseProfiles>
</configuration>
</plugin>
릴리스 수행 절차:
# 1. 준비 (버전 확정, 태그 생성)
mvn release:prepare
# 2. 배포 (저장소 업로드)
mvn release:perform
# 문제 발생 시 롤백
mvn release:rollback
다중 모듈 프로젝트 구성
대규모 시스템은 모듈화하여 관리합니다:
<!-- 부모 POM -->
<groupId>io.example.platform</groupId>
<artifactId>platform-parent</artifactId>
<version>4.0.0</version>
<packaging>pom</packaging>
<modules>
<module>core-domain</module>
<module>api-gateway</module>
<module>notification-service</module>
<module>reporting-engine</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.example.platform</groupId>
<artifactId>core-domain</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
모듈 빌드 시 부모 디렉터리에서 일괄 실행:
mvn clean install -pl api-gateway -am
# -pl: 특정 모듈 지정
# -am: 해당 모듈의 의존 모듈 함께 빌드