Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

빌드 종속성 추가

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

종속 항목 유형

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

예를 들어 앱 모듈의 다음 build.gradle 파일에는 세 가지 종속 항목 유형이 포함되어 있습니다.

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')

'mylibrary'라는 Android 라이브러리 모듈에 종속 항목을 선언합니다. 이 이름은 settings.gradle 파일의 include:로 정의한 라이브러리 이름과 일치해야 합니다. 앱을 빌드할 때 빌드 시스템은 라이브러리 모듈을 컴파일하고 컴파일된 콘텐츠를 APK에 패키징합니다.

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

Gradle은 build.gradle 파일에 관한 경로를 읽기 때문에 프로젝트의 module_name/libs/ 디렉터리 내의 JAR 파일 종속성을 선언합니다.

또는 다음과 같이 개별 파일을 지정할 수도 있습니다.

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 를 클릭할 때 또는 빌드를 실행할 때) 원격 사이트에서 가져옵니다.

네이티브 종속 항목

Android Gradle 플러그인 4.0부터는 이 문서에서 설명하는 방식으로 네이티브 종속 항목을 가져올 수도 있습니다.

네이티브 라이브러리를 노출하는 AAR에 따라 externalNativeBuild에서 사용하는 빌드 시스템에서 자동으로 사용할 수 있게 됩니다. 코드에서 라이브러리에 액세스하려면 네이티브 빌드 스크립트에서 라이브러리에 연결해야 합니다. 자세한 내용은 네이티브 종속 항목 사용을 참조하세요.

종속 항목 구성

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(현재는 지원 중단됨)와 동일하게 작동합니다.

참고: compileOnly 구성은 AAR 종속 항목과 함께 사용할 수 없습니다.

runtimeOnly apk Gradle은 런타임 동안 사용하기 위해 빌드 출력에만 종속 항목을 추가합니다. 즉 컴파일 클래스 경로에는 추가되지 않습니다. 이 구성은 apk(현재는 지원 중단됨)와 동일하게 동작합니다.
annotationProcessor compile 주석 프로세서인 라이브러리에 종속 항목을 추가하려면 annotationProcessor 구성을 사용하여 주석 프로세서 클래스 경로에 추가해야 합니다. 이 구성을 사용하면 컴파일 클래스 경로를 주석 프로세서 클래스 경로에서 분리하여 빌드 성능이 개선되기 때문입니다. Gradle은 컴파일 클래스 경로에서 주석 프로세서를 찾으면 컴파일 회피를 비활성화하며 이는 빌드 시간에 부정적인 영향을 미칩니다(Gradle 5.0 이상에서는 컴파일 클래스 경로에서 발견된 주석 프로세서를 무시합니다).

JAR 파일에 다음 파일이 포함되어 있으면 Android Gradle 플러그인은 종속 항목이 주석 프로세서라고 가정합니다.
META-INF/services/javax.annotation.processing.Processor 플러그인이 컴파일 클래스 경로에 있는 주석 프로세서를 감지하면 빌드 오류가 발생합니다.
lintChecks 프로젝트를 빌드할 때 Gradle에서 실행할 린트 검사를 포함하려면 이 구성을 사용합니다.

참고: Android Gradle 플러그인 3.4.0 이상을 사용할 때 이 종속 항목 구성은 더 이상 린트 검사를 Android 라이브러리 프로젝트에 패키징하지 않습니다. AAR 라이브러리에 린트 검사 종속 항목을 포함하려면 아래 설명한 lintPublish 구성을 사용하세요.

lintPublish Gradle에서 lint.jar 파일로 컴파일하고 AAR에 패키징할 린트 검사를 포함하려면 Android 라이브러리 프로젝트에서 이 구성을 사용하세요. 이렇게 하면 AAR을 사용하는 프로젝트에서 이 린트 검사도 적용합니다. 이전에 lintChecks 종속 항목 구성을 사용하여 게시된 AAR에 린트 검사를 포함한 경우 이 종속 항목을 이전하여 대신 lintPublish 구성을 사용해야 합니다.

dependencies {
  // Executes lint checks from the ':checks' project
  // at build time.
  lintChecks project(':checks')
  // Compiles lint checks from the ':checks-to-publish'
  // into a lint.jar file and publishes it to your
  // Android library.
  lintPublish project(':checks-to-publish')
}

위의 구성은 종속 항목을 모든 빌드 변형에 적용합니다. 대신 특정 빌드 변형 소스 세트 또는 테스트 소스 세트에만 종속 항목을 선언하려면 구성 이름을 대문자로 지정하고 빌드 변형이나 테스트 소스 세트의 이름을 접두어로 붙여야 합니다.

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

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

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

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용 Android 플러그인 3.0.0 이상에서는 더 이상 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를 구현하는 클래스를 만든 후에는 아래와 같이 annotationProcessorOptions.compilerArgumentProvider 속성을 사용하여 클래스를 초기화하고 Android 플러그인에 전달해야 합니다.

// 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'
}

참고: 종속 항목 제외 섹션의 원본 코드 샘플과 같이 종속 항목 블록에서 exclude 키워드를 사용하여 테스트 구성에서만 사용하고 다른 구성에는 포함되지 않는 전이 종속 항목을 생략할 수 있습니다.

변형 인식 종속 항목 관리 사용

Android 플러그인 3.0.0 이상에는 라이브러리를 사용할 때 자동으로 변형을 매칭하는 새로운 종속 항목 메커니즘이 포함됩니다. 즉 앱의 debug 변형에서 라이브러리의 debug 변형 등을 자동으로 사용합니다. 이 기능은 버전을 사용할 때도 작동하며 앱의 freeDebug 변형에서 라이브러리의 freeDebug 변형을 사용합니다.

플러그인이 정확하게 변형을 매칭하려면 직접 매칭이 불가능한 경우 매칭 폴백을 제공해야 합니다. 앱에서 'staging'이라는 빌드 유형을 구성하지만 라이브러리 종속 항목 중 하나에서는 구성하지 않는 경우를 고려하세요. 앱의 'staging' 버전을 빌드하려고 시도할 때 플러그인에서는 사용할 라이브러리 버전을 알 수 없고 다음과 유사한 오류 메시지가 표시됩니다.

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

변형 매칭과 관련된 빌드 오류 해결

플러그인에는 DSL 요소가 포함되어 있어 Gradle이 앱과 종속 항목 간의 직접적인 변형 매칭이 불가능한 상황을 해결하는 방법을 제어할 수 있습니다. 변형 인식 종속 항목 매칭과 관련된 특정 빌드 오류를 해결하기 위해 사용해야 하는 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 스튜디오 프로젝트에서는 아래와 같이 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 라이브러리는 다음과 같습니다.

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 저장소 패키지를 다운로드해야 합니다.

그런 다음 평소와 같이 이러한 라이브러리를 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_A(LIB_D에 종속됨)는 LIB_B보다 우선순위가 높기 때문에 LIB_D는 여전히 LIB_B보다 우선순위가 높게 됩니다.

다양한 프로젝트 소스/종속 항목의 매니페스트를 병합하는 방법은 여러 매니페스트 파일 병합에서 자세히 알아보세요.

모듈 종속 항목 보기

일부 직접 종속 항목은 자체 종속 항목을 가질 수도 있습니다. 이런 종속 항목을 전이 종속 항목이라고 합니다. 각 전이 종속 항목은 수동으로 선언하지 않아도 Gradle에서 자동으로 수집하여 추가합니다. Gradle용 Android 플러그인에서 주어진 모듈을 위해 Gradle이 해결하는 종속 항목 목록을 표시합니다.

각 모듈의 보고서에서는 또한 빌드 변형, 테스트 소스 세트 및 클래스 경로를 기반으로 종속 항목을 그룹화합니다. 다음은 디버그 빌드 변형의 앱 모듈 런타임 클래스 경로 및 계측 테스트 소스 세트의 컴파일 클래스 경로를 위한 샘플 보고서입니다.

debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...

debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...

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

  1. View > Tool Windows > Gradle을 선택하거나 도구 창 모음에서 Gradle 을 클릭합니다.
  2. AppName > Tasks > android를 펼치고 androidDependencies를 더블클릭합니다. Gradle에서 작업을 실행하면 Run 창이 열리고 출력 내용이 표시됩니다.

Gradle의 종속 항목 관리에 관한 자세한 내용은 Gradle 사용자 가이드의 종속 항목 관리 기본 사항을 참조하세요.

종속 항목 해결 오류 수정

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

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

중복 종속 항목을 쉽게 찾을 수 없으면 다음과 같이 Android 스튜디오의 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. 여러 클래스 경로에 표시되는 종속 항목의 버전 번호는 이 계층 구조에 따라 매칭해야 합니다.

예를 들어 앱에서 implementation 종속 항목 구성을 사용하여 종속 항목의 한 버전을 포함하고 라이브러리 모듈에서는 runtimeOnly 구성을 사용하여 종속 항목의 다른 버전을 포함할 때 여러 클래스 경로에 동일한 종속 항목의 다른 버전이 표시되는 경우 충돌이 발생할 수 있습니다.

런타임 및 컴파일 시간 클래스 경로의 종속 항목을 해결할 때 Android Gradle 플러그인 3.3.0 이상에서는 특정 다운스트림 버전의 충돌을 자동으로 수정하려고 합니다. 예를 들어 런타임 클래스 경로에 라이브러리 A 버전 2.0이 포함되고 컴파일 클래스 경로에 라이브러리 A 버전 1.0이 포함된 경우 플러그인에서 오류를 방지하기 위해 컴파일 클래스 경로의 종속 항목을 라이브러리 A 버전 2.0으로 자동 업데이트합니다.

그러나 런타임 클래스 경로에 라이브러리 버전 1.0이 포함되고 컴파일 클래스 경로에 라이브러리 A 버전 2.0이 포함된 경우에는 플러그인에서 컴파일 클래스 경로의 종속 항목을 라이브러리 A 버전 1.0으로 다운그레이드하지 않으며 다음과 유사한 오류가 계속 발생합니다.

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.

이 문제를 해결하려면 다음 중 한 가지를 따르세요.

  • 원하는 종속 항목을 라이브러리 모듈에 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 {
            ...
        }
    }
}