Maven의 버전범위(version range) 기능은 정확한 버전을 지정하지 않아도 일정한 범위에 해당하는 버전을 모두 체크해서 그 중 가장 최신 버전을 선택하게 해주는 유용한 기능이다. 예를 들어 Spring dependency의 버전을 [2.5,2.6) 이라고 넣으면 2.5부터 시작해서 2.6이 되기 전까지 지속적으로 업그레이드 되는 최신 마이너버전(2.5.1, 2.5.2...)을 버전의 수정없이 가장 상위버전으로 선택해서 사용하게 해준다.  []는 경계버전의 포함, ()는 제외이다.  상위나 하위 범위 중 하나를 생략하면 이전, 이후의 모든 버전을 다 지정하게 할 수 있다. [3.5,]이라고 넣으면 3.5 이상의 모든 버전에서 가장 상위 버전을 선택해준다.

문제는 며칠전에 쓴 Spring 3.0 개발버전에서 Maven 활용하기에 나오는 방법을 이용해서 스프링의 최신버전을 계속 빌드하고, 리포지토리에 올려 그것을 활용하려는 작업이 자꾸 실패한다는 것이다.

3.0의 최신 소스를 받아서 빌드하는데는 아무런 문제가 없다. 이전 글에서 제시한 방법으로 전용 리포지토리에 배포하는 것도 잘 된다.

문제는 거의 매일 새로 업데이트 되는 버전을 빌드해서 올리기 때문에 최신 버전을 사용해서 3.0을 이용하는 애플리케이션을 빌드하려면 자동으로 가장 최신의 모듈을 가져올 수 있게 해야 한다는 것이다. 당연히 이럴 때 유용한 version range를 적용했다.

스프링 빌드가 만들어주는 Maven의 아티팩트 버전은 좀 독특하다. 마치 SNAPSHOT 버전이 배포될 때 자동으로 날자-시간이 따라 붙는 것처럼, 스프링의 Ivy 빌드에서 생성하는 Maven모듈과 POM 정보에도 3.0.0.BUILD-200901020304와 같은 식으로 날자-시간이 붙는다. 이전에 얘기한 것처럼 버ㅈ번에 SNAPSHOT이 없기 때문에 스냅샷으로 취급되지 않고 Release버전으로 올라가야 한다. 따라서 SNAPSHOT의 dependency를 사용할 수 없다. 대신 버전의 범위를 주는 것이 가장 편리한 방법일 것이다.

처음에 테스트 했을 때는 별 문제가 없었던 것 같은데, 오늘 다시 작업을 하느라 새로 프로젝트를 만들고 메이븐 설정을 한 뒤 빌드를 해보니 스프링의 모듈을 가져오지 못해서 빌드가 실패했다.

리포지토리에 올라가 있는 것은 최신버전은 3.0.0.BUILD-20090120232117이다.

내가 <dependency> 항목에 설정한 버전은 [3.0.0,] 이었다.

빌드를 시도하면 리포지토리에서 발견되는 [..., 3.0.0.BUILD-20090120232117]에서 [3.0.0,]의 범위에 드는 것을 찾을 수 없다는 메시지가 나오면서 빌드가 실패한다. 지난번에는 잘 가져온 것 같은데 어찌 된 것일까 하고 한참을 테스트를 해봤지만 원하는 번들을 가져올 수 없었다.

심지어는 [2.0,] [1.0.0,5.0.0]과 같은 조건을 주어도 리포지토리 버전에 있는 3.0.0.BUILD-20090120232117이 범위에 들지 않는다는 경고만 뜰 뿐이었다. 뭔가 수상하다 싶어서 다른 모듈에 테스트를 해보았는데 JUnit이나 일반 라이브러리에는 정상적으로 범위가 잘 적용되었다.

 

오기가 나서 Maven 자료를 다시 뒤져보기 시작했다. 이슈트래커에 최신버전(2.0.10, 2.1-M2,3.0.0-alpha)에 등록된 이슈들을 뒤져보았지만 별 내용이 없다. 결국 지금 사용하는 Maven 2.0.9의 소스코드를 받아서 관련된 클래스의 동작방법을 분석해기 시작했다. -X 옵션을 주면 디버깅 정보가 뜨긴하지만, 소스를 보면 알겠지만 사실 제공하는 디버그 메시지에서는 얻을 수 있는 정보가 거의 없다.

Version range를 다루는 클래스는 이름 그대로 VersionRange이다. 그 안에 버전의 범위를 체크하는 코드가 들어있다. 상식적으로 알고 있는 버전 범위를 체크하는 기능들이 좀 거칠지만 나름 꼼꼼하게 들어있다. 테스트 코드도 충분하게 작성되어있었다.

소스를 분석하면서 발견한 흥미로운 정보는 ArtifactVersion이라는 클래스였다. Maven이 아티팩트의 버전을 어떻게 파싱하고 저장, 비교하는지를 알수 있는 가장 핵심적인 내용이다.

아티팩트의 1.0.0-M1-NIGHTLY-123과 같은 정보는 어떻게 저장될까?

Maven의 버전의 표준 포맷은

<major version>.<minor version>.<incremental version>-<qualifier>

이다. 위의 버전이라면 major = 1, minor = 0, incremental = 0 그리고 qualifier = M1-NIGHTLY-123 이라고 파싱되어서 저장된다. 여기서 qualifier는 다시 마지막에 나오는 123과 같은 숫자를 Build No로 따로 분리해서 관리한다.

앞의 세가지 버전은 숫자로 관리되므로 당연히 10.0.0이 8.0.0보다 크다. 하지만 뒤에 따라오는 qualifier 영역은 빌드넘버까지 보함해서 모두 스트링으로 취급된다. 즉 M1-10과 M1-8이 있다면 M1-8이 더 최신버전(큰 버전)으로 인식된다는 것이다. 따라서 3가지 버전넘버 뒤에 따르는 부분은 스트링으로 비교된다고 생각하고 자리수를 일치 시켜서 M1-08, M1-10과 같이 사용해서 실수가 없다. 사실상 공식 레퍼런스 문서인 Maven Definitive Guide에 나오는 설명이다.

 

내가 위의 범위 설정을 적용했지만 제대로 동작하지 않은 것은 두가지 이유가 있다.

첫째는 현재 스프링의 빌드스크립트가 만들어내는 아티팩트 버전의 네이밍 방법이 Maven표준을 따르지 않는다는 점이다. 3개의 버전은 나오지만 대쉬(-)가 빠져있다. 이럴 때 Maven은 전체를 모두 qualify로 보고 스트링으로 처리해버린다.

따라서 3.0.0.BUILD-xxxx 라고 되어있지만 [2.0,]에도 포함되지 않는 것이다. major,minor,incremental version을 해석하지 못하기 때문이다.

 

결국 스프링의 현재 버전넘버는 모두 스트링으로 해석되고 비교된다는 것인데, 그래도 의문은 왜

[3.0.0.BUILD,]라고 준 범위에 3.0.0.BUILD-20090120232117이 포함되지 않느냐 하는 것이다. 자바의 스트링의 compareTo를 이용해서 두 값을 비교하면 3.0.0.BUILD가 더 작은 값으로 나온다. 따라서 3.0.0.BUILD와 무한대 사이에 위의 버전이 포함되는 것이 상식이다.

결국 이 것은 DefaultArtifactVersion의 코드를 뜯어보다가 발견한 코드에서 답을 찾았다.

Maven의 버전비교 로직에 보이는 희한한 코드가 있는데, 그것은 버전 스트링의 앞부분이 같은 경우 한쪽이 더 길이가 길면 긴쪽을 무조건 낮은 버전으로 취급한다는 것이다. 앞부분이 같다면 전체 길이도 같을 때만 스트링의 compareTo를 적용한다. DefaultArtifactVersion의 compareTo() 메소드를 살펴보면 알 수 있다.

예를 들어서

M1-10과 M1-8을 비교하면 스트링의 일반적인 비교방법을 생각하면 10이 더 작은 버전으로 나온다. 이런 경우는 가이드 문서에 나온 대로 이해가 된다.

그런데 M1-10과 M1-1를 비교하면 M2-1가 더 작은 버전으로 나올 것 같은데, 그렇지 않고 M1-10이 더 작은 버전으로 해석된다. 앞부분이 같다면 길이가 긴 버전이 작은 버전으로 무조건 취급되기 때문이다.

따라서 3.0.0.BUILD와 3.0.0.BUILD-20090120232117는 항상 뒤의 것이 더 낮은 버전으로 해석된다.

결국 맞는 버전의 범위를 만들려면

  1. 표준버전포맷이 아니고 버전의 시작부분이 다르며 스트링 비교에서 작은 값으로 나오는 [2.0.0.BUILD,] 같은 것을 사용하는 것
  2. 앞부분이 같고 길이가 일치하면서 스트링 비교에서 작은 값으로 나오는 [3.0.0.BUILD-00000000000000,]을 이용하는 것

중의 한가지 방법을 써야 한다.

단, 리포지토리에 기존 2.5.x버전이 있는 것을 포함했다면 위의 범위를 적용했을 때 2.5버전을 가져온다. 2.5.6는 표준 버전이고 3.0.0.BUILD-xxx 버전은 표준이 아니므로 major버전이 0으로 잡힌다. 따라서 [3.0.0.BUILD-0000..,]을 적용하면 표준버전이 더 큰 값으로 인식이 되서 2.5.6을 가져온다. 리포지토리를 3.0버전으로 제한하면 모르겠지만, 기존 리포지토리도 포함하는 경우라면 비표준 버전에서 적당히 큰 값을 상위 범위로 잡아준다. 즉 [3.0.0.BUILD-00000000000000,9.9.9.BUILD] 같은 것을 사용하면 된다.

 

일관성 없는, 문서에는 정확하게 제시되지 않은 버전 비교방법을 적용한 Maven 덕분에 저녁 시간을 몽땅 날려버렸다. 사실 표준 버전체계를 따르지 않은 스프링의 책임이 더 크기는 하다. 어쨌든 덕분에 Maven 소스도 찬찬히 뜯어보게 되었고 (코드는 정말 맘에 안들었다) 애매하게 알고 있던 메이븐 아티팩트의 버전개념을 확실하게 정리 할 수 있는 시간이어서 흥미로웠다.

 

다만 이것은 2.0.9에 적용된 것이라는 점. 2.0.x가 계속 나오고, 2.1, 3.0 (무려 3개의 버전 브랜치가 독립적으로 개발중이다. 이 메이븐 팀은 도대체 무슨 생각인지 모르겠다)이 개발되면서 이 룰은 달라질 수 있다는 점을 주의 해야 한다.

Related posts:

  1. Maven의 default directory layout 변경하기
  2. Maven의 다중 리포지토리에 존재하는 동일 artifact 사용시 주의점
  3. Spring 3.0 (4) – Maven에서 Spring 3.0 최신버전 사용하기
  4. Maven의 새로운 가이드북 – Maven: The Definitive Guide
  5. Maven과 OSGi(Spring)의 버전포맷 비호환 문제
  6. Maven 다중 리포지토리와 버전 범위를 사용할 때의 주의점
  7. Spring 3.0 (27) R-599 JDK1.5+ Concurrent
  8. Maven 3.0과 버전 포맷 문제
  9. Maven 재도전기 (1)
  10. Nexus Maven Repository 1.0 출시

Facebook comments:

to “Maven의 version range를 사용할 때 주의할 점”

  1. 레퍼런스에서 얻을수 없는 경험을 얻을수 있어서 좋았습니다.
    잘읽었습니다. ^^*

  2. Why Not Try This Out

  3. thank you for share!

  4. You could look here

  5. thank you for share!

  6. thank you for share!

  7. thank you for share!

  8. thank you for share!

  9. thanks for share!
    [url=http://www.chinafree98.com/member/contextmenul.php?/celine-borsier-celine-clearance-store.html]celine borsier-celine-clearance store[/url]
    celine borsier-celine-clearance store

  10. thank you for share!

  11. Why Not Look Here
    [url=http://quanjian120.com/member/flinkimain.php?/fastest-weight-lossmeizitangofficial-online.html]meizitang[/url]
    meizitang

  12. Visit THIS Site
    [url=http://mensbootsoutlet.com]mens uggs[/url]
    mens uggs

  13. Navigate To These Guys
    [url=http://bootssaleukonline.com]ugg boots sale uk[/url]
    ugg boots sale uk

  14. mbt shoes reviews Maven의 version range를 사용할 때 주의할 점 » Toby’s Epril

  15. cheap mbt sport shoes Maven의 version range를 사용할 때 주의할 점 » Toby’s Epril

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha