이 내용은 박재성님이 집필하신 [자바 세상의 빌드를 이끄는 메이븐] 책을 그대로 정리한 것이다.
회사에서 스터디를 하는데 문서 보안 때문에 어쩔수 없이 블로그를 이용하게 되었고,
위 내용은 박재성님의 허락을 받았습니다.

5 메이븐을 이용한 의존 라이브러리 관리
 1) 메이븐의 의존 라이브러리 관리
  - 의존 관계에 있는 라이브러리 관리 기능을 제공하며, 라이프사이클과 더불어 메이븐의 중심에 있는 기능중의 하나로 반드시 이해해야 함
  가. 메이븐 저장소
   - 메이븐의 저장소는 중앙저장소, 원격 저장소, 로컬 저장소로 나눌수 있음
    . 중앙 저장소 : 오픈 소스 라이브러리, 메이븐 플러그인, 메이븐 아키타입을 관리하는 저장소
                    메이븐 2.0의 중앙저장소는 http://repo1.maven.org/maven2 -> http://search.maven.org 이걸로 바뀐거 같음
                    중앙 저장소는 원격 저장소 중의 하나이며 개발자가 임으로 라이브러리 배포할수 없음
    . 원격 저장소 : 회사에서만 사용하기 위한 용도의 사내 원격 저장소와 스프링 소스에서 제공하는 메이븐 저장소처럼 외부에 위치하는
                    외부(공개)원격 저장소
    . 로컬 저장소 : 메이븐을 빌드할때 다운로드 하는 라이브러리, 플러그인을 관리하는 개발자 PC의 저장소
                    기본 로컬 저장소는 USER_HOME/.me/resository 디렉토리
   - 각각의 저장소와 메이븐 페이즈와의 관계 
     


  나. 메이븐 저장소 설정
   - 메이븐의 저장소 설정은 <repositories>/<repository> 엘리먼트에서 함, 최상위 POM에 설정된 중앙 저장소의 설정을 보면
     <project ...>
  <repositories>
     <repository>
        <snapshots>
           <enabled>false</enabled>
        </snapshots>
        <id>central</id>
        <name>Central Repository</name>
        <url>http://repo.maven.apache.org/maven2</url>
     </repository>
  </repositories>
     </project>
   - 대부분의 오픈 소스 라이브러리는 중앙 저장소에서 제공. 일부 라이브러리는 별도의 메이븐 원격 저장소를 통하여 제공.
     중앙 저장소에서 제공하지 않는 라이브러리가 있다면 <repository/> 엘리먼트에 id, name, url 값을 설정
     id,name은 임의값, url은 원격 저장소의 url 설정
   - 메이븐은 라이브러리를 다운로드 할때 <repositories/> 엘리먼트에 설정되어 있는 저장소 순서로 다운로드
     처음에서 찾았다면 다음 저장소 접근하지 않고, 다른 라이브러리를 찾음
  다. 메이븐 의존 라이브러리 관리
   - <dependencies /> 엘리먼트를 이용하여 메이븐 중앙 저장소에서 라이브러리를 관리하는 방법을 살펴보자.
     <dependencies>
     <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
     </dependency>
     </dependencies>
     위에 파일 실행 순서
      . 메이븐은 중앙 저장소에서 JUnit 3.8.1을 확인 해당 버젼이 있으면 다운. 찾는 과정은 메이븐 중앙저장소(http://repo.maven.apache.org/maven2)
        에 접근하여 groupId/artifactId/version에 있는 ${artifactId}-${version}.jar 파일을 다운
        http://repo.maven.apache.org/maven2/junit/junit/3.8/junit-3.8.jar
      . 메이븐은 로컬 저장소의 변경없이 기본 디렉토리를 사용할 경우 USER_HOME/.m2/repository(USER_HOME 디렉토리)에 모든 의존성 라이브러리를 다운
        로컬 저장소에 라이브러리를 관리하는 규칙 또한 중앙 저장소와 동일.
      . groupId는 일반적으로 도메인명을 사용. groupId에 도메인명을 사용할 경우 점(.)을 기준으로 디렉토리를 분리해 관리
   - <dependencies /> 엘리먼트의 하위에 여러개의 <dependency /> 엘리먼트를 가질수 있음
   - junit 라이브러리를 4.7 버젼으로 다운로드 하고 싶은 경우 pom.xml을 4.7로 변경후
     <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
     mvn test 실행
     로컬에 이미 다운로드한 Junit4.7 버젼이 있다면 로컬 저장소에 있는 Junit4.7 활용, 최초 한번만 다운로드
     디렉토리 구조는 확인해 봐라. 실제 로컬을....
   - 앤트의 경우 프로젝트에 의존 관계에 있는 라이브러리가 포함되어 있지만, 메이븐은 프로젝트 소스와 의존 관계 라이브러리리를 분산해서 관리
     . 프로젝트 전체 파일 크기가 크져서 버젼 관리 시스템을 통하여 소스 코드를 공유하는데 추가 비용 발생
     . 라이브러리에 대한 히스토리 관리와 버전 관리를 제대로 하지 않을 경우 중복된 라이브러리가 포함되어 문제가 발생할 가능성이 있음
   - 메이븐은 pom.xml 파일에 저장소를 설정하지 않을 경우 http://search.maven.org 기본 저장소로 설정
   - 라이브러리 간단 추가 방법
     -> http://search.maven.org
     ->  검색창에 junit을 입력
     -> 많은 목록중에 원하는 파일을 클릭 여기서는 groupId junit artifactId junit 을선택
     -> 중간 부분의 Latest version 에 버젼을 클릭
     -> 좌측 중간 부분에 Dependency Information 부분을 복사해서
     -> pom.xml에 복사하면 끝
   - http://mvnrepository.com 이 사이트도 동일하게 이용 가능
  라. 의존 라이브러리 버전
   - 메이븐은 의존 관계에 있는 라이브러리의 버젼을 효율적으로 관리할수 있는 옵션 제공
     가장 일반적인 방법은 1.0과 같이 명시적으로 버전 정보를 지정이며, 범위를 제한하여 버젼을 관리할수 있음
     범위를 지정할때 형식은 아래 두가지
    . (,) : 해당 버전을 제외
    . [,] : 해당 버전을 포함
    . junit 라이브러리의 버젼을 3.8보다 크거나 같고, 4.8보다 작은 범위
    <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <verison>[3.8,4.8)</version>
    </dependency>
    위와 같이 설정하면 3.8보다 크거나 같고, 4.8보다 작은 버젼 중에서 가장 최신 버젼을 가짐, 아마 4.7을 가짐
    <verison>LATEST</version> 또는 <version>RELEASE</version> 을 사용함으로써 가장 최신 버젼과 의존 관계를 갖도록 설정 가능하지만
    최신 버젼이 정상적으로 동작하지 않을 가능성이 있기 때문에 좋은 선택이 아님
   - 개발중인 라이브러리나 프로젝트에 대해서는 SHAPSHOT을 사용
  마. 의존 라이브러리의 적용 스코프
   - 메이븐은 사용하는 라이브러리의 성격에 따라 스코프 지정이 가능
   - junit의 경우 테스트에만 사용되고 실제 배포할 때는 필요없는 라이브러리, <scope/> 엘리먼트를 활용해 스코프 설정 가
     <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <verison>[3.8,4.8)</version>
        <scope>test</scope>
    </dependency>
   - 라이브러리가 필요한 스코프에 따라 6가지 방식으로 지정
    . compile : 스코프를 설정하지 않았을때의 기본 스코프, 컴파일 및 배포할때 같이 제공해야 하는 라이브러리
    . provided : 예를 들어 servlet.jar 는 서블릿 컨테이너에서 제공하므로 컴파일 시점에는 필요, 배포 시점에는 필요 없음
    . runtime : 컴파일 시에는 사용되지 않지만 애플리케이션 실행할때 사용되는 라이브러리일 경우
    . test : 테스트 시점에서만 사용
    . system : provided와 비슷. 단지 우리가 직접 jar 파일을 제공해야 함. 이 스코프의 jar 파일은 저장소에서 관리되지 않을수 있음
    . import : 다른 POM 설정 파일에 정의되어 있는 의존 관계 설정을 현재 프로젝트로 가져온다. 이 범위는
               <dependencyManagement/>엘리먼트에서만 사용 가능
 2) 웹진 프로젝트에 의존 라이브러리 추가하기
  가. 스트럿츠2, 스프링, 마이바스트 라이브러리 의존성 추가
   - 너무 라이브러리가 많아서 org.springframework, org.apache.struts, org.apache.ibatis
     pom.xml 참조


   - pom.xml 에 의존 관계 설정 후 mvn test 를 실행하면 의존 관계에 있는 라이브러리를 다운로드 하고 빌드가 성공
   - 의존 관계로 설정한 라이브러리를 프로젝트로 복사해 주는 dependency 플러그인 기능
     mvn clean dependency:copy-dependencies package 을 실행
     target/dependency 디렉토리가 생기고 jar 파일이 복사됨, 실제로 디렉토리를 확인해 보면 pom.xml에 추가한 파일 외에
     다른 jar 파일이 존재. 이유는 뒤에서 설명
  나. 의존성 전이
그림7


   - 그림 7과 같이 오픈 소스 프레임워크가 추가 될때마다 해당 프레임워크와 의존 관계에 있는 라이브러리를 추가해야 하기 때문에
     하나의 프로젝트가 의존 관계에 있는 라이브러리의 수는 증가. 이는 결과적으로 메이븐 설정 파일의 복잡도를 증가시킴
     이 한계점을 극복하기 위하여 메이븐은 2.0 버젼부터 의존성 전이 기능을 제공
   - 웹진 프로젝트가 Struts2 프레임워크와 의존 관계가 있고, Struts2는 freemarker, Ognl과 의존관계가 있다면 프로젝트는
     Struts2에 대한 의존 관계만 추가해도 freemarker, Ognl 의존 관계를 가지는 방식이 의존성 전이
     메이븐은 의존 관계에 있는 라이브러리를 다운로드 하면서 pom.xml 파일까지 다운로드, 다운로드 위치는 둘다 같음
     http://search.maven.org 사이트 확인 가능
     struts-core 라이브러리의 pom.xml을 열어보면 아래와 같고 <dependency/> 엘리먼트 설정이 10개가 넘음
     struts2-core-2.3.1.2.pom 파일 참조

    - struts2-core 라이브러리의 pom 파일을 보면 의존 관계에 있는 라이브러리 설정(<dependy/> 엘리먼트 설정)이 10개가 넘음
     웹진을 빌드할때 struts2-core pom 파일에 설정되어 있는 모든 라이브러리가 의존 관계를 가질 경우 라이브러리 수는 급격히 증가
     메이븐은 이와 같은 문제점을 해결하기 위해 의존 관계에 있는 라이브러리를 제한이 가능하도록 의존성 전이에 대한 설정 변경 지원
    a 의존성 중개 Dependency mediation : 버젼이 다른 두개의 라이브러리가 의존 관계에 있다면 메이븐은 더 가까운 의존 관계에 있는
      pom 설정의 버전과 의존관계를 가짐
      A 프로젝트가 A->B-C->D2.0 버전, A->E->D1.0 버젼의 의존 관계가 발생한다면 A 프로젝트는 D1.0버전과 의존 관계를 가짐
      D2.0 버전을 사용하고 싶다면, A프로젝트의 메이븐 설정 파일에 명확하게 의존 관계를 명시
    b 의존성 관리 Dependency management : 메이븐 설정 파일의 <dependencyManagement/>엘리먼트의 의존 관계에 있는 라이브러리와 버젼을
      명시적으로 표시. A 프로젝트에서 D라이브러리의 2.0버젼을 사용한다고 <dependencyManagement/>에 설정. 뒷장에서 설명
    c 의존성 스코프 Dependency scope : 현재 빌드의 상태에 맞는 라이브러리인 경우 의존 관계를 가짐
      test 스코프를 가지는 경우 최종 배포 산출물을 포함하는 시점에는 포함되지 않음
    d 의존성 예외 Excluded dependencies : 의존 관계에 있는 라이브러리를 <exclusion/> 엘리먼트를 활용하여 명시적으로 제외
    e 선택적 의존성 Optional dependencies : A->B->C 와 같은 구조로 의존 관계를 가지는 경우 B프로젝트에 C가 optional로 설정되어
      있다면 A 프로젝트를 빌드할때 C는 의존 관계를 가지지 않도록 설정하는 기능. 이 설정은 <optional/> 엘리먼트를 활용하여 설정
   - 메이븐이 의존성 전이 기능을 제공하기 때문에 불필요한 라이브러리가 추가되거나 의도하지 않는 라이브러리와의 의존 관계를 갖는 경우가 발생
     위의 기능 a~e 기능을 활용하여 불필요한 라이브러리를 포함하지 않도록 설정
     mvn dependency:copy-dependencies 를 실행하면 의존 관계로 설정한 라이브러리를 프로젝트로 복사해 주었음. 여기서 필요 없는
     의존 관계를 제거함

   
위에서 가장 먼저 제거하면 좋겠다고 생각하는 라이브러리가 commons-io-2.0.1.jar 에 대한 의존 관계임
     이걸 제거 하려면 commons-io-2.0.1.jar 라이브러리가 어떤 라이브러리의 의존성 전이가 된것인지 파악해야 함
     가장 무식한 방법은 <dependency/> 엘리먼트에 설정되어 있는 모든 라이브러리의 pom 파일을 다운로드해 열어 보면서 일일이 확인
     하는 것이지만 라이브러리가 너무 많아서 무리. 이것을 해결하기 위해 메이븐의 dependency 플러그인은 현재 프로젝트와 의존 관계에 있는
     라이브러리의 구조를 파악할수 있도록 tree 골을 제공
     mvn dependency:tree 실행

     
    위 에서 보면 commons-io-2.0.1.jar에 대한 의존관계는 struts2-core 라이브러리가 가지고 있음
     struts2-core-2.3.1.2.pom 파일에서 의존성 예외 기능을 활용하여 명시적으로 제외
 <dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <exclusions>
   <exclusion>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
   </exclusion>
  </exclusions>
        </dependency>
     위에 작업을 반복함으로서 필요한 라이브러리만 의존 관계를 가지도록 설정 가능
     최종 적으로 의존 관계를 가지는 라이브러리는 소수만 남음. 그 이유는 struts2-core pom 파일에 설정되어 있는 것처럼
     대부분의 라이브러리의 의존성 스코프와 선택적 의존성 설정 때문
     <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
 <scope>provided</scope>
     </dependency>
     <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <scope>compile</scope>
 <optional>true</optional>
     </dependency>
     위와 같이 의존성 스코프와 선택적 의존성 기능을 활용하여 의존 관계를 관리하도록 설정하고 있음
  다. 의존성 스코프와 의존성 전이와의 관계
    - 의존성 스코프는 단순히 라이브러리에 대한 의존성 스코프만을 정의하는 것이 아니라 의존성 전이와 관련이 있음
[그림10]


    그림 10 의존성 스코프와 의존성 전이의 관계
 3)속성
  - 메이븐 설정 파일에서 발생하는 중복 설정을 제거하기 위해 <properties/>엘리먼트를 정의하고 설정파일 전체에서 사용
    <project>
    [....]
    <properties>
 <struts2.version>2.1.8</struts2.version>
 <spring.version>3.0.1.RELEASE</spring.version>
    </properties>
 <dependencies>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <scope>compile</scope>
  <optional>true</optional>
  <verion>${spring.version}</version>
     </dependency>
 </dependencies>
  가. pom/project 속성
   - project와 pom을 접두사로 사용, pom접두사는 메이븐 3.0에서 deprecated 되는 속성
     가능하면 project 접두사를 사용하는 것이 바람직함
     ${project.build.directory} 는 target 디렉토리
     ${project.name}, {pom.name} 프로젝트 이름
     .... 생략
  나 settings 속성
   - 메이븐과 관련한 설정은 settings.xml 파일에서 함settings.xml에 정의한 설정값을 참조할수 있는 것이 settings 속성
     settings 접두사를 이용
     ${setting.localRepository}는 로컬저장소의 경로를 참조
  다. 환경 변수 속성
   - env 접두사를 이용하여 시스템 환경 변수의 값을 참조
     {env.PATH} 시스템의 PATH
     {env.JAVA_HOME} 시스템의 JAVA_HOME 설정값을 참조
  라 자바 시스템 속성
   - 메이븐은 자바 시스템 속성으로 설정된 모든 속성을 참조할수 있음
   - 자주 사용하는 속성중에 하나 ${basedir} 임. 이 속성은 pom.xml 설정 파일이 위치하는 디렉토리     

 

 

 

 

 

 

 

 

 

 

 

 



 

Posted by gt1000

블로그 이미지
gt1000

태그목록

공지사항

어제
오늘

달력

 « |  » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함