버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.

...

도움말
title고수와 하수를 구분하는 Dependency Management

Maven을 좀 안다고 자랑하려면 Maven Dependency Management에 대한 깊은 이해 및 문제해결 능력을 갖추고 있어야 합니다. 특히 dependency의 충돌 문제는 Maven을 사용하는 개발자들에게 정말 쉽지 않은 문제이므로 많이 사용하면서 충돌 문제를 해결하는 능력을 키우는 것이 중요합니다.

Dependency의 속성 및 정의

Maven POM에 dependency를 추가할 때 다음과 같은 형식으로 추가합니다.

...

속성설명필수
Group ID

Java의 패키지와 같은 개념

Artifact의 그룹

O
Artifact ID

Artifact의 식별자

Artifact 유형이 여러 가지가 있지만 대표적으로 .jar .war .ear 등이 있음

Artifact는 소스코드와 JavaDoc이 같이 포함될 수 있음

O
VersionArtifact의 버전 정보O
TypeArtifact의 유형X
Scope

Artifact의 적용 범위 (test, runtime, compile, provided, import, system 등 다양한 범위가 있음)

  • compile이 기본값(모든 classpath에 적용)
  • test는 테스트 코드 컴파일 및 테스트 실행에만 적용하라는 의미
  • runtime은 실행시에만 적용하라는 의미(컴파일에는 필요하지 않음)
  • provided는 컴파일할때에는 적용이 되지만 패키징할 때에는 빠짐
  • system은 repository에서 찾지 않으며 별도로 <systemPath> 를 추가하고 .jar 파일의 경로를 추가해야 함
X
ClassifierArtifact에 여러 개의 식별자를 두고 싶을 때 사용X
System PathScope가 system인 경우 <systemPath> 를 추가해야 함X

새로운 Dependency 추가하기

Central Repository에서 Dependency 검색하기

...

Central Maven Repository에서 Dependency 검색하기

Central Maven Repository의 https://mvnrepository.com 입니다. 다음과 같이 접속을 하면 검색 화면을 확인할 수 있습니다.

Image Added

검색창에 spring 으로 입력하면 spring과 관련된 dependency가 검색됩니다. 아래에서 spring-core를 추가하고자 하는 경우 spring-core를 클릭합니다.

Image Added

그러면 다음과 같이 spring-core의 버전 목록이 나타납니다. 5.2.5.RELEASE를 클릭합니다.

Image Added

Maven POM에  Dependency 추가하기

이제 해당 버전을 클릭하면 다음과 같이 XML의 내용을 확인할 수 있습니다.

Image Added

이제 이 XML의 내용을 Maven POM(pom.xml)파일에 추가합니다.

코드 블럭
languagexml
linenumberstrue
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

Local Repository에는 어떻게 저장되나?

...

Maven의 dependency plugin에는 의존성 그래프를 트리 형식으로 보여주는 기능을 제공하는 goal(tree)가 있습니다. 그렇다면 이 그래프를 왜 확인해야 하나요? 답은 dependency의 충돌(conflict) 문제를 해결하기 위해서 입니다. 

코드 블럭
languagetext
linenumberstrue
# mvn dependency:tree
[INFO] Scanning for projects...
[INFO] 
[INFO] -------------< org.springframework.boot:spring-boot-ldap >--------------
[INFO] Building Spring Boot LDAP Sample 2.2.6.RELEASE
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ spring-boot-ldap ---
[INFO] org.springframework.boot:spring-boot-ldap:jar:2.2.6.RELEASE
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.2.6.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.2.6.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.2.6.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.2.6.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.2.6.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.12.1:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.12.1:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.25:runtime
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.2.6.RELEASE:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.10.3:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.3:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.10.3:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.10.3:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.10.3:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.10.3:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-validation:jar:2.2.6.RELEASE:compile
[INFO] |  |  +- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile
[INFO] |  |  \- org.hibernate.validator:hibernate-validator:jar:6.0.18.Final:compile
[INFO] |  |     +- org.jboss.logging:jboss-logging:jar:3.4.1.Final:compile
[INFO] |  |     \- com.fasterxml:classmate:jar:1.5.1:compile
[INFO] |  +- org.springframework:spring-web:jar:5.2.5.RELEASE:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.2.5.RELEASE:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.2.5.RELEASE:compile
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- org.springframework.data:spring-data-ldap:jar:2.2.6.RELEASE:compile
[INFO] |  +- org.springframework:spring-context:jar:5.2.5.RELEASE:compile
[INFO] |  +- org.springframework.ldap:spring-ldap-core:jar:2.3.2.RELEASE:compile
[INFO] |  +- org.springframework.data:spring-data-commons:jar:2.2.6.RELEASE:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] +- org.springframework.data:spring-data-jpa:jar:2.2.6.RELEASE:compile
[INFO] |  +- org.springframework:spring-orm:jar:5.2.5.RELEASE:compile
[INFO] |  +- org.springframework:spring-aop:jar:5.2.5.RELEASE:compile
[INFO] |  +- org.springframework:spring-tx:jar:5.2.5.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:5.2.5.RELEASE:compile
[INFO] |  +- org.springframework:spring-core:jar:5.2.5.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.2.5.RELEASE:compile
[INFO] |  \- org.aspectj:aspectjrt:jar:1.9.5:compile
[INFO] +- org.apache.directory.server:apacheds-core:jar:1.5.7:test
[INFO] |  +- org.apache.directory.server:apacheds-i18n:jar:1.5.7:test
[INFO] |  +- org.apache.directory.server:apacheds-core-api:jar:1.5.7:test
[INFO] |  |  \- org.apache.directory.server:apacheds-core-constants:jar:1.5.7:test
[INFO] |  +- org.apache.directory.server:apacheds-utils:jar:1.5.7:test
[INFO] |  +- bouncycastle:bcprov-jdk15:jar:140:test
[INFO] |  +- org.apache.directory.shared:shared-ldap:jar:0.9.19:test
[INFO] |  |  +- commons-collections:commons-collections:jar:3.2.1:test
[INFO] |  |  +- org.apache.directory.shared:shared-i18n:jar:0.9.19:test
[INFO] |  |  \- antlr:antlr:jar:2.7.7:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-schema:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-schema-loader:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-schema-manager:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-cursor:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-jndi:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-asn1-codec:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-asn1:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-constants:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-converter:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldap-schema-dao:jar:0.9.19:test
[INFO] |  +- org.apache.directory.shared:shared-ldif:jar:0.9.19:test
[INFO] |  \- org.apache.directory.shared:shared-dsml-parser:jar:0.9.19:test
[INFO] |     +- dom4j:dom4j:jar:1.6.1:test
[INFO] |     |  \- xml-apis:xml-apis:jar:1.0.b2:test
[INFO] |     \- xpp3:xpp3:jar:1.1.4c:test
[INFO] +- org.apache.directory.server:apacheds-core-entry:jar:1.5.7:test
[INFO] +- org.apache.directory.server:apacheds-protocol-shared:jar:1.5.7:test
[INFO] |  \- org.apache.mina:mina-core:jar:2.0.0-RC1:test
[INFO] +- org.apache.directory.server:apacheds-protocol-ldap:jar:1.5.7:test
[INFO] |  +- org.apache.directory.server:apacheds-kerberos-shared:jar:1.5.7:test
[INFO] |  |  \- org.apache.directory.server:apacheds-core-jndi:jar:1.5.7:test
[INFO] |  \- org.apache.directory.server:apacheds-xdbm-tools:jar:1.5.7:test
[INFO] |     \- org.apache.directory.server:apacheds-xdbm-base:jar:1.5.7:test
[INFO] +- org.apache.directory.server:apacheds-server-jndi:jar:1.5.7:test
[INFO] |  +- org.apache.directory.server:apacheds-ldif-partition:jar:1.5.7:test
[INFO] |  |  +- org.apache.directory.server:apacheds-avl-partition:jar:1.5.7:test
[INFO] |  |  |  \- org.apache.directory.server:apacheds-core-avl:jar:1.5.7:test
[INFO] |  |  \- org.apache.directory.server:apacheds-core-mock:jar:1.5.7:test
[INFO] |  \- org.apache.directory.server:apacheds-jdbm-partition:jar:1.5.7:test
[INFO] |     +- org.apache.directory.server:apacheds-jdbm-store:jar:1.5.7:test
[INFO] |     |  \- org.apache.directory.server:apacheds-jdbm:jar:1.5.7:test
[INFO] |     \- org.apache.directory.server:apacheds-xdbm-search:jar:1.5.7:test
[INFO] +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.2.6.RELEASE:provided
[INFO] |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.33:provided
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.33:provided
[INFO] |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.33:provided
[INFO] +- org.apache.tomcat.embed:tomcat-embed-jasper:jar:9.0.33:provided
[INFO] |  \- org.eclipse.jdt:ecj:jar:3.18.0:provided
[INFO] +- org.springframework.session:spring-session-jdbc:jar:2.2.2.RELEASE:compile
[INFO] |  +- org.springframework.session:spring-session-core:jar:2.2.2.RELEASE:compile
[INFO] |  \- org.springframework:spring-jdbc:jar:5.2.5.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.2.6.RELEASE:compile
[INFO] |  \- com.zaxxer:HikariCP:jar:3.4.2:compile
[INFO] +- com.h2database:h2:jar:1.4.200:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.2.6.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:2.2.6.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.2.6.RELEASE:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.4.0:test
[INFO] |  |  \- net.minidev:json-smart:jar:2.3:test
[INFO] |  |     \- net.minidev:accessors-smart:jar:1.2:test
[INFO] |  |        \- org.ow2.asm:asm:jar:5.0.4:test
[INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.3:test
[INFO] |  |  \- jakarta.activation:jakarta.activation-api:jar:1.2.2:test
[INFO] |  +- org.junit.jupiter:junit-jupiter:jar:5.5.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-api:jar:5.5.2:test
[INFO] |  |  |  +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] |  |  |  \- org.junit.platform:junit-platform-commons:jar:1.5.2:test
[INFO] |  |  +- org.junit.jupiter:junit-jupiter-params:jar:5.5.2:test
[INFO] |  |  \- org.junit.jupiter:junit-jupiter-engine:jar:5.5.2:test
[INFO] |  +- org.junit.vintage:junit-vintage-engine:jar:5.5.2:test
[INFO] |  |  +- org.apiguardian:apiguardian-api:jar:1.1.0:test
[INFO] |  |  +- org.junit.platform:junit-platform-engine:jar:1.5.2:test
[INFO] |  |  \- junit:junit:jar:4.12:test
[INFO] |  +- org.mockito:mockito-junit-jupiter:jar:3.1.0:test
[INFO] |  +- org.assertj:assertj-core:jar:3.13.2:test
[INFO] |  +- org.hamcrest:hamcrest:jar:2.1:test
[INFO] |  +- org.mockito:mockito-core:jar:3.1.0:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.10.8:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.10.8:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.6:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-test:jar:5.2.5.RELEASE:test
[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.6.4:test
[INFO] \- org.springframework.ldap:spring-ldap-test:jar:2.3.2.RELEASE:test
[INFO]    +- com.google.code.typica:typica:jar:1.3:test
[INFO]    |  +- commons-httpclient:commons-httpclient:jar:3.1:test
[INFO]    |  \- commons-codec:commons-codec:jar:1.13:test
[INFO]    +- commons-io:commons-io:jar:2.4:test
[INFO]    +- commons-lang:commons-lang:jar:2.6:test
[INFO]    +- javax.activation:activation:jar:1.1:test
[INFO]    \- org.springframework.ldap:spring-ldap-ldif-core:jar:2.3.2.RELEASE:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.953 s
[INFO] Finished at: 2020-04-20T01:54:58+09:00
[INFO] ------------------------------------------------------------------------

...

다음은 Java EE 버전에 따른 Java EE를 구성하는 표준들의 버전을 나열한 표입니다. 만약 Java EE 6를 지원하는 Tomcat을 사용한다면 Servlet API는 3.0을 사용해야 합니다. 그런데 dependency를 확인해보니 Servlet API 2.5 버전이라면 표준이 호환되지 않기 때문에 당연히 Tomcat이 제대로 실행되지 않는 문제가 발생합니다. 이러한 문제가 가장 찾기 어려운 문제중 하나입니다.

SpecificationJava EE 6Java EE 7Java EE 8
Unified Expression Language (EL)2.23.03.0
Servlet3.03.14.0
Managed Beans1.01.01.0
JavaServer Pages Standard Tag Library (JSTL)1.21.21.2
JavaServer Pages (JSP)2.22.32.3
JavaServer Faces (JSF)2.02.22.3
Java Transaction API (JTA)1.11.21.2
Java Persistence API (JPA)2.02.12.2
Java API for WebSocket (WebSocket)n/a1.01.1
Java API for RESTful Web Services (JAX-RS)1.12.02.1
Java API for JSON Processing (JSON-P)n/a1.01.1
Interceptors1.11.21.2
Enterprise JavaBeans (EJB)3.1 Lite3.2 Lite3.2
Dependency Injection for Java1.01.01.0
Debugging Support for Other Languages (JSR-45)1.01.01.0
Contexts and Dependency Injection for the Java EE Platform1.01.12.0
Common Annotations for the Java Platform (JSR-250)1.11.21.3
Bean Validation1.01.12.0

다음은 Apache Tomcat의 버전에 적용된 표준의 버전을 나열한 표입니다. 웹 애플리케이션을 Spring Boot로 개발한다면, Spring WebMVC를 사용한다면 아래 버전을 유심히 확인해야 합니다.

Servlet SpecJSP SpecEL SpecWebSocket SpecAuthentication (JASIC) SpecApache Tomcat VersionLatest Released VersionSupported Java Versions
5.03.04.02.02.010.0.x10.0.0-M4 (alpha)8 and later
4.02.33.01.11.19.0.x9.0.348 and later
3.12.33.01.11.18.5.x8.5.547 and later
3.12.33.01.1N/A8.0.x (superseded)8.0.53 (superseded)7 and later
3.02.22.21.1N/A7.0.x7.0.1036 and later
(7 and later for WebSocket)
2.52.12.1N/AN/A6.0.x (archived)6.0.53 (archived)5 and later
2.42.0N/AN/AN/A5.5.x (archived)5.5.36 (archived)1.4 and later
2.31.2N/AN/AN/A4.1.x (archived)4.1.40 (archived)1.3 and later
2.21.1N/AN/AN/A3.3.x (archived)3.3.2 (archived)1.1 and later

어떻게 충돌 문제를 해결할 수 있을까?

Dependency Conflict가 발생하면 다음과 같은 에러 메시지가 발생하거나 Classpath와 관련된 오류가 발생하는 것이 대표적이고, 그외 앞서 설명한 Java SE/Java EE 표준의 궁합이 맞지 않는 경우는 더 이상한 오류 메시지가 나올 수 있습니다.

...

가장 먼저 확인해야하는 것은 Dependency Tree를 확인하고 어떤 dependency라 문제가 되는지 찾는 것입니다. 아래는 commons-collections 의 충돌 이슈를 해결하기 위해서 별도 옵션을 지정했습니다.

코드 블럭
languagetext
linenumberstrue
# mvn dependency:tree -Dverbose -Dincludes=commons-collections
... 생략
[INFO] [dependency:tree]
[INFO] org.apache.maven.plugins:maven-dependency-plugin:maven-plugin:2.0-alpha-5-SNAPSHOT
[INFO] +- org.apache.maven.reporting:maven-reporting-impl:jar:2.0.4:compile
[INFO] |  \- commons-validator:commons-validator:jar:1.2.0:compile
[INFO] |     \- commons-digester:commons-digester:jar:1.6:compile
[INFO] |        \- (commons-collections:commons-collections:jar:2.1:compile - omitted for conflict with 2.0)
[INFO] \- org.apache.maven.doxia:doxia-site-renderer:jar:1.0-alpha-8:compile
[INFO]    \- org.codehaus.plexus:plexus-velocity:jar:1.1.3:compile
[INFO]       \- commons-collections:commons-collections:jar:2.0:compile

...

일단 문제가 되는 dependency를 찾으면 다음과 같이 <exclude> 처리를 합니다. 이렇게 <exclude> 처리를 하면 해당 dependency는 아예 제거됩니다.

코드 블럭
languagexml
linenumberstrue
<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
          <groupId>sample.ProjectB</groupId>
          <artifactId>Project-B</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>
</project>

...

이 방법은 아주 간단합니다. JAR 파일의 패키지명을 변경하는 것입니다. Maven Shade Plugin을 사용하면 JAR 파일 내부의 패키지명을 변경할 수 있습니다. 예를 들면 com.demo 패키지의 클래스가 충돌이 발생하는 경우 이 패키지를 shade.com.demo 로 변경하여 아예 충돌이 발생하지 않도록 하는 방법입니다. 보통 이 단계까지 진행이 되면 가장 안좋은 상황으로 인지하면 되겠습니다.

참고