본문 바로가기

Computer/JAVA

Maven

1. Maven 이란?

    Apache 재단에서 만든 프로젝트 관리도구이다.

    그러나 쉽게 말해 의존성 관리등이 포함된 빌드도구이다.

 

    의존성이란?

        하나의 클래스를 구현함에 있어 다른 클래스를 직접참조하는 경우 참조하는 클래스에 의존한다고 할 수 있다.

        즉 만들고 싶은게 있는데 그것이 없으면 못 만들때 그것의존하고 있는 것이다.

 

     빌드란?

         소스코드를 컴파일 단계를 포함하여 하나의 생산품으로 만들어 주는 것을 빌드라 한다.

 

     필요성

          자바는 컴파일러(javac)와 실행환경(java)을 배포했다. 

          이것을 순수하게 콘솔(명령창)에서 작업을 하려면 컴파일과 실행을 위해
          수많은 클래스를 Class Path에 설정해야 하는 불편함이 있었다. 

 

          이때 등장한것이 순수한 빌드도구인 Ant였다.

          JAVA는 오픈소스이다보니 수많은 라이브러리들이 등장하게 되었다.
          이것이 장점이기도 했지만 관련 라이브러리를 찾고 버전을 관리하는 것도 일이 되어버렸다.

          Ant는 컴파일과 빌드에 유용했지만 관련 라이브러리를 찾고 버전을 관리하는것에는 기능이 약했다.
          (이후 Ivy가 등장하기 전까지......)

 

          Apache 에서는 이런 문제점을 해소하고 보다 체계적으로 프로젝트를 관리하기 위해서 Maven을 만들었다.

 

            예전에는 라이브러리가 필요하면 관련 라이브러리 사이트에서 해당 jar파일을 링크를 통해서 다운로드를 받았다.

            그러나 요즘 최신 라이브러리들은 파일을 다운로드로 제공하지 않고 Maven 설정만 제공하는 경우가 많이 생겼다.

            어쩔수 없이 해당 라이브러리를 받으려면 Maven을 사용해야하는 상황이 발생한 것이다.("버틸 수가 없다!!!")

 

            Maven은 설정을 통해서 의존성을 인지하고 Maven저장소(Repository)로 부터 관련 라이브러리들을 제공한다.

 

2. Maven의 설치

 

    Maven의 설치에 필요한 사항

        

        JDK : Maven은 Java프로젝트를 관리하기 위한 도구이기 때문에 JDK가 먼저 설치 되어 있어야 한다.

               2018년 현재 Maven 3.3 이상은 JDK 1.7 이상에서 동작한다고 한다.

               (그러나 JDK 1.3 혹은 다른 버전도 아직 지원한다고 써있기는 하다.)

 

        Disk : 설치에만 10MB 공간과 추가적으로 Maven repository(메이븐 저장소)를 위해서 최소 500MB 공간이 필요하다.

 

    Maven 설치

 

        1. Maven은 Apache 사이트에서 다운로드 받을 수 있다.(http://maven.apache.org/download.cgi)

        2. 다운 받은 Maven을 원하는 위치에 설치(압축을 해제하는 것 만으로 설치 할 수 있다.)한다.

        3. 먼저 JDK가 Path에 지정이 되어있고 Maven이 설치된(bin 아래 실행파일이 있는 경로)경로를 Path에 지정한다.

           (JDK를 예전에 JAVA_HOME 이라고 등록하여 Path에 지정했듯이 

            오래된 문서에 Maven은 M2_HOME이라고 등록하여 Path에 지정하기도 한다.)

        4. 설치가 완료되었으면 정상적으로 설치 되었는지 확인 하기 위해 콘솔창에 버전을 확인하는 명령을 입력해서 본다.

            >mvn -version

  

    Maven 설정

        설치된 Maven은 기본설정외에 별도로 환경을 수정할 수 있으나 이는 개별 저장소 운영이나 신규 아키타입 설정등이 필요한 단계에서
        사용하므로 좀더 심화된 자료를 참고하시기 바란다.

       

 

3. 아키타입과 POM

 

    아키타입(archetype)

    

        Maven은 아키타입 이라는 기능을 제공하는데 이는 Eclipse에서 Wizard를 이용해서 Project를 생성하는 것과
        같은 기능이다.
        

        Maven에서는 미리 정의된 많은 아키타입들을 제공함은 물론 자신만의 아키타입을 생성할 수 있다.
        (아키타입에 대해서는 기회가 된다면 나중에 더 자세하게 다뤄보기로 한다.)

        

    POM(Project Object Model)

 

         Maven은 pom.xml을 가지는데 POM의 약어가 나타내듯이 Project 전반에 관한 설정이 담겨진 파일이다.

         이 pom.xml을 이용해서 project의 의존성을 관리하고 테스트, 컴파일등 전반적인 프로젝트를 관리 한다.

         이 파일은 Ant의 build.xml이나 Eclipse의 .project, .classpath 파일 등과 유사한 기능을 한다.

 

4. 프로젝트 디렉터리 구조

 

    Maven을 이용해서 개발할 경우 다음과 같은 디렉터리 구조를 가지게 된다.

 

   +- src

   |    +- main

   |    |     +- java

   |    |     +- resources

   |    |     +- webapp

   |    |             +- WEB-INF

   |    +- test

   |           +- java

   |           +- resources

   +- target

   +- pom.xml

 

    /src : 소스와 관련된 root 디렉터리

    /src/main :  소스 디렉터리

    /src/main/java : java 소스 디렉터리

    /src/main/resources : xml, properties 등 각종 설정 파일 디렉터리

    /src/main/webapp : web context root

    /src/test : 테스트 소스 디렉터리

    /src/test/java : 테스트 java 소스 디렉터리

    /src/test/resources : 테스트 xml, properties 등 설정파일 디렉터리

    /target : 빌드 결과물 디렉터리(처음에는 없다가 빌드 이후 자동생성됨)

    /pom.xml : maven 프로젝트 설정파일

 

    * maven의 디렉터리 구조는 임의로 구성된 것이 아니고 JEE 가이드에 맞춰서 구성되었다.

    

 

 

5. POM의 구조

 

    pom.xml은 기본정보, 프로퍼티, 의존성, 저장소, 빌드, 프로파일 형태로 구성되어 있다.

 

    <project>

        <!-- 기본정보: 프로젝트 관련 기초정보 -->

        <modelVersion></modelVersion>

 

        <!-- 프로퍼티 정보: 공통 프로퍼티를 설정할 경우 사용 -->

        <properties></properties>

 

        <!-- 의존성 정보: 관련의존성 정보를 설정 -->

        <dependencies></dependencies>
       

        <!-- 저장소 정보: 특정저장소 정보를 설정할 경우 사용 -->

        <repositories></repositories>

 

        <!-- 빌드 정보: 빌드관련 설정 -->

        <build></build>

 

        <!-- 프로파일 정보: 프로파일 별관리 설정 -->

        <profiles></profiles>

    </project>

 

    기본정보

        기본정보 부분은 세부적으로 다음과 같이 구성되어 있다.

    

        * 모델버전

            Maven POM의 버전을 표시한다.(4.0.0)

 

        * 그룹 ID

            프로젝트가 속한 그룹ID를 설정한다. 일반적으로 메인패키지 명을 주로 사용 (ex. kr.pe.kihwa )

 

        * 아티팩트 ID

            프로젝트의 Artifact ID를 설정한다. 아티팩트란 사전적의미로 "인공물" 을 말하는 것으로

            프로젝트 ID라고 보면된다. 일반적으로 프로젝트 패키지 명을 사용(ex. porco )

 

        * 패키징 

            패키지 유형을 설정한다. (jar, war, ear 등)

 

        * 버전
            해당 프로젝트의 버전을 설정

 

        * 이름
            프로젝트의 이름을 설정

 

        * URL
            프로젝트 사이트의 URL 설정

 

    프로퍼티(properties)

        의존성등 pom 전반에 사용되는 프로퍼티(사용자정의 속성)를 정의한다.

        주로 사용하는 방법에는 소스 인코딩 속성(UTF-8), 동일 패키지의 버전(Spring 버전)등을

        일괄 정의하고 해당 변수를 el 형식으로 사용한다.

 

    저장소(repositories)

        저장소에 관한여 설정할 수 있다.

        maven 설정외에 POM상에서 참고할 추가 저장소 정보를 명시할 수 있다.

 

        보안강화에따라 2020년 1월 15일 이후 부터 Maven 중앙 저장소에서 단계적으로 http 관련 URL을 허용하지 않기때문에

        다음과 같이 추가적으로 설정해 줘야 한다.

         <repositories>

          <repository>

            <id>central</id>

            <name>Central Repository</name>

            <url>https://repo.maven.apache.org/maven2</url>

            <layout>default</layout>

            <snapshots>

                <enabled>false</enabled>

            </snapshots>

        </repository>

         

         ....

         

     </repositories>

     <pluginRepositories>

        <pluginRepository>

            <id>central</id>

            <name>Central Repository</name>

            <url>https://repo.maven.apache.org/maven2</url>

            <layout>default</layout>

            <snapshots>

                <enabled>false</enabled>

            </snapshots>

            <releases>

                <updatePolicy>never</updatePolicy>

            </releases>

        </pluginRepository>

    </pluginRepositories>

 

    의존성(dependencies)

        프로젝트의 의존성을 설정하는 부분으로 각각의 의존성에 대한 속성은 다음과 같이 구성되어 있다.

 

        * 그룹 ID
            의존하는 라이브러리의 그룹 ID

 

        * 아티팩트 ID

            의존하는 라이브러리의 아티팩트 ID

 

        * 버전
            의존하는 라이브러리의 버전

 

        * 스코프

            의존하는 라이브리리의 의존범위를 정의하며 다음과 같은 스코프가 존재한다.

 

            - compile(default) 

                컴파일 할 때 필요. 테스트 및 런타임에도 클래스패스에 포함된다. 

                <scope>를 설정하지 않을 경우 기본 값은 compile 이다.

 

            - provided

                 컴파일 할 때 필요하지만, 실제 런타임 때에는 컨테이너 같은 것에서 기본적으로 제공되는 모듈임을 의미한다.

                 예를 들어, 서블릿이나 JSP API 등이 이에 해당한다. 

                 컴파일과 테스트 시에 클래스패스에 포함되지만 배포시 제외된다.

                 ex) 운영시에 WAS에 있는 JDBC 드라이버를 사용하려고 한다면 JDBC 드라이버에 대한 스코프를 provided로 한다.

 

            - runtime

                 실행시(런타임)에 필요. 

                 프로젝트의 코드를 컴파일 할 때는 필요하지 않지만, 실행할 때 필요하다는 것을 의미한다. 

                 테스트와 실행시 클래스패스에 포함되지만 컴파일시에는 제외된다.

                 JDBC 드라이버 등이 예가 된다.

                 배포시 포함된다.

 

            - test

                 테스트 코드를 컴파일 할 때 필요. 

                 Mock 테스트를 위한 모듈이 예이다. 

                 테스트 시에 클래스패스에 포함되며, 배포시 제외된다.

 

            - system

                 해당 jar를 포함해야 한다고 명시적으로 입력 하는 것을 제외하고는 provided와 유사하다. 

                 단순 참조용으로 사용되며 Maven 저장소가 아닌 <systemPath> 속성을 사용하여 jar의 경로를 정의해 줄수 있다.

                 배포시 제외된다.

 

            - import

                 Maven 2.0.9 이상의 버전에서 지원하는 scope

                 <dependencyManagement> 섹션에서 pom의 의존관계에 대해 사용된다.

                 지정된 pom이 해당 pom의 <dependencyManagement> 영역에 있는 의존관계로 대체됨을 뜻한다.

                 다중 프로젝트에서 사용된다고 하는데 사용해본적이 없어서 '더 이상 자세한 설명은 생략한다.'

 

    빌드(build)

        빌드와 관련하여 정의 한다.

  

      - 최종이름

            jar, war 등 최종적으로 빌드되는 이름을 설정한다.

 

        - 디렉터리 구조

            기본디렉터리 구조와 다르거나 참고되어야 하는 경로가 있는 경우 설정한다.

 

        - 플러그인

            빌드필요한 플러그인을 설정한다.

            * web application의 경우 기본 compiler 외에 war 플러그인을 정의 한다.

 

    <build>

        <finalName>paragon-ips</finalName>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-war-plugin</artifactId>

                <version>3.2.2</version>

            </plugin>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>3.3</version>

                <configuration>

                    <source>$</source>

                    <target>$</target>

                </configuration>

            </plugin>

        </plugins>

    </build>

                 

    프로파일(profiles)

        여러가지 상황에 따른 빌드를 설정 한다.

   

  로컬, 개발, 테스트, QA, 운영 등 여러 환경에대여 배포할 경우 프로파일을 설정하고 그때그때 -P 옵션을 이용해서 배포할 수 있다.

 

  대부분은 소스파일 중에서 리소스(resource)에 있는 설정파일들이 차이가 있는데 이를 프로파일을 이용해서 각각 다르게 배포한다.

 

  <build>

     <resources>

         <resource>

             <directory>src/main/resources/$</directory>

         </resource>

     </resources>

  </build>

  <profiles>

      <profile>

          <id>local</id>

          <properties>

       <env>local</env>

          </properties> 

      </profile>

      <profile>

          <id>test</id>

          <properties>

       <env>test</env>

          </properties> 

      </profile>

      <profile>

          <id>prod</id>

          <properties>

       <env>prod</env>

          </properties> 

      </profile>

  </profiles>

   

위의 예제는 프로파일에 여러 ID를 설정하고 해당 ID의 프로퍼티인 env를 활용한 설정이다.

 

만약 테스트기에 배포할 패키지를 만든다면 다음과 같이 입력하면 된다.

 

         mvn clean package -P test

        

현장에서는 maven profile 기능보다 spring profile 등 다른 것을 사용하길 권장하고 있다.

* 필자는 rename 커맨드를 이용해서 properties 를 변경하는 방식을 사용했었다.

 

 

6. 메이븐 동작

 

    메이븐의 라이프사이클이라고 부르는 빌드는 플러그인에 의해 이루어지며 단계(Phase)를 가진다. 

    각 단계를 진행시키기 위해서는 플러그인이 지원하는 골(Goal)을 수행해야 한다.

 

    메이븐은 크게 3종류의 라이프사이클을 가진다.

    

    Clean : clean 단계를 이용하며 모든 결과물을 제거한다.

    Default : 일반적인 빌드 라이프사이클 

        - validate : 프로젝트 상태 점검, 빌드에 필요한 정보 존재유무 검사 단계

        - compile : 소스코드 컴파일 단계

        - test : JUnit들을 이용해서 테스트 하는 단계

        - package : jar, war 등 패키징 수행 단계

        - verify : 패키지 품질 기준 검사 단계

        - install : 패키지를 로컬 저장소에 설치하는 단계

       

    Site : site 단계, site-deploy 단계를 이용하며 프로젝트에 대한 문서사이트를 생성해 준다.(추가 설정 필요)

    

 

7. 메이븐에 Jar 추가하기

 

    개발을 진행하다보면 범용 저장소(Repository)가 아닌 고객사가 제공하는 라이브러리를 사용해야 할 경우가 있다.

    친절하게 고객사가 저장소를 운영하고 해당 주소를 알려주면 좋겠지만 대부분 범용 저장소를 사용하지 않는다는 것은

    특화된 라이브러리일 가능성이 높다.

 

    7.1. 의존성 스코프 system 이용하기(참고)

        POM 의존성 설정에서 system 스코프를 설정하고 systemPath 속성을 이용해서 경로를 지정해 주는 방법이 있다.

        

            <!-- custom -->

       <dependency>

            <groupId>Acme.JPG</groupId>

            <artifactId>AcmeGif</artifactId>

            <version>1.0.0</version>

            <scope>system</scope>

            <systemPath>$/libs/AcmeGif-1.0.0.jar</systemPath>

       </dependency>     

 

              출처: https://okjsp.tistory.com/1165644118 [OK 괜찮아, fInD YoUr FuN, eNjOy iT!]

        이 방법은 여러의존성을 추가할 경우 불편함이 있으니 다음 방법을 추천한다.

 

        [주의!!]

        - system 스코프의 경우 컴파일은 되나 배포시에 제외가 되므로 주의 해야한다.

 

   7.2. jar 를 로컬 저장소에 install 하는 방법(참고)

 

1. 로컬 maven 저장소에 아래 형식으로 jar를 install 한다.

mvn install:install-file -Dfile=파일경로/파일명.jar -DgroupId=그룹아이디 -DartifactId=아티팩트아이디 -Dversion=버전 -Dpackaging=jar 

2. pom에 dependency 설정

 

<!-- custom -->

        <dependency>

            <groupId>Acme.JPG</groupId>

            <artifactId>AcmeGif</artifactId>

            <version>1.0.0</version>

        </dependency>  

* 출처: kaling88.tistory.com/3

 

    7.3. 저장소를 설정(추천!!)

        POM 저장소 설정에 경로를 설정하고 의존성을 추가해주는 방법이 있다.

 

        <repositories>

            <repository>

                <id>in-project</id>

                <name>In Project Repo</name>

                <url>file://$/libs</url>

            </repository>

        </repositories>

 

        <!-- custom -->

        <dependency>

            <groupId>Acme.JPG</groupId>

            <artifactId>AcmeGif</artifactId>

            <version>1.0.0</version>

        </dependency>        

 

        출처: https://okjsp.tistory.com/1165644118 [OK 괜찮아, fInD YoUr FuN, eNjOy iT!]

 

     lib 폴더 구조도 repository 구조에 맞게 수정한다.

 

      +- libs

          +- Acme

              +- JPG

                  +- AcmeGif

                       +- 1.0.0

                            +- AcmeGif-1.0.0.jar

 

          출처: https://okjsp.tistory.com/1165644118 [OK 괜찮아, fInD YoUr FuN, eNjOy iT!]

[주의!!]

여기까지만 하면 되기도하고 안되기도 하는 사태가 발생한다. ㅡㅡ;

jar 이름을 참조해서 .pom 파일도 같은 위치에 만들어 줘야한다.

더보기

       +- libs

          +- Acme

              +- JPG

                  +- AcmeGif

                       +- 1.0.0

                            +- AcmeGif-1.0.0.jar

                            +- AcmeGif-1.0.0.pom

 

pom 내용은 기존 pom.xml 과 같은 형식으로 작성한다.

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>Acme.JPG</groupId>
    <artifactId>AcmeGif</artifactId>
    <version>1.0.0</version>
</project>

[주의!!]

내용은 pom.xml 같은 형식이지만 확장자는 .pom으로 작성해야 한다.