Maven 정리하기

Tina Jeong·2020년 8월 17일
1

Maven이 뭐야?

🤷‍♀️: 메이븐이 뭐야?
나: 그거..라이브러리 관리해주는 빌드 툴이야 (자세히 설명하려면 버퍼링 걸림)

Maven이 뭐냐고 물어봤을 때, 하나하나 정돈된 언어로 설명하고 싶어 이 포스팅을 적는다.

Maven에 대한 처음 인식

유명한 빌드 툴에는 Ant, Maven, Gradle이 있다.

Ant는 몇번 안 써봤고, 처음 써본 게 Database 과제 때.
제출 형식이 jar 파일이었고, 빌드 툴이 뭔지도 모르는 우리에게 교수님께서 Ant를 말씀해주셨기 때문이었다. 다행히 Ant를 꽤 하는 랩실 선배2017년에 Ant를 써본 학부생이란..그는 도덕책의 도움을 받아 약간의 삽질과 함께 숙제를 제출할 수 있었다. 빌드 과정에 이것 저것 세팅하는 것이 귀찮았던 기억이 난다.

그 이후로 딱히 빌드 툴을 쓸 일이 없다가 Gradle을 만났다. Gradle은 build.gradle 파일이 groovy로 되어 있어 의존성 부분을 비롯해 가독성도 좋고, 명령어 몇번이면 jar,war 파일 등을 생성할 수 있어 편리했다. 빌드 속도도 만족스러웠다.

그 다음 간단한 웹 프로젝트를 만들면서 Maven을 써봤다. groovy를 보다가 xml을 보니 가독성이 살짝 떨어졌고, Gradle이 Maven보다 빌드 스피드가 최대 100배 빠르다고는 했다. 그치만 의존성 관리와 빌드를 편리하게 할 수 있다는 장점은 여전히 가지고 있었다.

결론적으로 내가 가진 Maven에 대한 처음 인식은 "Gradle 보단 조금 떨어지지만 꽤 괜찮은 빌드 툴"이었다.

Maven

Maven은 SW 프로젝트 관리 기능을 가진 빌드 툴이다. Ant은 configuration 중심으로 빌드에 충실한 툴이라면, Maven은 '프로젝트 관리'에 방점이 찍힌다. 공식문서에는 프로젝트 관련 사항을 모두 아우르는 one-stop-shop이라고 했다.

POM

POM은 Project Object Model의 약자이며, pom.xml으로 표현된다.
프로젝트 관리의 핵심적인 요소라고 할 수 있는 pom.xml에는 여러가지 요소가 포함된다.

프로젝트 기본 정보

요소설명
<modelVersion>4.0.0</modelVersion>pom.xml 파일 양식의 버전 정보이며, 5.0.0은 아직 나오지 않았다.
<groupId>com.회사이름</groupId>다른 프로젝트들과 구별되는 유니크한 패키지 이름. 관례적으로 범위가 큰 것에서 작은 것 순으로 기술한다. ex) com.naver, org.apache
<artifactId>모듈이름</artifactId>프로젝트에서 생성되는 jar, war 파일 등의 이름을 의미한다.
<version>artifact의 버전</version>프로젝트에서 생성되는 artifact의 버전을 의미하며, default로 명명된 0.0.1-SNAPSHOT은 아직 개발 중이라는 뜻이다.
<packaging>artfact의 포맷</packaging>프로젝트에서 생성되는 artifact의 파일 포맷을 의미한다. ex) jar, war
<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>org.codehaus.mojo</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
</project> 

프로퍼티

<properties>...</properties>프로퍼티는 값을 가진 constant라고 생각하면 편하다. property에 명시된 값들은 pom.xml 파일 내부에서 ${propertyname}의 형태로 참조할 수 있다.
<properties>
      <java-version>1.8</java-version>
</properties>
...중략...
<source>${java-version}</source>
<target>${java-version}</target>

의존성

의존성은 POM에서 가장 중요한 요소이다. 일관성있는 프로젝트 관리가 가능해지기 때문이다.
Maven은 dependencies 요소에 명시된 의존성을 가져와주고(자동으로 다운로드), 해당 의존성이 의존하는 또다른 의존성까지(transitive dependencies) 가져와 주기 때문이다. 외부 라이브러리 jar 파일을 일일이 다운로드 받아 관리하던 것에서 아주 개선된 방식이다.

<dependencies>...</dependencies>dependency 상위 태그. dependency list.
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
</dependencies>

빌드

<build>...</build>프로젝트 빌드에 사용될 여러가지 정보들

참고로 java 9 버전 이상의 프로젝트에서는 maven-compiler-plugin 버전 3.6.0 이상을 사용해야 한다.

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>${java-version}</source>
                        <target>${java-version}</target>
                        <showWarnings>true</showWarnings>
                        <showDeprecation>true</showDeprecation>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

Maven Phases and Goals

Maven phase를 나열하면 다음과 같다. phase는 goal과 일대일 매핑되며, goal은 메이븐에서 실행되는 작업 단위이다.
validation -> compile -> test -> package -> integration test -> verify -> install -> deploy

핵심적이고 자주 사용되는 goal들에 대한 설명이다. mvn goalname의 형태로 실행한다.

Goal설명
compile프로젝트 소스 코드를 컴파일 한다.
testJUnit 같은 테스트 프레임워크로 코드를 테스트 한다.
packageJar 등의 distributable한 포맷으로 패키징한다.
install로컬 레포에 package를 설치한다.
deploy원격 레포에 package를 설치한다.(POM에 추가적인 설정이 필요하다.)
clean생성된 artifact를 삭제한다. (target 디렉토리)

Maven Project 구조

maven 프로젝트를 생성하면 자동으로 다음과 같은 구조로 디렉토리가 생성된다.
(정석적으로,관례적으로) src와 test로 분리된 구조이다.

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- HelloMaven.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- HelloMavenTest.java

간단하게 Maven goal 실행하기

클래스에 코드를 작성

public class HelloMaven {

    public static void main(String[] args) {
        System.out.println("Hello, Maven!");
    }
}

$ mvn compile

$ mvn compile
[INFO] Scanning for projects...
[INFO][INFO] -------------------------< app:hellomaven >-------------------------
[INFO] Building hellomaven 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO][INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hellomaven ---
[WARNING] Using platform encoding (MS949 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO][INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hellomaven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding MS949, i.e. build is platform dependent!
[INFO] Compiling 1 source file to \hellomaven\target\classes
[WARNING] bootstrap class path not set in conjunction with -source 8
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.600 s
[INFO] Finished at:
[INFO] ------------------------------------------------------------------------

$ mvn package

테스트 코드는 작성하지 않았으므로 테스트는 실행되지 않는다.

$ mvn package
[INFO] Scanning for projects...
[INFO][INFO] -------------------------< app:hellomaven >-------------------------
[INFO] Building hellomaven 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO][INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hellomaven ---
[WARNING] Using platform encoding (MS949 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO][INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hellomaven ---
[INFO] Nothing to compile - all classes are up to date
[INFO][INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hellomaven ---
[WARNING] Using platform encoding (MS949 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory \hellomaven\src\test\resources
[INFO][INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ hellomaven ---
[INFO] Nothing to compile - all classes are up to date
[INFO][INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hellomaven ---
[INFO] No tests to run.
[INFO][INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hellomaven ---
[INFO] Building jar: \hellomaven\target\hellomaven-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.562 s
[INFO] Finished at:
[INFO] ------------------------------------------------------------------------

$ java -cp target\hellomaven-1.0-SNAPSHOT.jar app.HelloMaven

Hello, Maven!

예상한 결과가 뜬다.

참고

https://maven.apache.org/
https://wikidocs.net/17298
https://gradle.org/gradle-vs-maven-performance/

profile
Keep exploring, 계속 탐색하세요.

2개의 댓글

comment-user-thumbnail
2020년 8월 18일

선생님의 포스팅을 읽고 메이븐 버퍼링에서 벗어날 수 있었습니다.

1개의 답글