01. 메이븐 (Maven) - 정리
OS | Windows 10 PRO 64bit 버전 20H2 (OS 빌드 19042.867) |
Maven | 4.0.0 |
공식 홈페이지 주소
읽기전
Maven 은 Apache Ant 의 대안으로 만들어졌다
(Ant는 많은 스크립트 작성과 라이브러리 의존관리가 되지 않아 불편했기 때문)
초기의 java 빌드도구로 Ant 를 많이 사용하였으나 최근 많은 빌드도구들이 생겨나 Maven 이 많이 쓰였고,
현재는 Gradle 이 많이 쓰인다
라이프 사이클
Clean | 빌드 시 생성되었던 파일들 삭제하는 단계 (target 폴더 삭제) |
Validate | 프로젝트가 올바른지 확인하고 필요한 모든 정보를 사용할 수 있는 지 확인하는 단계 |
Compile | 프로젝트의 소스 코드를 컴파일 하는 단계 |
Test | 유닛(단위) 테스트를 수행 하는 단계 (테스트 실패시 빌드 실패로 처리, 스킵 가능) |
Package | 실제 컴파일된 소스 코드와 리소스들을 jar, war 등등의 파일 등의 배포를 위한 패키지로 만드는 단계 |
Verify | 통합 테스트 결과에 대한 검사를 실행하여 품질 기준을 충족하는지 확인하는 단계 |
Install | 패키지를 로컬 저장소에 설치하는 단계 ( compile + package ) |
Site | 프로젝트 문서와 사이트 작성, 생성하는 단계 |
Deploy | 만들어진 package 를 원격 저장소에 release 하는 단계 |
- 빌드 시 생성되었던 산출물을 삭제
- pre-clean : clean 작업 전에 사전작업
- clean : 이전 빌드에서 생성된 모든 파일 삭제
- post-clean : 사후작업
- default : 프로젝트 배포절차, 패키지 타입별로 다르게 정의됌
- validate : 프로젝트 상태 점검, 빌드에 필요한 정보 존재유무 체크
- initialize : 빌드 상태를 초기화, 속성 설정, 작업 디렉터리 생성
- generate-sources : 컴파일에 필요한 소스 생성
- process-sources : 소스코드를 처리
- generate-resources : 패키지에 포함될 자원 생성
- compile : 프로젝트의 소스코드를 컴파일
- process-classes : 컴파일 후 후처리
- generate-test-source : 테스트를 위한 소스 코드를 생성
- process-test-source : 테스트 소스코드를 처리
- generate-test-resources : 테스팅을 위한 자원 생성
- process-test-resources : 테스트 대상 디렉터리에 자원을 복사하고 가공
- test-compile : 테스트 코드를 컴파일
- process-test-classes : 컴파일 후 후처리
- test : 단위 테스트 프레임워크를 이용해 테스트 수행
- prepare-package : 패키지 생성 전 사전작업
- package : 개발자가 선택한 war, jar 등의 패키징 수행
- pre-integration-test : 통합테스팅 전 사전작업
- integration-test : 통합테스트
- post-integration : 통합테스팅 후 사후작업
- verify : 패키지가 품질 기준에 적합한지 검사
- install : 패키지를 로컬 저장소에 설치
- deploy : 패키지를 원격 저장소에 배포
- site : 프로젝트 문서화 절차
- pre-site : 사전작업
- site : 사이트문서 생성
- post-site : 사후작업 및 배포 전 사전작업
- site-deploy : 생성된 문서를 웹 서버에 배포
최종 빌드 순서
compile > test > package
- compile : src/main/java 디렉토리 아래의 모든 소스 코드가 컴파일
- src/test/java, src/test/resources 테스트 자원 복사 및 테스트 소스 코드 컴파일
- junit: 단위 테스트 프레임워크, 테스트 단계를 거치기 위해 의존 설정을 해준다
- packaging: 컴파일과 테스트가 완료된 후, jar, war 같은 형태로 압축하는 작업
페이즈(Phase) = 단계
- Build Lifecycle 의 각각의 단계를 Phase 라고 한다 (pre-integratuin-test, install ... 등)
- Phase는 의존관계를 가지고 있어 해당 Phase 가 수행되려면 이전 단계의 Phase가 모두 수행되어야 한다
- 즉, 모든 빌드단계는 이전 단계가 성공적으로 실행되었을 때 실행된다는 것이 Dependency 이다
골(Goal) = 실행
- 특정 작업, 최소한의 실행 단위(task)
- 하나의 플러그인에서는 여러 작업을 수행할 수 있도록 지원하며, 플러그인에서 실행할 수 있는 각각의 기능(명령)을 Goal이라고 한다
POM (Project Object Model)
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!--POM model의 버전-->
<parent> <!--프로젝트의 계층 정보-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.god</groupId> <!--프로젝트를 생성하는 조직의 고유 아이디를 결정한다. 일반적으로 도메인 이름을 거꾸로 적는다.-->
<artifactId>bo
</artifactId> <!--프로젝트 빌드시 파일 대표이름 이다. groupId 내에서 유일해야 한다.Maven을 이용하여 빌드시 다음과 같은 규칙으로 파일이 생성 된다. artifactid-version.packaging. 위 예의 경우 빌드할 경우 bo-0.0.1-SNAPSHOT.war 파일이 생성된다.-->
<version>0.0.1-SNAPSHOT</version> <!--프로젝트의 현재 버전, 프로젝트 개발 중일 때는 SNAPSHOT을 접미사로 사용-->
<packaging>war</packaging> <!--패키징 유형(jar, war, ear 등)-->
<name>bo</name> <!--프로젝트, 프로젝트 이름-->
<description>Demo project for Spring Boot</description> <!--프로젝트에 대한 간략한 설명-->
<url>http://goddaehee.tistory.com</url> <!--프로젝트에 대한 참고 Reference 사이트-->
<properties> <!-- 버전관리시 용이 하다. ex) 하당 자바 버전을 선언 하고 dependencies에서 다음과 같이 활용 가능 하다. <version>${java.version}</version> -->
<java.version>1.8</java.version>
</properties>
<dependencies> <!--dependencies태그 안에는 프로젝트와 의존 관계에 있는 라이브러리들을 관리 한다.-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build> <!--빌드에 사용할 플러그인 목록-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
modelVersion | POM model 의 버전 |
parent | 프로젝트의 계층 정보 |
groupId | 프로젝트를 생성하는 조직의 고유 아이디 일반적으로 도메인 이름을 거꾸로 적는다 예시) naver.com -> com.naver |
artifactId | 프로젝트 빌드 시 파일 대표 이름. groupId 내에서 유일해야 한다 Maven 을 이용하여 빌드 시 다음과 같은 규칙으로 생성 artifactid-version.packaging 위 예의 경우 빌드 할 경우 bo-0.0.1-SNAPSHOT.war 파일 생성 |
version | 프로젝트의 현재 버전, 프로젝트 개발 중 일 때는 SNAPSHOT 을 접미사로 사용 |
packaging | 패키징 유형 (jar, war, ear 등) jar = java 실행 war = tomcat 실행 |
name | 프로젝트, 프로젝트 이름 |
description | 프로젝트에 대한 간략한 설명 |
url | 프로젝트에 대한 참고 Reference 사이트 |
properties | 버전관리시 용이하다 예시) 동일한 버전을 중복으로 계속 적는 경우 (spring mvc, spring context, spring jpa ... 등) |
dependencies | 라이브러리들을 관리한다 |
build | 빌드에 사용할 플러그인 목록 |
TIP
기본적으로 <groupId>.<artifactId> 패키지에 파일을 생성한다
위 예시에서는 com.god.bo 위치에 clsss 가 생성된다
scope
compile | default scope <scope></scope> 를 작성하지 않아도 기본값 모든 상황에서 포함됨 |
provided | compile 과 유사하게 모든 상황에서 수행됨 하지만, 다른 외부 컨테이너에서 기본 제공되는 API 인 경우 provided 를 지정 시 마지막 패키징 할 때 포함되지 않음 예를들어 tomcat 에서 기본적으로 servlet api 를 제공하기 때문에 servlet api 를 provided 로 지정하면 패키징시 제외한다 |
runtime | 컴파일 시에는 불필요하고, 실행 시 필요한 경우 런타임 및 테스트 시 classpath 에 추가 되지만, 컴파일시에는 추가되지 않음 |
test | 테스트 시 에만 사용 |
system | provided 와 유사 system 의 특정 path 를 참조하도록 지정 Maven central repository 를 사용하지 않음 |
import | scope 는 dependencyManagement 섹션에서 pom 의 의존관계에 대해 사용 |
플러그인
Compile Plugin
- 기본적으로 maven 은 jdk 1.5 기준으로 compile 을 시도한다
- 1.5 버전 보다 더 높은 버전으로 compile 하기 위해서는 다음과 같은 조치가 필요하다
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
Jar Plugin
jar 패키징된 파일을 실행하기 위해서 ManifestFile 을 생성해주는 plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Source Plugin
- package 시에 Source 코드를 포함한다
- 아래의 코드를 추가하면 package 수행 및 install 수행 시 기본jar명-sources.jar 파일이 추가로 하나 생성된다
- 내부에 <goal> 설정은 plugin 별로 고유의 goal 이 있다
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-resources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
spring boot plugin
- jar 파일에서 spring boot 를 실행 시킬 수 있게 해주는 플러그인
- execution 는 maven lifecycle pre intergration 에서 spring boot 를 start 하고, post intergration test 에서 stop 하기 위함 (빌드 테스트 과정이라고 생각하면 된다)
- lombok 은 제외시킴
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre integration test</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post integration test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
resource plugin
- 원하는 파일을 원하는 위치에 복사할 수 있다
- 주로 compile 될 때 생성되는 target/classes 에 복사할 때 사용한다
- jar 파일 또는 war 로 파일로 묶이기 전에 파일을 복사해주어야 하기 때문에 `prepare-package` phase 단계에서 진행
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy front-end template</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<outputDirectory>${basedir}/src/main/resources/templates</outputDirectory>
<resources>
<resource>
<directory>${basedir}/../frontend/dist</directory>
<includes>
<include>index.html</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
위의 예시는 vue 에서 build 된 dist 폴더에서 spring/resource 폴더로 복사하는 예시이다
예시로 1개 보여줬지만 target/classes 에도 복사를 해주어야 한다
exec plugin
- 외부 프로그램을 실행 하거나 현재 VM 에 있는 메인 클래스 실행할 때 사용
<executions> | 실행 목록들 |
<execution> | 실행 설정 |
<id> | id (중복불가) |
<goal> | exec (외부프로그램 실행) help (exec 플러그인 도움말 보기) java (현재 VM 에 있는 메인 클래스 실행) |
<phase> | 해당 페이즈 단계에서 실행 |
<plugin.configuration> | workingDirectory : 해당 명령을 실행할 위치를 설정 |
<execution.configuration> | executable : 실행할 파일명 argument : 실행 파일에 넘겨줄 인자 설정 |
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>front-end install</id>
<goals>
<goal>exec</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
</executions>
<configuration>
<workingDirectory>${basedir}/../frontend</workingDirectory>
</configuration>
</plugin>
위 예시는 pom.xml/../frontend 폴더에서 npm install 명령 실행하라는 의미이다
execution 순서는 맨 위에 있는 executuin 이 먼저 실행 된다 (순서 유의)
참고 블로그