메이븐 버전 충돌 해결
pom.xml 에 여러 개의 dependency 설정을 했을 때 각 라이브러리가 참조하는 라이브러리 중 버전이 충돌하는 경우가 있다.
예를 들어 다음과 같이 hystrix-core 라이브러리는 commons-logging 1.1.1 버전을 참조하고 있고
httpcomponents 라이브러리는 commons-logging 1.2 버전을 참조한다.
1 2 | hystrix-core -> commons-logging:1.1.1 httpcomponents -> commons-logging:1.2 | cs |
이처럼 두 개의 서로 다른 버전을 참조하고 있을 때 maven은 root 레벨과 가장 가까운 라이브러리를 선택하게 된다.
이게 무슨 의미냐 하면
mvn dependency:tree 명령을 치면 pom.xml 에 선언되어 있는 의존성 라이브러리들의 트리 구조를 확인할 수 있다.
pom.xml 자신이 root 라고 했을 때 그 안에 선언되어 있는 dependency 들이 트리 구조로 보여진다.
즉, <dependencies> </dependencies> 안에서 가장 위에 있는 <dependency> 가 root 와 가장 가까운 라이브러리라 할 수 있는 것이다.
아래 두 개의 라이브러리가 선언되어 있을 때 해당 프로젝트에서는 commons-logging:1.2 버전이 사용되어 진다. (httpclient 라이브러리가 root 와 가깝기 때문)
1 2 3 4 5 6 7 8 9 10 11 | <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5</version> </dependency> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.4.4</version> </dependency> | cs |
이와같이 버전 충돌시 메이븐 버전 전략에 의존하는 것이 아닌 내가 직접 제어하고 싶은 경우가 있다.
개발자가 직접 해결하는 방법에 대해서 작성해 본다.
1.
maven-enforcer-plugin 설정
pom.xml 파일에 아래 플러그인을 추가한다.
maven-enforcer-plugin 은 버전 충돌이 발생하는 라이브러리를 출력해 준다.
1 2 3 4 5 6 7 8 9 10 11 | <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <configuration> <rules> <dependencyConvergence/> </rules> </configuration> </plugin> | cs |
위의 플러그인 설정 후 다음의 명령어를 실행해 보자.
1 | mvn enforcer:enforce | cs |
pom.xml 에 버전 충돌이 발생하는 라이브러리가 있다면 다음과 같이 출력될 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [WARNING] Dependency convergence error for commons-logging:commons-logging:1.1.1 paths to dependency are: +-test_project:test_project:0.0.1-SNAPSHOT +-com.netflix.hystrix:hystrix-core:1.4.4 +-com.netflix.archaius:archaius-core:0.4.1 +-commons-configuration:commons-configuration:1.8 +-commons-logging:commons-logging:1.1.1 and +-test_project:test_project:0.0.1-SNAPSHOT +-org.apache.pdfbox:pdfbox:1.8.10 +-org.apache.pdfbox:fontbox:1.8.10 +-commons-logging:commons-logging:1.1.1 and +-test_project:test_project:0.0.1-SNAPSHOT +-org.apache.pdfbox:pdfbox:1.8.10 +-commons-logging:commons-logging:1.1.1 and +-test_project:test_project:0.0.1-SNAPSHOT +-org.apache.httpcomponents:httpclient:4.5 +-commons-logging:commons-logging:1.2 and +-test_project:test_project:0.0.1-SNAPSHOT +-org.apache.httpcomponents:fluent-hc:4.5 +-commons-logging:commons-logging:1.2 | cs |
프로젝트 내에서 충돌이 발생하는 라이브러리들을 알았으니 이를 해결하기 위한 방법을 알아보자.
2.
해결 방법
가장 쉽게 해결할 수 있는 방법은 exclusion을 버전이 충돌하는 라이브러리에 추가해 주는 것이다.
그럼 hystrix-core는 commons-logging:1.1.1 버전이 아닌 commons-logging:1.2 버전을 사용하게 될 것이다.
1 2 3 4 5 6 7 8 9 10 11 | <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.4.4</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> | cs |
허나 난 다른 방법으로 버전 충돌을 해결한다.
일단 충돌이 나는 라이브러리를 모두 추출하고, 충돌나는 라이브러리 중 어떤 버전을 사용할지 결정한다.
commons-logging:1.2, commons-logging:1.1 두 개가 있다고 했을 때 commons-logging:1.2 사용 결정
결정이 되면 다음과 같이 주석으로 충돌이 발생하는 라이브러리라고 표기하고 그 아래에 의존성 라이브러리를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!-- ==================================================== --> <!-- dependency conflict library --> <!-- ==================================================== --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.7</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.9.7</version> </dependency> | cs |
마지막으로 충돌이 발생하는 라이브러리에 exclusion을 추가한다.
이와 같이 하면 dependency conflict library 주석 하위에 선언한 라이브러리를 참조하게 될 것이다.
1 2 3 4 5 6 7 8 9 10 | <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <exclusions> <exclusion> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclusion> </exclusions> </dependency> | cs |
결론은 충돌이 발생하는 라이브러리들이 있다면 충돌이 발생하는 라이브러리를 명시적으로 작성한다.
그리고 선언한 라이브러리들을 사용할 수 있게 충돌이 발생하는 구간에 exclusion 옵션을 추가해 주는 것이다.
'개발툴' 카테고리의 다른 글
maven effective pom 활용 (0) | 2019.08.23 |
---|---|
Fiddler Filter 기능에 대해서 알아보자 (3) | 2019.04.03 |
메이븐 버전 충돌 해결 (8) | 2017.12.13 |
윈도우 loopback 패킷 캡쳐 (RawCap) (0) | 2017.12.11 |
Maven 용어 정리 (0) | 2017.10.16 |
vagrant 구동 시 오류 (Your VM has become inaccessible) (0) | 2017.10.13 |
Microsoft SQL Server Management Studio - 서버 정보 저장하기 (0) | 2017.09.22 |
이클립스 NEON (0) | 2016.11.02 |
remote debugging on 안드로이드 (proxy 이용) (0) | 2016.06.30 |
감사합니다.
덕분에 3일 넘게 로그가 죽어도 안나오는것을 해결하였습니다.
잘 해결되어서 다행이네요. :)
포스팅 감사합니다.
궁금한것이, 충돌나는 depandency를 삭제하지 않고,
<exclusions>...</exclusions>처리를 하는것은
충돌난 것에 대한 기록으로 남기는 것인가요?
그냥 삭제하지 않는 또다른 이유가 궁금합니다.
안녕하세요.
A 라이브러리와 B 라이브러리가 있다고 가정하고, 두 개의 라이브러리는
A -> C 1.0 버전을
B -> C 1.1 버전을 사용중이라고 하겠습니다.
이와 같은 상황에서 C 라이브러리 참조에 대한 충돌을 회피하기 위해서 최상단에 C1.1 라이브러리를 명시하고,
A 라이브러리의 C 라이브러리 참조를 exclusions 하는 것입니다.
exclusions 부분을 작성하지 않으면 버전 충돌은 해결되지 않은 상태로 남아있게 됩니다.
도움이 되었으면 합니다.
감사합니다.
명령어를 어디에 ... 입력하는건가요,.?
intelliJ 기준으로 말씀드리면
Maven Projects View에 보시면 상단 도구모음에 Execute Maven Goal 이 있습니다.
클릭하시면 팝업이 하나 뜨는데 그곳에 명령어를 기입해서 실행하시면 됩니다.
Maven Project View는 아래와 같이 접근하시면 됩니다.
View > Tool Windows > Maven Project
안녕하세요 글 잘 봤습니다
exclusion 태그는 필수인가요?
만약 netflix library 에 exclusion 을 작성해주지 않으면 commons-loggin 1.2 를 자동으로 사용하는게 아니라 빌드가 실패하게 되는건가요?
또 하나 궁금한게..
netflix 에서는 1.1 을 사용하고, httpcomponents 에서는 1.2를 사용하도록 설정할 순 없나요? 당연히 이렇게 될 줄 알았는데.. 의외네요
httpcomponents 여러 버전을 한 프로젝트에서 사용할 수는 없습니다.
예를 들어
1.1 버전에 A.class가 있고
1.2 버전에 A.class 가 있을 때
애플리케이션 입장에서는 어떤 A.class를 써야 할지 판단을 하지 못하기 때문입니다.
감사합니다.