Maven
Maven
자바 프로젝트의 빌드(build)를 자동화 해주는 빌드 툴이자 프로젝트의 전체적인 라이프 사이클을 관리하는 도구다.
기존에는 Ant가 많이 사용되었지만 Maven이 Ant를 넘어서 더 많은 개발자들이 사용하게 되었다.
Maven의 특징
1. 필요한 라이브러리를 특정 문서(pom.xml)에 정의해 놓으면 내가 사용할 라이브러리 뿐만 아니라
해당 라이브러리가 작동하는데에 필요한 다른 라이브러리들까지 관리하여 네트워크를 통해서 자동으로 다운받아 준다.
2. 라이브러리를 공유하는 파일 서버라고 볼 수 있는 중앙 저장소(아파치재단에서 운영 관리)를 통해 자동으로 의존성을 관리한다.
3. 하지만 라이브러리가 서로 종속적일 경우 복잡한 XML 구조를 갖게 된다.
4. XML 구조로 인해 계층적인 데이터를 표현하기에는 좋지만, 플로우나 조건부 상황을 표한하기에는 어렵다.
Maven이 참조하는 설정 파일
프로그래밍에 직접적인 연관이 있는 두개의 설정파일을 알아보자.
settings.xml
1. settings.xml은 maven tool 자체에 관련된 설정을 담당한다.
2. MAVEN_HOME/conf/ 아래에 있다. ( * MAVEN_HOME은 환경변수에 설정한 경로)
메이븐을 빌드할 때 의존 관계에 있는 라이브러리, 플러그인을 중앙 저장소에서 개발자 PC로 다운로드 하는위치(로컬저장소)의
기본 설정은 'USER_HOME/.m2/repository' 인데 settings.xml의 에 원하는 로컬 저장소의 경로를 지정, 변경할 수 있다.
pom.xml
1. 하나의 자바 프로젝트에 빌드 툴로 maven을 설정했다면, 프로젝트 최상위 디렉토리에 "pom.xml"이라는 파일이 생성되었을 것이다.
2. pom.xml은 POM(Project Object Model)을 설정하는 부분으로 프로젝트 내 빌드 옵션을 설정하는 부분이다.
3. 꼭 pom.xml이라는 이름을 가진 파일이 아니라 다른 파일로 지정할 수도 있다. (mvn -f ooo.xml test)
그러나 maven의 원칙(습관에 의한 편의성?)으로 다른 개발자들이 헷갈릴 수 있으므로 그냥 pom.xml으로 쓰기를 권장한다.
pom.xml 분석
<?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>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev</id>
<properties>
<java.version>1.8</java.version>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<java.version>1.9</java.version>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
</project>
Spring boot에서 프로젝트를 생성했을 때 나오는 pom.xml의 내용이다.
pom.xml은 <project>...</project>로 둘러싸여서 section별로 여러 정보를 나타내며 설정할 수 있다.
프로젝트 정보
- modelVersion : maven의 pom.xml의 모델 형식 버전
- groupId : 프로젝트를 생성한 조직 또는 그룹명으로 보통, URL의 역순으로 지정
- artifactId : 프로젝트에서 생성되는 기본 아티팩트의 고유 이름
- version : 애플리케이션의 버전. 접미사로 SNAPSHOT이 붙으면 아직 개발단계라는 의미이며, 메이븐에서 라이브러리를 관리하는 방식이 다르다고 한다.
- packaging : jar, war, ear, pom등 패키지 유형을 나타낸다.
- name : 프로젝트 명
- description : 프로젝트 설명
- url : 프로젝트를 찾을 수 있는 URL
parent
super pom.xml이라는 것이 있는데 모든 pom.xml이 기본적으로 상속하고 있는 부모 설정파일로
이것 때문에 기본으로 생성된 pom.xml에 별 내용이 없어도 잘 처리한다.
물론 생성된 pom.xml에서 설정 값을 오버라이드하면 super pom.xml 내용을 변경할 수 있다.
스프링부트의 경우 부모 pom.xml에 자주 사용하는 라이브러리들의 버전정보나 dependency들을 이미 가지고 있어서 참조하기 편리하다.
properties
pom.xml에서 중복해서 사용되는 설정(상수) 값들을 지정해놓는 부분이다.
다른 위치에서 ${...}로 표기해서 사용할 수 있다. (java.version에 1.8을 적용하고 다른 위치에서 ${java.version}이라고 쓰면 "1.8"이라고 쓴 것과 같다.
profiles
dev, prod 이런식으로 개발할 때, 릴리즈할 때를 나눠야할 필요가 있는 설정 값은 profiles로 설정할 수 있다.
maven goal 부분에 -P 옵션으로 프로파일을 선택할 수 있고 예를 들어 mvn compile -P prod 라고 하면 ${java.version}은 1.9가 된다
dependencies
<dependencies> 에 의존성 라이브러리 정보를 적을 수 있는데 최소한 groupId, artifactId, version 정보가 필요하다.
스프링부트의 spring-boot-starter같은 경우에는 부모 pom.xml에서 이미 버전정보가 있어서 version은 따로 지정할 필요가 없다.
특히 스프링부트는 해당 스프링버전에 잘 맞는 버전으로 이미 설정되어 있기 때문에 오버라이드해서 문제가 생기는 부분은 순전히 개발자 탓이다.
dependency에 <scope>의 경우 compile, runtime, provided, test등이 올 수 있는데
해당 라이브러리가 언제 필요한지, 언제 제외되는지, 적용될 범위를 나타내는 것이다.
그리고 A라는 라이브러리를 사용하는데 B,C,D가 의존성을 가진다면 A를 dependency에 추가하면 자동으로 필요한 B,C,D도 가져온다.
scope
- compile (default) : 기본 설정값으로, 모든 클래스 경로에서 이용할 수 있고 컴파일 및 배포 시 같이 제공된다. 해당 프로젝트에 종속된 다른 프로젝트에도 적용될 수 있다.
- provided : compile과 유사하나, JDK 혹은 컨테이너가 런타임 시에만 해당 라이브러리를 제공한다. 컴파일 혹은 테스트 경로에서만 사용할 수 있으며, 배포시에는 빠진다.
- runtime : 컴파일 시에는 사용되지 않고, 실행될 때만 사용된다. 런타임과 테스트 경로에서는 있지만 컴파일 클래스 경로에는 존재하지 않는다.
- test : 테스트시에만 사용된다. 테스트 컴파일과 테스트 실행 단계에서만 사용하며 종속된 다른 프로젝트에 영향을 미치지 않는다.
- system : provided와 유사하나, 저장소에서 관리되지 않고 직접 관리하는 JAR를 추가한다. 해당 범위에 있는 라이브러리는 artifact 단위에서는 항상 사용할 수 있으나 repository는 존재하지 않는다. 해당 범위를 사용하는 경우에는 dependency 설정에 systemPath를 추가해서 작성해야 한다.
- optional : 이 프로젝트가 다른 프로젝트에 의존성을 가진 경우에 사용할지 여부인데, A라는 프로젝트에서 B라는 프로젝트를 참조하여 사용한다고 했을 때 B에서 의존성으로 포함한 dependency를 optional true로 설정하면 A 프로젝트에서는 해당 dependency를 참조할 수 없다.
repository
의존성을 다운로드 받을 위치의 repository 주소이다.
기술되지 않을 시 기본적인 위치로 http://repo.maven.apache.org/maven2 가 지정된다.
다수의 <repository> 기술이 가능하고 회사 내부의 repository(nexus, artifactory)를 기술 하기도 한다.
build
빌드에서 사용할 플러그인과 sourceDirectory, outputDirectory, resource 경로 설정, 빌드 결과물 이름 설정등을 설정할 수 있다.
Maven의 Lifecycle
Maven에서는 clean, build(default), site의 세 가지 Lifecycle을 제공하고 있다.
Lifecycle의 각각의 빌드 단계를 Phase라하고 단계들의 순서를 Lifecycle이라고 한다.
각각의 Phase는 의존관계를 가지고있어 해당 Phase가 수행되려면 이전 단계의 Phase가 모두 수행되어야 한다.
- mvn clean : 이전 빌드에서 생성된 target 디렉토리 내용 삭제
- mvn process-resources : resources:resources의 실행으로 resource 디렉토리에 있는 내용을 target/classes로 복사한다.
- mvn process-testResources, mvn test-compile : 이것은 위의 두 개가 src/java였다면 test/java의 내용을 target/test-classes로 복사. (참고로 test만 mvn test 명령을 내리면 라이프사이클상 원본 소스로 컴파일된다.)
- mvn validate : 프로젝트가 올바른지 확인학고 필요한 모든 정보를 사용할 수 있는 지 확인하는 단계
- mvn compile : compiler:compile의 실행으로 src/java 밑의 모든 자바 소스를 컴파일해서 target/classes로 복사
- mvn test : surefire:test의 실행으로 target/test-classes에 있는 테스트케이스의 단위테스트를 진행하고 결과를 target/surefire-reports에 생성한다.
- mvn package : 배포를 위해 target 디렉토리 하위에 실제 컴파일된 소스 코드와 리소스들을 jar, war, ear등의 패키지로 만드는 단계
- mvn verify : 통합테스트 결과에 대한 검사를 실행하여 품질 기준을 충족하는지 확인하는 단계
- mvn install : 패키지를 로컬 저장소에 설치하는 단계
- mvn site : target/site에 문서 사이트 생성
- mvn deploy : 만들어진 Package를 원격 저장소에 release하는 단계
- mvn site-deploy : 문서 사이트를 서버로 배포
위의 라이프사이클 말고도 더 많은종류의 라이프사이클이 존재하고 각 단계를 모두 수행하는 것이 아니라
원하는 단계까지만 수행할 수도 있으며 test단계는 큰 프로젝트의 경우에 몇시간이 소요될 수도있으니
수행하지 않도록 스킵이 가능하다.
Phase와 Goal
메이븐에서 제공되는 모든 기능은 플러그인 기반으로 동작하는데 각각의 Phase는 어떤 일을 할지 정의하지 않고 어떤 플러그인의 Goal을 실행할지 설정한다.
플러그인에서 실행할 수 있는 각각의 작업을 골(goal)이라하고 Maven에서 기본으로 제공하는 Phase를 실행하면 해당 Phase와 연결된 플러그인의 Goal이 실행된다.
각 phase는 0개 이상의 goal과 바인드 되어 있으며, 대부분 0또는 1개 이상의 Goal이 바인드 되어 있다.
Comments