개린이 탈출기

[Maven/Gradle]라이브러리 버전 관리 시 Snapshot 과 release 의 처리 방식 차이 본문

카테고리 없음

[Maven/Gradle]라이브러리 버전 관리 시 Snapshot 과 release 의 처리 방식 차이

yooverd 2024. 12. 13. 00:37
728x90
반응형
SMALL

 

 

 최근에 maven 을 사용하는 프로젝트에서 갑자기 빌드가 되지 않는 문제를 마주했다.
 조금 당황했지만, 문제가 되는 라이브러리에 대응되는 버전의 폴더를 삭제하고 maven 프로젝트를 새로고침한 뒤 재실행 하니 문제가 감쪽같이 해결되었다.

 왜...?


 

SNAPSHOT 과 RELEASE의 차이

 우선 SNAPSHOT 과 RELEASE 의 가장 큰 차이점 중 하나는 변경 가능성 이라고 생각한다.

  SNAPSHOT은 개발 단계에서 주로 사용하는 버전으로, 보통 변경 가능성이 높은 경우 SNAPSHOT으로 배포한다.

 동일한 버전으로 스냅샷을 배포하면 1.0.0-SNAPSHOT. 20241212.123456-1 와 같이 타임스탬프와 일련번호를 섞어 스냅샷 버전을 구분할 수 있도록 한다.

 RELEASE 는 보통 변경 가능성이 크지 않은 경우이므로, 스냅샷과 같이 타임스탬프가 추가되거나 하지는 않는다.

 


의존성 라이브러리 관리

Maven

Maven은 프로젝트의 의존성을 가져올 때, 로컬 리포지토리, 원격 리포지토리(Nexus 등), Maven 중앙 리포지토리 순서로 가져온다.

 

여기서 SNAPSHOT과 RELEASE 버전에 따라 의존성 버전 처리 방식에 조금 차이가 발생한다.

 

RELEASE

RELEASE 버전의 경우 다음과 같다

RELEASE 버전

 

 우선적으로 로컬 리포지토리를 탐색한다.
 로컬 리포지토리 경로 디폴트 위치(윈도우 기준)는 C:\Users\<사용자 이름>\.m2\repository 이며, 위치를 수정할 수 있다
해당 경로로 해당 되는 버전의 라이브러리가 존재한다면 더 이상 탐색하지 않고 기존에 다운받아놓은 jar 파일을 사용한다.

 만일 해당하는 버전을 찾지 못한 경우 순차적으로 원격 리포지토리(Nexus 같은 원격 저장소), 중앙 Maven 리포지토리에서 찾는다.

 

SNAPSHOT

SNAPSHOT 버전은 변경 가능성이 있는 개발 버전이라 탐색 방식에 차이가 발생한다.
 우선 해당하는 버전이 있는지 로컬 리포지토리를 먼저 확인한다. 없다면 원격 리포지토리에서 해당 스냅샷 최신 버전을 다운받아 사용한다.

 만일 존재한다면, 설정해놓은 updatePolicy의 설정에 따라 원격 리포지토리에서 스냅샷 최신 버전을 찾아 비교한다.

 원격 리포지토리의 버전이 더 최신 버전이라면 다시 다운받아 로컬에 덮어쓴다.

 

updatePolicy 의 설정 방법은 다음과 같다.

<profiles>
    <profile>
        <id>default</id>
        <repositories>
            <repository>
                <id>repository1</id>
                <url>http://repository1.sample.com/repository/snapshots</url>
                <snapshots>
                    <enabled>true</enabled>
                    <updatePolicy>always</updatePolicy>
                </snapshots>
            </repository>
        </repositories>
    </profile>
</profiles>

 

always 항상 원격 리포지토리에서 최신 SNAPSHOT과 비교
daily 하루에 한 번 원격 리포지토리에서 최신 SNAPSHOT과 비교
interval:정수 (정수)분 간격으로 원격 리포지토리에서 최신 SNAPSHOT과 비교
never 원격 리포지토리와 최신 SNAPSHOT을 비교하지 않음

 


Gradle

 gradle은 maven과 약간 차이가 있다.

 첫번째는 gradle은 기본적으로 라이브러리를 24시간동안 캐싱한다는 점이고,

 두번째는 라이브러리 의존성을 가져올 리포지토리 순서를 build.gradle에 명시할 수 있다는 것이다.

 다음은 build.gradle 의 예시이다

// 중략 //
allprojects {
    group 'com.sample.poject' 
    version serviceVersion
    configurations.all {
        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
}

def useMavenLocalFirst = false
subprojects {
    apply plugin: 'java'
    apply plugin: 'groovy'
    apply plugin: 'java-library'
    apply plugin: 'maven-publish'
    apply plugin: 'signing'
    apply plugin: 'io.spring.dependency-management'
    
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
    
    repositories {
        if (useMavenLocalFirst) {
            mavenLocal()
        }
        maven {
            credentials {
                username System.getenv('NEXUS_ID') ?: nexususer
                password System.getenv('NEXUS_PASSWORD') ?: nexuspassword
            }
            url "${nexusBaseUrl}/${nexusPublicRepository}"
            allowInsecureProtocol = true
        }
        if (!useMavenLocalFirst) {
            mavenLocal()
        }
        mavenCentral()
    }
    // 중략 //

 

RELEASE

 해당 버전으로 캐싱되어 있는 라이브러리가 있다면 빌드 시, 원격 저장소를 방문하지 않는다

 없다면 지정한 순서에 따라 원격 -> 로컬 -> 중앙 리포지토리 순서로 라이브러리를 가져올 것이다.

 

SNAPSHOT

 해당 버전으로 캐싱되어 있는 라이브러리가 있다면 빌드 시, 원격 저장소를 방문하지 않는다.

 그러나 상단에서 캐싱을 0초간 하겠다고 지정하였으므로
(  configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' }  )

 캐싱된 라이브러리를 찾을 수 없어 매번 새롭게 라이브러리를 가져와야 할 것이다.

 참고로 seconds, minutes, hours 등 다양하게 시간을 지정할 수 있다. 

 

 이때, build.gradle 에 명시한 순서에 따라원격 -> 로컬 -> 중앙 이므로 원격 리포지토리에 우선적으로 접근할 것이다.

 


 

 

 문제가 어떻게 해결되었던 것인지 이제야 알았다.

 문제가 되었던 라이브러리를 release 버전으로 종속성을 갖고 있었고, 해당 라이브러리에 버전업 없이 수정사항(클래스 추가 등)이 존재했기 때문이었다.

 

 

 

 

 

참고

 

Introduction to Repositories – Maven

Internal Repositories When using Maven, particularly in a corporate environment, connecting to the internet to download dependencies is not acceptable for security, speed or bandwidth reasons. For that reason, it is desirable to set up an internal reposito

maven.apache.org

 

 

 

Dependency Caching

The --offline command-line switch instructs Gradle to use dependency modules from the cache, regardless of whether they are due to be checked again. When running with offline, Gradle will not attempt to access the network for dependency resolution. If the

docs.gradle.org

 

728x90
반응형
LIST