빌드 종속성 추가

Android Studio의 Gradle 빌드 시스템에서는 외부 바이너리 또는 다른 라이브러리 모듈을 빌드에 종속성으로 쉽게 포함할 수 있습니다. 종속성은 컴퓨터 또는 원격 저장소에 위치할 수 있으며, 종속성에서 선언하는 과도적 종속성도 자동으로 포함됩니다. 이 페이지에서는 Gradle용 Android 플러그인에 따른 동작 및 구성에 대한 자세한 내용을 포함하여 Android 프로젝트에서 종속성을 사용하는 방법을 설명합니다. Gradle 종속성에 대한 보다 심층적인 개념적 가이드는 종속성 관리를 위한 Gradle 가이드를 참조하세요. 그러나 Android 프로젝트에서는 이 페이지에 정의된 종속성 구성만 사용해야 합니다.

종속성 유형

프로젝트에 종속성을 추가하려면 implementation과 같은 종속성 구성을 build.gradle 파일의 dependencies 블록에 정의합니다.

예를 들어 다음의 앱 모듈 build.gradle 파일에는 3가지 서로 다른 종속성 유형이 포함되어 있습니다.

apply plugin: 'com.android.application'

android { ... }

dependencies {
    // Dependency on a local library module
    implementation project(":mylibrary")

    // Dependency on local binaries
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // Dependency on a remote binary
    implementation 'com.example.android:app-magic:12.3'
}

이들은 각각 다음과 같이 서로 다른 종류의 라이브러리 종속성을 요청합니다.

로컬 라이브러리 모듈 종속성
implementation project(':mylibrary')

이것은 Android 라이브러리 모듈 중 "mylibrary"라는 이름의 모듈에 종속성을 선언합니다(이 이름이 반드시 settings.gradle 파일의 include:로 정의한 라이브러리 이름과 일치해야 함). 앱을 빌드할 때 빌드 시스템이 라이브러리 모듈을 컴파일하여 그 결과로 컴파일된 콘텐츠를 APK에서 패키징합니다.

로컬 바이너리 종속성
implementation fileTree(dir: 'libs', include: ['*.jar'])

Gradle은 프로젝트 module_name/libs/ 디렉토리 내의 JAR 파일에 종속성을 선언합니다(Gradle은 build.gradle 파일에 상대적인 경로를 읽기 때문).

또는, 다음과 같이 각 파일을 지정할 수 있습니다.

implementation files('libs/foo.jar', 'libs/bar.jar')
원격 바이너리 종속성
implementation 'com.example.android:app-magic:12.3'

위의 내용을 길게 풀면 다음과 같습니다.

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'

"com.example.android" 네임스페이스 그룹 안에 있는 "app-magic" 라이브러리의 12.3 버전에 대한 종속성을 선언합니다.

참고: 이와 같은 원격 종속성은 Gradle이 라이브러리를 찾을 대상인 원격 저장소가 필요합니다. 라이브러리가 로컬에 존재하지 않는다면 빌드에 필요할 경우 Gradle이 원격 사이트에서 가져옵니다(예: Sync Project with Gradle Files 을 클릭하거나 빌드를 실행할 경우).

종속성 구성

dependencies 블록에서 여러 가지 다양한 종속성 구성을 사용하여 라이브러리 종속성을 선언할 수 있습니다(예: 위의 implementation). 각 종속성 구성은 Gradle에 종속성 사용 방법에 대한 서로 다른 명령을 제공합니다. 다음 표는 Android 프로젝트에서 종속성에 사용할 수 있는 각각의 구성을 설명한 것입니다. 또한 이 표에서는 이러한 구성을 Android Gradle 플러그인 3.0.0부터 지원이 중단된 구성과 비교하기도 하였습니다.

새 구성 지원 중단된 구성 동작
implementation compile Gradle은 종속성을 컴파일 클래스 경로에 추가하여 종속성을 빌드 출력에 패키징합니다. 다만 모듈이 implementation 종속성을 구성하는 경우, 이것은 Gradle에 개발자가 모듈이 컴파일 시 다른 모듈로 유출되는 것을 원치 않는다는 것을 알려줍니다. 즉, 종속성은 런타임 시 다른 모듈에서만 이용할 수 있습니다.

api 또는 compile(지원 중단됨) 대신 이 종속성 구성을 사용하면 빌드 시스템이 재컴파일해야 하는 모듈의 수가 줄어들기 때문에 빌드 시간이 상당히 개선될 수 있습니다. 예를 들어, implementation 종속성이 API를 변경하면 Gradle은 해당 종속성과 그 종속성에 직접 연결된 모듈만 다시 컴파일합니다. 대부분의 앱과 테스트 모듈은 이 구성을 사용해야 합니다.

api compile Gradle은 컴파일 클래스 경로 및 빌드 출력에 종속성을 추가합니다. 모듈에 api 종속성을 포함하면 다른 모듈에 그 종속성을 과도적으로 내보내기를 원하며 따라서 런타임과 컴파일 시 모두 종속성을 사용할 수 있다는 사실을 Gradle에 알려줄 수 있습니다.

이 구성은 compile(현재 지원 중단됨)과 똑같이 동작합니다. 다만 이것은 주의해서 사용해야 하며 다른 업스트림 소비자에게 일시적으로 내보내는 종속성만 함께 사용해야 합니다. 그 이유는 api 종속성이 외부 API를 변경하면 Gradle이 컴파일 시 해당 종속성에 액세스할 권한이 있는 모듈을 모두 다시 컴파일하기 때문입니다. 그러므로 api 종속성이 많이 있으면 빌드 시간이 상당히 증가합니다. 종속성의 API를 별도의 모듈에 노출시키고 싶은 것이 아니라면 라이브러리 모듈은 implementation 종속성을 대신 사용해야 합니다.

compileOnly provided Gradle이 컴파일 클래스 경로에만 종속성을 추가합니다(빌드 출력에 추가되지 않음). Android 모듈을 생성할 때는 유용하고 컴파일 시 종속성이 필요하지만 런타임에 반드시 종속성이 있어야 할 필요는 없습니다.

즉, 이 구성을 사용할 경우 라이브러리 모듈에 종속성이 사용 가능한지 확인하는 런타임 조건을 포함하고, 종속성이 제공되지 않더라도 계속 작동할 수 있도록 동작을 적절히 변경해야 합니다. 이 방법을 사용하면 중요하지 않은 임시 종속성을 추가하지 않으므로 최종 APK의 용량이 줄어듭니다. 이 구성은 provided(현재 지원 중단됨)와 동일하게 동작합니다.

runtimeOnly apk Gradle이 런타임 시에 사용하도록 빌드 출력에만 종속성을 추가합니다. 즉, 컴파일 클래스 경로에는 추가되지 않습니다. 이 구성은 apk와 동일하게 동작합니다(지금은 지원 중단됨).
annotationProcessor compile 주석 프로세서인 라이브러리에 종속성을 추가하려면 반드시 annotationProcessor 구성을 사용하여 주석 프로세서 클래스 경로에 추가해야 합니다. 그 이유는 이 구성을 사용하면 컴파일 클래스 경로를 주석 프로세서 클래스 경로와 분리하여 빌드 성능을 향상할 수 있기 때문입니다. Gradle이 컴파일 클래스 경로에서 주석 프로세서를 찾으면 빌드 시간에 부정적인 영향을 미치는 컴파일 회피를 비활성화합니다(Gradle 5.0 이상은 컴파일 클래스 경로에서 찾은 주석 프로세서를 무시합니다).

Android Gradle 플러그인은 JAR 파일에 다음 파일이 포함되어 있으면 종속성이 주석 프로세서라고 가정합니다.
META-INF/services/javax.annotation.processing.Processor 플러그인은 컴파일 클래스 경로에 있는 주석 프로세서를 감지하면 빌드 오류를 발생시킵니다.

위의 구성은 프로젝트 메인 소스 세트에 적용됩니다. 메인 소스 세트는 모든 빌드 변형에 적용됩니다. 그 대신 특정 빌드 변형 소스 세트나 테스트 소스 세트에 대해서만 종속성을 선언하고자 할 경우, 종속성 구성 이름을 대문자로 지정하고 이 이름 앞에 빌드 변형이나 테스트 소스 세트의 이름을 접두사로 붙입니다.

예를 들어 (원격 바이너리 종속성을 사용하여) implementation 종속성을 "free" 제품 버전에만 추가하는 방법은 다음과 같습니다.

dependencies {
    freeImplementation 'com.google.firebase:firebase-ads:9.8.0'
}

그러나 제품 버전 빌드 유형을 결합하는 변형에 종속성을 추가하려면 configurations 블록에서 구성 이름을 초기화해야 합니다. 다음 샘플에서는 (로컬 바이너리 종속성을 사용하여) runtimeOnly 종속성을 "freeDebug" 빌드 변형에 추가합니다.

configurations {
    // Initializes a placeholder for the freeDebugRuntimeOnly dependency
    // configuration.
    freeDebugRuntimeOnly {}
}

dependencies {
    freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar'])
}

implementation 종속성을 로컬 테스트와 계측 테스트에 추가하는 방법은 다음과 같습니다.

dependencies {
    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

그러나 특정 구성은 이 상황에 맞지 않습니다. 예를 들어, 다른 모듈에서는 androidTest를 사용할 수 없으므로 androidTestApi 구성을 사용하면 다음 경고가 나타납니다.

WARNING: Configuration 'androidTestApi' is obsolete and has been replaced with
'androidTestImplementation'.

주석 프로세서 추가

컴파일 클래스 경로에 주석 프로세서를 추가하면 다음과 유사한 오류 메시지가 나타납니다.

Error: Annotation processors must be explicitly declared now.

이 오류를 해결하려면 아래와 같이 annotationProcessor를 사용하여 종속성을 구성함으로써 프로젝트에 주석 프로세서를 추가해야 합니다.

dependencies {
    // Adds libraries defining annotations to only the compile classpath.
    compileOnly 'com.google.dagger:dagger:version-number'
    // Adds the annotation processor dependency to the annotation processor classpath.
    annotationProcessor 'com.google.dagger:dagger-compiler:version-number'
}

참고: Gradle 3.0.0+용 Android 플러그인은 이제 android-apt플러그인을 지원하지 않습니다.

주석 프로세서에 인수 전달

주석 프로세서에 인수를 전달해야 하는 경우, 모듈의 빌드 구성에 있는 AnnotationProcessorOptions 블록을 사용하면 됩니다. 예를 들어 원시 데이터 유형을 키-값 쌍으로 전달하고자 하는 경우, 아래와 같이 argument 속성을 사용합니다.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                argument "key1", "value1"
                argument "key2", "value2"
            }
        }
    }
}

그러나 Android Gradle 플러그인 3.2.0 이상을 사용할 때에는 Gradle의 CommandLineArgumentProvider인터페이스를 사용하여 파일 또는 디렉토리를 나타내는 프로세서 인수를 전달해야 합니다.

CommandLineArgumentProvider를 사용하면 개발자나 주석 프로세서 작성자가 증분 빌드 속성 유형 주석을 각 인수에 적용하여 증분 및 캐시된 클린 빌드의 정확성과 성능을 향상할 수 있습니다.

예를 들어 아래의 클래스는 CommandLineArgumentProvider를 구현하고 프로세서의 각 인수에 주석을 단 것입니다. 이 샘플은 Groovy 언어 구문을 사용하기도 하고, 모듈의 build.gradle 파일에 직접 포함됩니다.

class MyArgsProvider implements CommandLineArgumentProvider {

    // Annotates each directory as either an input or output for the
    // annotation processor.
    @InputFiles
    // Using this annotation helps Gradle determine which part of the file path
    // should be considered during up-to-date checks.
    @PathSensitive(PathSensitivity.RELATIVE)
    FileCollection inputDir

    @OutputDirectory
    File outputDir

    // The class constructor sets the paths for the input and output directories.
    MyArgsProvider(FileCollection input, File output) {
        inputDir = input
        outputDir = output
    }

    // Specifies each directory as a command line argument for the processor.
    // The Android plugin uses this method to pass the arguments to the
    // annotation processor.
    @Override
    Iterable<String> asArguments() {
        // Use the form '-Akey[=value]' to pass your options to the Java compiler.
        ["-AinputDir=${inputDir.singleFile.absolutePath}",
         "-AoutputDir=${outputDir.absolutePath}"]
    }
}

android {...}

CommandLineArgumentProvider를 구현하는 클래스를 생성한 뒤에는, 이를 초기화하여 Android 플러그인에 전달해야 합니다. 이때 아래와 같이 annotationProcessorOptions.compilerArgumentProvider 속성을 사용합니다.

// This is in your module's build.gradle file.
android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                // Creates a new MyArgsProvider object, specifies the input and
                // output paths for the constructor, and passes the object
                // to the Android plugin.
                compilerArgumentProvider new MyArgsProvider(files("input/path"),
                                         new File("output/path"))
            }
        }
    }
}

CommandLineArgumentProvider 구현이 빌드 성능을 향상하는 방법을 자세히 알아보려면 자바 프로젝트 캐싱을 읽어보세요.

주석 프로세서 오류 검사 중지

불필요한 주석 프로세서를 포함하는 종속성이 컴파일 클래스 경로상에 있는 경우, 다음 코드를 build.gradle 파일에 추가하여 오류 검사를 중지할 수 있습니다. 명심할 점은, 컴파일 클래스 경로에 추가되는 주석 프로세서는 여전히 프로세서 클래스 경로에 추가되지 않는다는 점입니다.

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath false
            }
        }
    }
}

프로젝트의 주석 프로세서를 프로세서 클래스 경로에 마이그레이션한 뒤 문제가 발생하는 경우, includeCompileClasspathtrue로 설정하여 컴파일 클래스 경로의 주석 프로세서를 허용하면 됩니다. 다만 이 속성을 true로 설정하는 것은 권장되지 않으며, 향후 Android 플러그인의 업데이트에서는 이렇게 하는 옵션이 삭제될 예정입니다.

전이 종속성 제외

앱의 범위가 커지면 다수의 종속성이 포함될 수 있습니다. 예를 들어 직접 종속성 및 전이 종속성 등이 대표적입니다(앱의 가져온 라이브러리가 종속되는 라이브러리). 더는 필요하지 않은 전이 종속성을 제외하려면 아래와 같이 exclude 키워드를 사용하면 됩니다.

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

테스트 구성에서 전이 종속성 제외

테스트에서 특정 전이 종속성을 제외해야 하는 경우, 위에 표시한 코드 샘플이 예상한 대로 작동하지 않을 수 있습니다. 이것은 테스트 구성(예: androidTestImplementation)이 모듈의 implementation 구성을 확장하기 때문입니다. 다시 말해, Gradle이 구성을 해결할 때면 항상 implementation 종속성이 포함됩니다.

따라서 테스트에서 전이 종속성을 제외하려면 아래와 같이 실행 시점에 이를 수행해야 합니다.

android.testVariants.all { variant ->
    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}

Note: 종속성 블록에서 exclude 키워드를 사용해도 되는 것은 종속성 제외 섹션의 원본 코드 샘플에서와 마찬가지입니다. 이렇게 하면 테스트 구성에만 특정되고 다른 구성에는 포함되지 않은 전이 종속성을 생략합니다.

버전을 인식하는 종속성 관리 사용

Android 플러그인 3.0.0 이상에는 라이브러리를 사용할 때 자동으로 변형을 매칭시키는 새로운 종속성 메커니즘이 포함됩니다. 즉, 앱의 debug 변형은 라이브러리의 debug 변형을 자동으로 사용하는 방식입니다. 이 기능은 버전을 사용할 때도 마찬가지로 작동하며, 앱의 freeDebug 변형은 라이브러리의 freeDebug 변형을 사용합니다.

플러그인이 정확하게 변형을 일치시키려면 직접 매칭이 불가능한 경우에 매칭 대안을 제공해야 합니다. 앱이 '스테이징'이라는 빌드 유형을 구성하려고 하는데 그 라이브러리 종속성 중 하나가 없는 경우를 가정해 보겠습니다. 플러그인이 '스테이징' 버전의 앱을 빌드하려고 시도할 때 플러그인은 어떤 버전의 라이브러리를 사용할지 알지 못하며, 다음과 같은 유사한 오류 메시지가 나타납니다.

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

변형 일치와 관련된 빌드 오류 문제 해결

플러그인에는 앱과 종속성 사이의 직접적인 변형 매칭이 불가능한 상황을 Gradle이 어떻게 해결할지 그 방법을 제어하는 DSL 요소들이 포함됩니다. 변형 인식 종속성 매칭과 관련된 빌드 오류를 해결하기 위해 어떤 DSL 속성을 사용해야 할지 확인하려면 아래 표를 참조하세요.

빌드 오류의 원인해결책

라이브러리 종속성이 없는 빌드 유형이 앱에 포함됩니다.

예를 들어, 앱에는 'staging' 빌드 유형이 포함되지만 종속성에는 'debug' 및 'release' 빌드 유형만 포함됩니다.

참고로, 앱에 없는 빌드 유형이 라이브러리 종속성에 포함된 경우는 문제가 되지 않습니다. 그 이유는 플러그인이 해당 빌드 유형을 종속성으로부터 절대 요청하지 않기 때문입니다.

matchingFallbacks를 사용하여 주어진 빌드 유형에 대한 대체 매칭을 지정합니다(아래 참조).

// In the app's build.gradle file.
android {
    buildTypes {
        debug {}
        release {}
        staging {
            // Specifies a sorted list of fallback build types that the
            // plugin should try to use when a dependency does not include a
            // "staging" build type. You may specify as many fallbacks as you
            // like, and the plugin selects the first build type that's
            // available in the dependency.
            matchingFallbacks = ['debug', 'qa', 'release']
        }
    }
}

주어진 버전 차원이 앱과 그 라이브러리 종속성에 모두 존재하는 경우, 라이브러리에 없는 버전이 앱에 포함됩니다.

예를 들어, 'tier' 버전 차원은 앱과 그 라이브러리 종속성에 모두 포함됩니다. 그러나 앱의 'tier' 차원에는 'free' 및 'paid' 버전이 포함되지만, 종속성에는 동일 차원에 대해 'demo' 및 'paid' 버전만 포함됩니다.

참고로, 주어진 버전 차원이 앱과 그 라이브러리 종속성에 모두 존재하는 경우, 앱에 없는 제품 버전이 라이브러리에 포함된 경우는 문제가 되지 않습니다. 그 이유는 플러그인이 해당 버전을 종속성으로부터 요청하지 않기 때문입니다.

matchingFallbacks를 사용하여 앱의 'free' 제품 버전에 대한 대체 매칭을 지정합니다(아래 참조).

// In the app's build.gradle file.
android {
    defaultConfig{
    // Do not configure matchingFallbacks in the defaultConfig block.
    // Instead, you must specify fallbacks for a given product flavor in the
    // productFlavors block, as shown below.
  }
    flavorDimensions 'tier'
    productFlavors {
        paid {
            dimension 'tier'
            // Because the dependency already includes a "paid" flavor in its
            // "tier" dimension, you don't need to provide a list of fallbacks
            // for the "paid" flavor.
        }
        free {
            dimension 'tier'
            // Specifies a sorted list of fallback flavors that the plugin
            // should try to use when a dependency's matching dimension does
            // not include a "free" flavor. You may specify as many
            // fallbacks as you like, and the plugin selects the first flavor
            // that's available in the dependency's "tier" dimension.
            matchingFallbacks = ['demo', 'trial']
        }
    }
}

앱에 없는 버전 차원이 라이브러리 종속성에 포함됩니다.

예를 들어, 라이브러리 종속성에는 'minApi' 차원에 대한 버전이 포함되지만, 앱에는 'tier' 차원에 대한 버전만 포함됩니다. 따라서 'freeDebug' 버전의 앱을 빌드하려는 경우, 플러그인은 'minApi23Debug' 또는 'minApi18Debug' 버전의 종속성 사용 여부를 알지 못합니다.

참고로, 라이브러리 종속성에 없는 버전 차원이 앱에 포함된 경우는 문제가 되지 않습니다. 그 이유는 종속성에 있는 차원만의 버전을 플러그인이 매칭시키기 때문입니다. 예를 들어, ABI에 대한 차원이 종속성에 포함되지 않은 경우, 'freeX86Debug' 버전의 앱은 그냥 'freeDebug' 버전의 종속성을 사용합니다.

defaultConfig 블록의 missingDimensionStrategy를 사용하여 누락된 각 차원으로부터 플러그인이 선택해야 하는 기본 버전을 지정합니다(아래 샘플 참조). 또한, productFlavors 블록에서 선택한 내용을 재정의할 수 있으며 이 경우 각 버전은 누락된 차원에 대해 각기 다른 매칭 전략을 지정할 수 있습니다.

// In the app's build.gradle file.
android {
    defaultConfig{
    // Specifies a sorted list of flavors that the plugin should try to use from
    // a given dimension. The following tells the plugin that, when encountering
    // a dependency that includes a "minApi" dimension, it should select the
    // "minApi18" flavor. You can include additional flavor names to provide a
    // sorted list of fallbacks for the dimension.
    missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
    // You should specify a missingDimensionStrategy property for each
    // dimension that exists in a local dependency but not in your app.
    missingDimensionStrategy 'abi', 'x86', 'arm64'
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // You can override the default selection at the product flavor
            // level by configuring another missingDimensionStrategy property
            // for the "minApi" dimension.
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        }
        paid {}
    }
}

Wear OS 앱 종속성 구성

Wear OS 모듈의 종속성 구성은 다른 모든 모듈에서와 비슷합니다. 다시 말해, 여기에서도 implementationcompileOnly와 같은 동일한 종속성 구성을 사용합니다.

Wear 모듈은 변형 인식 종속성 관리도 지원합니다. 그러므로 기본 앱 모듈에 Wear 모듈의 종속성이 있는 경우, 기본 모듈의 각 변형이 Wear 모듈의 일치하는 변형을 소비합니다. 단 한 가지 Wear 모듈의 종속성 하나로만 단순한 앱을 빌드하는 경우, 모듈이 기본 모듈과 같은 변형을 구성하며 이때는 아래와 같이 기본 모듈의 build.gradle 파일에서 wearApp 구성을 지정해야 합니다.

dependencies {
    // If the main and Wear app modules have the same variants,
    // variant-aware dependency management automatically matches
    // variants of the main app module with that of the wear module.
    wearApp project(':wearable')
}

Wear 모듈이 여러 개이고 앱 버전별로 서로 다른 Wear 모듈을 지정하고자 하는 경우, 다음과 같이 flavorWearApp 구성을 사용하면 됩니다(다만, wearApp 구성을 사용하는 다른 종속성을 포함하면 안 됨).

dependencies {
    paidWearApp project(':wear1')
    demoWearApp project(':wear1')
    freeWearApp project(':wear2')
}

원격 저장소

종속성이 로컬 라이브러리나 파일 트리 외에 다른 것일 경우, Gradle은 build.gradle파일의 repositories 블록에 지정된 온라인 저장소에 있는 파일을 찾습니다. 각 저장소를 나열하는 순서에 따라 Gradle이 각 프로젝트 종속성의 저장소를 검색하는 순서가 결정됩니다. 예를 들어 어느 종속성을 저장소 A와 B 양쪽에서 모두 이용할 수 있고 개발자가 A를 먼저 나열한 경우, Gradle은 해당 종속성을 저장소 A에서 다운로드합니다.

기본적으로 새 Android Studio 프로젝트는 Google Maven 저장소와 JCenter를 프로젝트의 최상위 build.gradle 파일에 있는 저장소 위치로 지정합니다(아래 참조).

allprojects {
    repositories {
        google()
        jcenter()
    }
}

Maven 중앙 저장소에 있는 파일을 원할 경우에는 mavenCentral()을 추가하고 로컬 저장소에 있는 파일을 원할 경우에는 mavenLocal()을 사용합니다.

allprojects {
    repositories {
        google()
        jcenter()
        mavenCentral()
        mavenLocal()
    }
}

또는, 다음과 같이 각 Maven이나 Ivy 저장소를 선언할 수 있습니다.

allprojects {
    repositories {
        maven {
            url "https://repo.example.com/maven2"
        }
        maven {
            url "file://local/repo/"
        }
        ivy {
            url "https://repo.example.com/ivy"
        }
    }
}

자세한 내용은 Gradle 저장소 가이드를 참조하세요.

Google Maven 저장소

다음 Android 라이브러리의 가장 최근 버전은 Google Maven 저장소에서 제공됩니다.

Google Maven 저장소 색인에서 모든 이용 가능한 아티팩트를 확인할 수 있습니다 (아래의 프로그램 액세스 참조).

빌드에 위의 라이브러리 중 하나를 추가하려면 최상위 build.gradle 파일에 Google의 Maven 저장소를 포함합니다.

allprojects {
    repositories {
        google()

        // If you're using a version of Gradle lower than 4.1, you must instead use:
        // maven {
        //     url 'https://maven.google.com'
        // }
        // An alternative URL is 'https://dl.google.com/dl/android/maven2/'
    }
}

그런 다음, 모듈의 dependencies 블록에 원하는 라이브러리를 추가합니다. 예를 들어 appcompat library는 다음과 같은 모습입니다.

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
}

그러나 위 라이브러리의 구 버전을 사용하려고 할 때 종속성에 오류가 발생하면 Maven 저장소에서 해당 버전을 제공하지 않는 경우이므로, 오프라인 저장소에서 라이브러리를 가져와야 합니다.

프로그래밍 방식 액세스

Google의 Maven 아티팩트에 프로그래밍 방식으로 액세스하려면 maven.google.com/master-index.xml에서 아티팩트 그룹의 XML 목록을 가져옵니다. 그러면 모든 그룹에 대해 다음 경로에서 라이브러리 이름과 버전을 볼 수 있습니다.

maven.google.com/group_path/group-index.xml

예를 들어 android.arch.lifecycle 그룹의 라이브러리는 maven.google.com/android/arch/lifecycle/group-index.xml에 나열됩니다.

또한 다음 경로에서 POM과 JAR 파일을 다운로드할 수 있습니다.

maven.google.com/group_path/library/version /library-version.ext

예: maven.google.com/android/arch/lifecycle/compiler/1.0.0/compiler-1. 0.0.pom

SDK Manager의 오프라인 저장소

Google Maven 저장소에서 제공하지 않는 라이브러리(일반적으로 구 버전 라이브러리)는 SDK Manager에서 오프라인 Google Repository 패키지를 다운로드해야 합니다.

그런 다음, 평소와 같이 dependencies 블록에 라이브러리를 추가합니다.

오프라인 라이브러리는 android_sdk/extras/에 저장됩니다.

종속성 순서

종속성을 나열하는 순서는 각각의 우선순위를 나타냅니다. 첫 번째 라이브러리는 두 번째보다 우선순위가 높고, 두 번째 라이브러리는 세 번째보다 우선순위가 높습니다. 이 순서는 라이브러리에서 리소스 또는 매니페스트 요소를 앱에 병합할 때 중요합니다.

예를 들어 프로젝트가 다음을 선언할 경우:

  • LIB_ALIB_B에 대한 종속성(언급된 순서)
  • LIB_ALIB_CLIB_D에 종속됨 (해당 순서로)
  • LIB_BLIB_C에 종속됨

그러면 일반 종속성 순서는 다음과 같습니다.

  1. LIB_A
  2. LIB_D
  3. LIB_B
  4. LIB_C

이렇게 하면 LIB_ALIB_B가 모두 LIB_C를 재정의할 수 있습니다. 또한 LIB_DLIB_B보다 여전히 우선순위가 높습니다. (LIB_D에 종속된) LIB_ALIB_B보다 우선순위가 높기 때문입니다.

다양한 프로젝트 소스/종속성에서 매니페스트를 병합하는 방법에 대한 자세한 내용은 여러 매니페스트 파일 병합을 참조하세요.

종속성 트리 보기

일부 직접 종속성은 자체적인 종속성을 가질 수도 있습니다. 이런 종속성을 과도적 종속성이라고 합니다. 각 과도적 종속성을 수동으로 선언할 필요가 없으며, Gradle이 이 종속성을 자동으로 수집하고 추가합니다. 프로젝트의 직접 종속성 및 과도적 종속성을 모두 시각화하기 위해 Gradle용 Android 플러그인은 각 빌드 변형테스트 소스 세트에 대해 종속성 트리를 생성하는 Gradle 작업을 제공합니다.

이 작업을 실행하려면 다음 절차를 따르세요.

  1. View > Tool Windows > Gradle를 선택합니다(또는, 도구 창 표시줄에서 Gradle 을 클릭).
  2. AppName > Tasks > android를 펼치고 androidDependencies를 두 번 클릭합니다. Gradle에서 작업을 실행하면 Run 창이 열리고 출력 내용이 표시됩니다.

다음 샘플 출력은 디버그 빌드 변형에 대한 종속성 트리를 보여주며, 이전 예시의 로컬 라이브러리 모듈 종속성과 원격 종속성을 포함합니다.

Executing tasks: [androidDependencies]
:app:androidDependencies
debug
/**
 * Both the library module dependency and remote binary dependency are listed
 * with their transitive dependencies.
 */
+--- MyApp:mylibrary:unspecified
|    \--- com.android.support:appcompat-v7:28.0.0
|         +--- com.android.support:animated-vector-drawable:28.0.0
|         |    \--- com.android.support:support-vector-drawable:28.0.0
|         |         \--- com.android.support:support-v4:28.0.0
|         |              \--- LOCAL: internal_impl-28.0.0.jar
|         +--- com.android.support:support-v4:28.0.0
|         |    \--- LOCAL: internal_impl-28.0.0.jar
|         \--- com.android.support:support-vector-drawable:28.0.0
|              \--- com.android.support:support-v4:28.0.0
|                   \--- LOCAL: internal_impl-28.0.0.jar
\--- com.android.support:appcompat-v7:28.0.0
     +--- com.android.support:animated-vector-drawable:28.0.0
     |    \--- com.android.support:support-vector-drawable:28.0.0
     |         \--- com.android.support:support-v4:28.0.0
     |              \--- LOCAL: internal_impl-28.0.0.jar
     +--- com.android.support:support-v4:28.0.0
     |    \--- LOCAL: internal_impl-28.0.0.jar
     \--- com.android.support:support-vector-drawable:28.0.0
          \--- com.android.support:support-v4:28.0.0
               \--- LOCAL: internal_impl-28.0.0.jar
...

Gradle에서 종속성 관리에 대한 자세한 내용은 Gradle 사용자 가이드의 [종속성 관리 기본 사항] 을 (http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html) 참조하세요.

종속성 해결 오류 수정

앱 프로젝트에 여러 종속성을 추가할 때 이러한 직접 종속성 및 전이 종속성이 서로 충돌할 수 있습니다. Android Gradle 플러그인은 이러한 충돌을 적절히 해결하려 하지만, 일부 충돌은 컴파일 시간 또는 런타임 오류를 초래할 수 있습니다.

어느 종속성이 오류의 원인인지 조사하려면 앱 종속성 트리를 검사하고 1회 이상 나타났거나 충돌 버전이 있는 종속성을 찾습니다.

중복 종속성을 쉽게 찾을 수 없다면 다음과 같이 Android Studio의 UI를 사용해 중복 클래스를 포함하는 종속성을 검색합니다.

  1. 메뉴 바에서 Navigate > Class를 선택합니다.
  2. 팝업 검색 대화상자에서 Include non-project items 옆에 있는 상자를 선택합니다.
  3. 빌드 오류에 나타난 클래스의 이름을 입력합니다.
  4. 클래스를 포함하는 종속성의 결과를 조사합니다.

다음 섹션은 개발자가 마주할 수 있는 여러 종속성 해결 오류 유형과 수정 방법을 설명합니다.

중복 클래스 오류 수정

한 클래스가 런타임 클래스 경로에 두 번 이상 나타나면 다음과 같은 오류 메시지가 표시됩니다.

Program type already present com.example.MyClass

이 오류는 일반적으로 다음 중 하나의 상황에서 발생합니다.

  • 바이너리 종속성이 앱에 직접 종속성으로 포함된 라이브러리를 포함합니다. 예를 들어 앱이 라이브러리 A와 라이브러리 B에 대한 종속성을 선언했는데 바이너리에서 라이브러리 A가 이미 라이브러리 B를 포함하고 있는 경우가 해당됩니다.
    • 이 문제를 해결하려면 라이브러리 B를 직접 종속성으로 삭제하세요.
  • 앱의 동일한 라이브러리에 로컬 바이너리 종속성과 원격 바이너리 종속성이 있습니다.
    • 이 문제를 해결하려면 바이너리 종속성 중 하나를 삭제하세요.

클래스 경로간 충돌 수정

Gradle이 클래스 경로를 해결할 때에는 우선 런타임 클래스 경로를 해결하고 그 결과를 사용하여 컴파일 클래스 경로에 추가할 종속성 버전을 결정합니다. 바꿔 말하면 런타임 클래스 경로가 다운스트림 클래스 경로의 동일한 종속성에 필요한 버전 번호를 결정한다고 할 수 있습니다.

앱의 런타임 클래스 경로는 Gradle이 앱의 테스트 APK의 런타임 클래스 경로에서 종속성을 매칭하는 데 필요한 버전 번호를 결정하기도 합니다. 클래스 경로의 계층 구조를 설명한 것이 그림 1입니다.

그림 1. 복수의 클래스 경로에 걸쳐 나타나는 종속성의 버전 번호는 반드시 이 계층 구조에 따라 일치해야 합니다.

복수의 클래스 경로에 걸쳐 같은 종속성의 상충되는 버전이 나타나는 경우, 다음과 같은 오류가 표시될 수 있습니다.

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.

이 충돌은 예를 들어 앱에 implementation 종속성 구성 을 사용하는 종속성의 한 버전이 포함되고 라이브러리 모듈에는 runtimeOnly 구성을 사용하는 그 종속성의 다른 버전이 포함된 경우 나타납니다. 이 문제를 해결하려면, 다음 중 한 가지를 수행합니다.

  • 종속성의 원하는 버전을 라이브러리 모듈에 api 종속성으로 포함합니다. 다시 말해 이 종속성을 선언하는 것은 라이브러리 모듈뿐이지만, 앱 모듈도 그 종속성의 API에 일시적으로 액세스 권한을 가지게 됩니다.
  • 아니면 두 모듈에서 모두 종속성을 선언할 수도 있지만 대신 각 모듈이 해당 종속성의 같은 버전을 사용해야 합니다. 프로젝트 전체에 걸쳐 각 종속성이 일관된 버전을 유지하도록 하려면 프로젝트 범위 속성 구성 을 고려할 만합니다.

사용자설정 빌드 논리 적용

이 섹션에서는 Android Gradle 플러그인을 확장하고자 할 때 또는 자기만의 플러그인을 작성하고자 할 때 유용한 고급 주제를 설명합니다.

변형 종속성을 사용자설정 논리로 게시

라이브러리에는 다른 프로젝트 또는 하위 프로젝트에서 사용하고자 하는 기능이 있을 수 있습니다. 라이브러리 게시는 해당 라이브러리를 소비자가 이용할 수 있게 해주는 프로세스입니다. 라이브러리는 컴파일 시 및 런타임에 소비자가 액세스할 수 있는 종속성을 제어할 수 있습니다.

각 클래스 경로의 전이 종속성을 보관하는 구성이 두 개 있는데, 소비자는 이를 사용하여 아래와 같이 라이브러리를 소비해야 합니다.

  • variant_nameApiElements: 이 구성은 컴파일 시 소비자가 이용 가능한 전이 종속성을 보관합니다.
  • variant_nameRuntimeElements: 이 구성은 런타임에 소비자가 이용 가능한 전이 종속성을 보관합니다.

다양한 구성 간 관계에 대해 자세히 알아보려면 자바 라이브러리 플러그인 구성으로 이동하세요.

사용자설정 종속성 문제 해결 전략

한 프로젝트에는 같은 라이브러리의 두 가지 다른 버전에 대한 종속성이 포함될 수 있으며 이 때문에 종속성 충돌이 발생할 수 있습니다. 예를 들어 프로젝트가 모듈 A의 버전 1과 모듈 B의 버전 2에 종속되고 모듈 A는 일시적으로 모듈 B의 버전 3에 종속된다면 종속성 버전 충돌이 발생하게 됩니다.

Android Gradle 플러그인은 이러한 충돌을 해결하기 위하여 다음과 같은 종속성 해결 전략을 사용합니다. 즉 플러그인이 종속성 그래프에 같은 모듈의 서로 다른 버전이 포함된 것을 감지하면 기본적으로 버전 번호가 가장 높은 것을 선택하는 것입니다.

다만 이 전략이 의도한 대로 통하지 않을 때도 있습니다. 종속성 해결 전략을 사용자 설정하려면 다음 구성을 사용하여 작업에 필요한 변형의 특정 종속성을 해결해야 합니다.

  • variant_nameCompileClasspath: 이 구성에는 주어진 변형의 컴파일 클래스 경로에 맞는 해결 전략이 포함되어 있습니다.
  • variant_nameRuntimeClasspath: 이 구성에는 주어진 변형의 런타임 클래스 경로에 맞는 해결 전략이 포함되어 있습니다.

Android Gradle 플러그인에는 각 변형의 구성 객체에 액세스하는 데 사용할 수 있는 getter가 포함되어 있습니다. 따라서 변형 API를 사용하여 아래와 같이 종속성 해결을 쿼리할 수 있습니다.

android {
    applicationVariants.all { variant ->
        // Return compile configuration objects of a variant.
        variant.getCompileConfiguration().resolutionStrategy {
        // Use Gradle's ResolutionStrategy API
        // to customize how this variant resolves dependencies.
            ...
        }
        // Return runtime configuration objects of a variant.
        variant.getRuntimeConfiguration().resolutionStrategy {
            ...
        }
        // Return annotation processor configuration of a variant.
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {
            ...
        }
    }
}