Gradle 의존성

출처 : https://android.jlelse.eu/android-101-gradle-dependencies-9e2742b59f9

Gradle에서 의존성(dependency)은 `dependencies` 블록의 클로저로 선언된다.

dependencies {
    implementation "com.square.up.okhttp3:okhttp:3.9.1"
}

의존성 트리는 ./gradlew dependencies테스크에서 볼 수 있다. 직접 의존성과 추이 의존성(Transitive dependencies) 모두를 표시해준다.

+--- com.squareup.okhttp3:okhttp:3.9.1       : Direct artifact
     \--- com.squareup.okio:okio:1.6.0      : Transitive dependency

Packaging type

모든 아티팩트(artifact)들은 패키징 타입을 가진다(예를 들어 jar, aar). 아티팩트의 작성자는 발행 전에 POM에 기본 패키징 타입을 지정할 수 있다. 만약 POM에 지정되지 않았다면 다운로드시의 기본 타입은 jar가 될 것이다.

Jar (Java Archive) : 자바 클래스 파일들을 합치고 압축(zip)할 때 사용되는 패키징 파일 포멧

Aar (Android Archive) : jar와 동일하지만 추가적으로 레이아웃, drawable, AndroidManifest 파일같은 안드로이드 리소스들이 추가된다.

아티팩트를 기본 패키징 타입으로 다운로드하기 (추천)

아래 예제와 같이 의존성을 선언할 때 패키지 타입을 명시적으로 지정하지 않았다면, 아티팩트는 POM 파일에 명시된 기본 패키징 타입으로 다운로드 될 것이다.

dependencies {
   implementation "com.squareup.okhttp3:okhttp:3.9.1"
   implementation "com.android.support:percent:26.0.0"
}

Gradle은 아티팩트 okhttp를 jar로, percent를 aar로 다운로드 할 것이다. percent의 작성자는 POM 파일에 패키징 타입을 aar로 지정하였으므로 Gradle은 아티팩트를 다운로드 할 때 기본 패키징 타입을 사용할 것이다.

+--- com.squareup.okhttp3:okhttp:3.9.1
|    \--- com.squareup.okio:okio:1.6.0
\--- com.android.support:percent:26.0.0
     \--- com.android.support:support-compat:26.0.0
          \--- com.android.support:support-annotations:26.0.0

아티팩트를 특정 패키징 타입으로 다운로드하기

@type 표기를 추가하여 패키징 타입을 명시적으로 지정할 수 있다.

dependencies {
    implementation "com.squareup.okhttp3:okhttp:3.9.1@jar"
    implementation "com.android.support:percent:26.0.0@aar"
}

아티팩트 okhttp는 jar로, percent는 aar로 다운로드 된다.

+--- com.squareup.okhttp3:okhttp:3.9.1
\--- com.android.support:percent:26.0.0

하지만 추이 의존성이 다운로드되지 않은 결과 의존성 트리가 조금 달라졌다. Gradle은 이 표기가 사용되면 추이 의존성을 제외한 메인 아티팩트만을 다운로드 한다. 이를 artifact-only notation라고도 부른다.

이 이슈를 해결하기 위한 방법이 몇 개 있다:

  • transitive=true를 사용하여 추이 의존성을 다운로드할 것을 gradle에게 명시적으로 알린다.
dependencies {
    implementation("com.squareup.okhttp3:okhttp:3.9.1@jar") {
        transitive true
    }   
    implementation("com.android.support:percent:26.0.0@aar"){
        transitive true
    }
}
  • Gradle은 다른 직/간접 의존성이 동일한 추이 의존성을 가지고 있다면 자동으로 이 문제를 해결해준다.

예를 들어 percent의 결여된 의존성들은 recyclerview-7를 통해 자동적으로 해결된다.

dependencies {
    implementation("com.android.support:percent:26.0.0@aar")
    implementation "com.android.support:recyclerview-v7:26.0.0"
}
  • 결여된 의존성 각각을 하나 하나 명시적으로 선언한다.
dependencies {
    implementation("com.squareup.okhttp3:okhttp:3.9.1@jar")  
    implementation("com.android.support:percent:26.0.0@aar")

    // transitive dependencies are declared one by one
    implementation "com.squareup.okio:okio:1.6.0"
    implementation "com.android.support:support-compat:26.0.0"
}

주어진 패키징 타입의 아티팩트가 없다면?

Gradle은 아티팩트의 다운로드 시도를 할 것이지만 저장소에는 지정된 패키징 타입이 존재하지 않으므로 결국 실패할 것이다.

dependencies {
    implementation "com.squareup.okhttp3:okhttp:3.9.1@aar"
}

오류가 출력된다:

Failed to resolve: okhttp

지정된 추이 의존성 제외하기

충돌 상황에서는 지정된 추이 의존성을 제거할 수 있다.

다음 예제는 percent 라이브러리에서 support-annotations 추이 의존성을 제거하는 방법을 보여준다.

dependencies {
  implementation("com.android.support:percent:26.0.0") {
    exclude group:'com.android.support',module:'support-annotations'
  }
}

의존성 트리에는 support-annotations가 더 이상 존재하지 않음을 관찰 할 수 있다.

추이 의존성 해결 전략

서로 다른 아티팩트 버전이 동시에 선언 된다면 Gradle은 최신 버전을 선택하여 해결하려 할 것이다.

다음 예제에서는 support-annotations의 최신 버전이 명시적으로 선언되어 있다. percent 또한 낮은 버전의 동일한 의존성을 가진다.

dependencies { 
    implementation "com.android.support:support-annotations:27.0.2"
    implementation "com.android.support:percent:26.0.0"
}

추이 의존성이 최신 버전을 가르킴을 관찰 할 수 있다.

+-- com.android.support:support-annotations:27.0.2
\-- com.android.support:percent:26.0.0
    \-- com.android.support:support-compat:26.0.0
        \-- com.android.support:support-annotations:26.0.0 -> 27.0.2

버전이 26.0.0 vs 26.0.0-alpha 처럼 수식어를 가지고 있으면 어떤 일이 벌어질까?

테스트를 해보니 Gradle은 maven과 동일한 버전 비교 방법을 가지고 있는 듯 하다. For the complete list of how version ordering works, check maven version order specification.

results matching ""

    No results matching ""