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.