Spring을 공부하면서 pom.xml을 알아보다가 Maven에 대한 글을 봤다.
1. Maven 이란?
Maven은 자바 프로젝트의 빌드(build)를 자동화 해주는 빌드 툴(build tool)
쉽게 말해서, 자바 소스를 compile하고 package해서 deploy하는 일을 자동화 해주는 것
- 여기서 compile이란?
A.java -> A.class로 만들어주는 것인데
build는 이런 컴파일들의 집합(확장)이다. 또는 사용할 준비가 된 시스템으로 만드는 프로세스 전체를 말한다.
- build의 과정
1. 해당 클래스를 컴파일하기 위해 필요한 클래스들(혹은 jar)을 확인하고 - dependency
2. 클래스패스를 잡아주고 - classpath
3. class 파일로 컴파일하면서 이 class 파일이 어디로 컴파일 되어 가는지 정해주고 - build path 등의 과정을 거친다.
위의 과정으로 소스를 build 한다.
이런 과정을 편하게 해주기 위해서 build tool이 존재하는데 예로 maven, ant 등이 있다.
빌드는 컴파일을 한 파일 또는 파일 그룹을 대상으로 행해진다. 컴파일의 산출물은 보통 실행파일이나 오브젝트 파일 또는 어떤 라이브러리가 될 수 있다.
때때로 배포를 위한 시스템을 준비하기 위해 빌드 이후에 다른 단계가 있기도 하다.
(베타 버전에는 흔히 빌들 번호가 노출이 된다. 빌드 번호라고 하지 컴파일 번호라고 하지 않는다.)
- 여기서 deploy란?
군대에서 병력을 배치하다 할 때의 배치를 뜻한다.
만들어진 프로그램을 서비스 위치로 보내는 작업이다.
2. Maven이 참조하는 설정 파일
두 개의 설정파일을 볼 수 있다.
1. settings.xml
settings.xml은 maven tool 자체에 관련된 설정을 담당한다.
MAVEN_HOME/conf/ 아래에 있다.(*MAVEN_HOME은 환경번수에 설정한 경로)
Maven 자체에 설정 값을 바꾸는 일은 잘 없으므로 일단 넘어간다.
2. pom.xml
하나의 자바 프로젝트에 빌드 툴로 maven을 설정했다면, 프로젝트 최상위 디렉토리에 'pom.xml'이라는 파일이 생성되었을 것이다.
pom.xml은 POM(Project Object Model)을 설정하는 부분으로 프로젝트 내 빌드 옵션을 설정하는 부분이다.
꼭 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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kr.co</groupId>
<artifactId>controller</artifactId>
<name>study</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<!-- 스프링 버전 수정 -->
<java-version>1.8</java-version>
<org.springframework-version>4.3.8.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<!-- 오라클 -->
<repositories>
<repository>
<id>oracle</id>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<!--
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
-->
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- <scope>test</scope>-->
</dependency>
<!-- spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
<!-- <scope>test</scope>-->
</dependency>
<!-- log4jdbc-log4j2-jdbc4 -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
<!-- org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- 첨부파일 START-->
<!-- MultipartHttpServletRequset -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<!-- 첨부파일 END -->
<!-- 트랜젝션 START -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<!-- 트랜젝션 END -->
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<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>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml은 <project>...</project>로 둘러싸여서 section별로 여러 정보를 나타내며 설정이 가능하다.
1) 프로젝트 정보
<modelVersion> : maven의 pom.xml의 모델 버전이다.
<groupId> : 프로젝트를 생성한 조직 또는 그룹명으로 보통, URL의 역순으로 지정한다.
<artifactId> : 프로젝트에서 생성되는 기본 아티팩트의 고유 이름, 메이븐에 의해 생성되는 일반적인 artifact는 <artifact>-<version>.<extention>이다.(ex) demo-0.0.1-SNAPSHOT.jar)
<version> : 애플리케이션의 버전, 접미사로 SNAPSHOT이 붙으면 아직 개발단계라는 의미이며, 메이븐에서 라이브러리를 관리하는 방식이 다르다고 한다.
<packaging> : jar, war, ear, pom 등 패키지 유형을 나타낸다.
<name> : 프로젝트 명
<description> : 프로젝트 설명
<url> : 프로젝트를 찾을 수 있는 URL
<properties> : pom.xml에서 중복해서 사용되는 설정(상수) 값들을 지정해놓는 부분, 다른 위치에서 ${...}로 표기해서 사용할 수 있다.(java.version에 1.8을 적용하고 다른 위치에서 $(java.version}이라고 쓰면 "1.8"이라고 쓴 것과 동일하다.
<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>
출처: https://jeong-pro.tistory.com/168 [기본기를 쌓는 정아마추어 코딩블로그]
<profiles> : 릴리즈할 때를 나눠야 할 필요가 있는 설정 값은 profiles로 설정할 수 있다.(dev, prod 이런 식으로 개발할 때)
maven goal 부분에 -P 옵션으로 프로파일을 선택할 수 있다. 예) mvn compile -P prod 라고 하면 ${java.version}은 1.9가 되는 것이다.
2) 의존성 라이브러리 정보
의존성 라이브러리 정보를 담을 수 있다.
최소한 groupId, artifactId, version 정보가 필요하다.
A라는 라이브러리를 사용하는데 B,C,D가 의존성을 가진다면 A를 dependency에 추가하면 자동으로 필요한 B,C,D도 가져온다.
dependency에 <scope>의 경우 compile, runtime, provided, test 등이 올 수 있다.
Maven Dependency의 Scope 개념
Index
goodgid.github.io
3) build 정보
build tool : maven의 핵심인 빌드와 관련된 정보를 설정할 수 있는 곳이다.
<build> 부분에서 설정할 수 있는 값들에 대해 설명하기 전에 '라이프 사이클(life-cycle)'에 대해서 알아볼거다.
- lie cycle이란?
객체의 생명주기처럼 maven에도 라이프 사이클이 존재한다.
라이프 사이클은 크게 default, clean, site 로 나누고 세부적으로 phase(페이즈)가 있다.
메이븐의 모든 기능은 플러그인(plugin)을 기반으로 동작한다.
플러그인에서 실행할 수 있는 각각의 작업을 골(goal)이라고 하고, 하나의 페이즈는 하나의 골과 연결되며, 하나의 플러그인에는 여러 개의 골이 있을 수 있다.
* 위의 그림들을 참고하여 maven의 라이프 사이클을 본다.
mvn process-resources : resources:resources의 실행으로 resource 디렉토리에 있는 내용을 target/classes로 복사
mvn compile : compiler:compile의 실행으로 src/jjava 밑의 모든 자바 소스를 컴파일해서 target/classes로 복사
mvn process-testResources, mvn test-compile : 위의 두 개가 src/java였다면 test/java의 내용을 target/test-classes로 복사 (참고로 test만 mvn test 명령을 내리면 라이프 사이클 상 원본 소스로 컴파일된다.)
mvn test : surefire:test의 실행으로 target/test-classes에 있는 테스트케이스의 단위테스트를 진행한다. 결과를 target/surefire-reports에 생성한다.
mvn package : target 디렉토리 하위에 jar, war, ear 등 패키지 파일을 생성하고, 이름은 <build>의 <finalName>의 값을 사용한다. 지정되지 않았을 때는 아까 설명한 'artifactId-version.extention' 이름으로 생성
mvn install : 로컬 저장소로 배포
mvn deploy : 원격 저장소로 배포
mvn clean : 빌드 과정에서 생긴 target 디렉토리 내용 삭제
mvn site : tartet/site에 문서 사이트 생성
mvn site-deploy : 문서 사이트를 서버로 배포
위의 진행 순서로 라이프 사이클이 진행된다.
- <build> 부분에서 설정할 수 있는 값
<finalName> : 빌드 결과물(ex .jar) 이름 설정
<resources> : 리소스(각종 설정 파일)의 위치를 지정할 수 있다.
- <resource> : 없으면 기본으로 'src/main/resources'
<testResources> : 테스트 리소스의 위치를 지정할 수 있다.
- <testResource> : 없으면 기본으로 'src/test/resources'
: 빌드할 때 접근할 저장소의 위치를 지정할 수 있다. 기본적으로 메이븐 중앙 저장소인 http://repo1.maven.org/maven2로 지정되어 있다.
<outputDirectory> : 컴파일한 결과물 위치 값 지정, 기본 'target/classes'
<testOutputDirectory> : 테스트 소스를 컴파일한 결과물 위치 값 지정, 기본 'target/test-classes'
<plugin> : 어떠한 액션 하나를 담당하는 것으로 가장 중요하지만 들어가는 옵션은 제 각각이다. 다행인 것은 플러그인 형식에 대한 것은 안내가 나와있으니 그것을 참고해서 작성하면 된다.
plugin이 작성되어 있다고 무조건 실행되는 것은 아니다. 명확한 것은 아니지만 따로 실행할 플러그인을 메이븐 명령어로 실행해야 하는 것으로 알고 있다.
- <executions> : 플러그인 goal과 관련된 실행에 대한 설정
- <configuration> : 플러그인에서 필요한 설정 값 지정
4) 배포
<project>
...
<distributionManagement>
<site>
<id>website</id>
<url>scp://www.mycompany.com/www/docs/project/</url>
</site>
</distributionManagement>
...
</project>
출처: https://jeong-pro.tistory.com/168 [기본기를 쌓는 정아마추어 코딩블로그]
사이트로 배포할 때 위와 같이 설정할 수도 있다.
'Blog > Build Tool' 카테고리의 다른 글
Build Tool (0) | 2020.04.09 |
---|