KMP용 Android Gradle 라이브러리 플러그인 설정

com.android.kotlin.multiplatform.library Gradle 플러그인은 Kotlin 멀티플랫폼 (KMP) 라이브러리 모듈에 Android 타겟을 추가하기 위해 공식적으로 지원되는 도구입니다. 프로젝트 구성을 간소화하고 빌드 성능을 개선하며 Android 스튜디오와의 통합을 개선합니다.

이전 접근 방식은 이제 Android-KMP 플러그인이라고도 하는 플러그인으로 대체되어 지원 중단됩니다. KMP용 com.android.library 플러그인을 계속 사용하면 JetBrains에서 더 이상 지원하지 않으며 향후 업데이트와 개선사항의 혜택을 누릴 수 없습니다.

이 플러그인을 적용하려면 Android-KMP 플러그인 적용 섹션을 참고하세요. 기존 API에서 이전해야 하는 경우 이전 가이드를 확인하세요.

주요 기능 및 차이점

Android-KMP 플러그인은 KMP 프로젝트에 맞게 특별히 조정되었으며 다음과 같은 여러 주요 측면에서 표준 com.android.library 플러그인과 다릅니다.

  • 단일 변형 아키텍처: 플러그인은 단일 변형을 사용하여 제품 버전과 빌드 유형 지원을 삭제하므로 구성이 간소화되고 빌드 성능이 향상됩니다.

  • KMP에 최적화: 이 플러그인은 공유 Kotlin 코드와 상호 운용성에 중점을 두고 Android 전용 네이티브 빌드, AIDL, RenderScript 지원을 생략하여 KMP 라이브러리용으로 설계되었습니다.

  • 기본적으로 사용 중지된 테스트: 빌드 속도를 높이기 위해 단위 테스트와 기기 (계측) 테스트가 모두 기본적으로 사용 중지됩니다. 필요한 경우 사용 설정할 수 있습니다.

  • 최상위 Android 확장 프로그램 없음: 구성은 Gradle KMP DSL 내의 androidLibrary 블록으로 처리되어 일관된 KMP 프로젝트 구조를 유지합니다. 최상위 android 확장 프로그램 차단이 없습니다.

  • 선택적 Java 컴파일: Java 컴파일은 기본적으로 사용 중지되어 있습니다. androidLibrary 블록에서 withJava()를 사용하여 사용 설정합니다. 이렇게 하면 Java 컴파일이 필요하지 않은 경우 빌드 시간이 개선됩니다.

Android-KMP 라이브러리 플러그인의 이점

Android-KMP 플러그인은 KMP 프로젝트에 다음과 같은 이점을 제공합니다.

  • 빌드 성능 및 안정성 개선: KMP 프로젝트 내에서 최적화된 빌드 속도와 향상된 안정성을 위해 설계되었습니다. KMP 워크플로에 중점을 두어 더 효율적이고 안정적인 빌드 프로세스를 지원합니다.

  • 향상된 IDE 통합: KMP Android 라이브러리로 작업할 때 더 나은 코드 완성, 탐색, 디버깅, 전반적인 개발자 환경을 제공합니다.

  • 간소화된 프로젝트 구성: 이 플러그인은 빌드 변형과 같은 Android 관련 복잡성을 제거하여 KMP 프로젝트의 구성을 간소화합니다. 이렇게 하면 더 깔끔하고 유지관리 가능한 빌드 파일이 생성됩니다. 이전에는 KMP 프로젝트에서 com.android.library 플러그인을 사용하면 androidAndroidTest과 같은 혼동스러운 소스 세트 이름이 생성될 수 있었습니다. 이 명명 규칙은 표준 KMP 프로젝트 구조에 익숙한 개발자에게는 직관적이지 않았습니다.

기본 요건

com.android.kotlin.multiplatform.library 플러그인을 사용하려면 프로젝트가 다음 최소 버전 이상으로 구성되어야 합니다.

  • Android Gradle 플러그인 (AGP): 8.10.0
  • Kotlin Gradle 플러그인 (KGP): 2.0.0

기존 모듈에 Android-KMP 플러그인 적용

기존 KMP 라이브러리 모듈에 Android-KMP 플러그인을 적용하려면 다음 단계를 따르세요.

  1. 버전 카탈로그에서 플러그인 선언 버전 카탈로그 TOML 파일(일반적으로 gradle/libs.versions.toml)을 열고 플러그인 정의 섹션을 추가합니다.

    # To check the version number of the latest Kotlin release, go to
    # https://kotlinlang.org/docs/releases.html
    
    [versions]
    androidGradlePlugin = "8.13.0"
    kotlin = "KOTLIN_VERSION"
    
    [plugins]
    kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
    android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
    
  2. 루트 빌드 파일에 플러그인 선언을 적용합니다. 프로젝트의 루트 디렉터리에 있는 build.gradle.kts 파일을 엽니다. apply false을 사용하여 플러그인 별칭을 plugins 블록에 추가합니다. 이렇게 하면 플러그인 로직을 루트 프로젝트 자체에 적용하지 않고도 모든 하위 프로젝트에서 플러그인 별칭을 사용할 수 있습니다.

    Kotlin

    // Root build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }

    Groovy

    // Root build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }
  3. KMP 라이브러리 모듈 빌드 파일에 플러그인을 적용합니다. KMP 라이브러리 모듈에서 build.gradle.kts 파일을 열고 plugins 블록 내 파일 상단에 플러그인을 적용합니다.

    Kotlin

    // Module-specific build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }

    Groovy

    // Module-specific build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }
  4. Android KMP 타겟을 구성합니다. Android 타겟을 정의하도록 Kotlin Multiplatform 블록(kotlin)을 구성합니다. kotlin 블록 내에서 androidLibrary를 사용하여 Android 타겟을 지정합니다.

    Kotlin

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.configure {
                   jvmTarget.set(
                       org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
                   )
               }
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
                   // Add Android-specific dependencies here
               }
           }
           getByName("androidHostTest") {
               dependencies {
               }
           }
    
           getByName("androidDeviceTest") {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }

    Groovy

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               it.sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.options.jvmTarget.set(
                   org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
               )
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
               }
           }
           androidHostTest {
               dependencies {
               }
           }
           androidDeviceTest {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }
  5. 변경사항 적용 플러그인을 적용하고 kotlin 블록을 구성한 후 Gradle 프로젝트를 동기화하여 변경사항을 적용합니다.

기존 플러그인에서 마이그레이션

이 가이드는 기존 com.android.library 플러그인에서 com.android.kotlin.multiplatform.library 플러그인으로 이전하는 데 도움이 됩니다.

1. 종속 항목 선언

일반적인 작업은 Android 전용 소스 세트의 종속성을 선언하는 것입니다. 새 플러그인에서는 이전에 사용된 일반 dependencies 블록과 달리 sourceSets 블록 내에 명시적으로 배치해야 합니다.

Android-KMP

새 플러그인은 androidMain 소스 세트 내에서 Android 종속 항목을 그룹화하여 더 깔끔한 구조를 지원합니다. 기본 소스 세트 외에도 요청 시 생성되는 두 개의 테스트 소스 세트가 있습니다. androidDeviceTestandroidHostTest (자세한 내용은 호스트 및 기기 테스트 구성 참고)

// build.gradle.kts

kotlin {
    android {}
    //... other targets

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
        }

        // Dependencies are now scoped to the specific Android source set
        androidMain.dependencies {
            implementation("androidx.appcompat:appcompat:1.7.0")
            implementation("com.google.android.material:material:1.11.0")
        }
    }
}

소스 세트에는 main, deviceTest, hostTest라는 Kotlin 컴파일이 각각 있습니다. 소스 세트와 컴파일은 다음과 같이 빌드 스크립트에서 구성할 수 있습니다.

// build.gradle.kts

kotlin {
    androidLibrary {
        compilations.getByName("deviceTest") {
            kotlinOptions.languageVersion = "2.0"
        }
    }
}

기존 플러그인

이전 플러그인에서는 최상위 종속 항목 블록에서 Android 전용 종속 항목을 선언할 수 있었는데, 이는 멀티 플랫폼 모듈에서 혼동을 야기할 수 있었습니다.

// build.gradle.kts

kotlin {
  androidTarget()
  //... other targets
}

// Dependencies for all source sets were often mixed in one block
dependencies {
  // Common dependencies
  commonMainImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

  // Android-specific dependencies
  implementation("androidx.appcompat:appcompat:1.7.0")
  implementation("com.google.android.material:material:1.11.0")
}

2. Android 리소스 사용 설정

빌드 성능을 최적화하기 위해 Android 리소스 (res 폴더) 지원은 새 플러그인에서 기본적으로 사용 설정되지 않습니다. 이 기능을 사용하려면 선택해야 합니다. 이 변경사항은 Android 관련 리소스가 필요하지 않은 프로젝트가 관련 빌드 오버헤드로 부담을 받지 않도록 하는 데 도움이 됩니다.

Android-KMP

Android 리소스 처리를 명시적으로 사용 설정해야 합니다. 리소스는 src/androidMain/res에 배치해야 합니다.

// build.gradle.kts

kotlin {
  android {
    // ...
    // Enable Android resource processing
    androidResources {
      enable = true
    }
  }
}

// Project Structure
// └── src
//     └── androidMain
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

기존 플러그인

리소스 처리가 기본적으로 사용 설정되었습니다. src/mainres 디렉터리를 즉시 추가하고 XML 드로어블, 값 등을 추가할 수 있습니다.

// build.gradle.kts

android {
    namespace = "com.example.library"
    compileSdk = 34
    // No extra configuration was needed to enable resources.
}

// Project Structure
// └── src
//     └── main
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

3. 호스트 및 기기 테스트 구성

새 플러그인의 중요한 변경사항은 Android 호스트 측 (단위) 및 기기 측 (계측) 테스트가 기본적으로 사용 중지된다는 점입니다. 테스트 소스 세트와 구성을 만들려면 명시적으로 선택해야 합니다. 이전 플러그인은 이를 자동으로 만들었습니다.

이 선택 모델은 프로젝트가 간결하게 유지되고 적극적으로 사용하는 빌드 로직과 소스 세트만 포함되도록 하는 데 도움이 됩니다.

Android-KMP

새 플러그인에서는 kotlin.android 블록 내에서 테스트를 사용 설정하고 구성합니다. 이렇게 하면 설정이 더 명시적이 되고 사용하지 않는 테스트 구성요소가 생성되지 않습니다. test 소스 세트는 androidHostTest이 되고 androidTestandroidDeviceTest이 됩니다.

// build.gradle.kts

kotlin {
  android {
    // ...

    // Opt-in to enable and configure host-side (unit) tests
    withHostTest {
      isIncludeAndroidResources = true
    }

    // Opt-in to enable and configure device-side (instrumented) tests
    withDeviceTest {
      instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
      execution = "ANDROIDX_TEST_ORCHESTRATOR"
    }
  }
}

// Project Structure (After Opt-in)
// └── src
//     ├── androidHostTest
//     └── androidDeviceTest

기존 플러그인

com.android.library 플러그인을 사용하면 testandroidTest 소스 세트가 기본적으로 생성되었습니다. android 블록 내에서 동작을 구성하며, 일반적으로 testOptions DSL을 사용합니다.

// build.gradle.kts

android {
  defaultConfig {
    // Runner was configured in defaultConfig
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  testOptions {
    // Configure unit tests (for the 'test' source set)
    unitTests.isIncludeAndroidResources = true

    // Configure device tests (for the 'androidTest' source set)
    execution = "ANDROIDX_TEST_ORCHESTRATOR"
  }
}

// Project Structure (Defaults)
// └── src
//     ├── test
//     └── androidTest

4. Java 소스 컴파일 사용 설정

KMP 라이브러리가 Android 타겟의 Java 소스를 컴파일해야 하는 경우 새 플러그인으로 이 기능을 명시적으로 사용 설정해야 합니다. 이렇게 하면 종속 항목이 아닌 프로젝트 내에 직접 있는 Java 파일의 컴파일이 사용 설정됩니다. Java 및 Kotlin 컴파일러의 JVM 타겟 버전을 설정하는 방법도 변경됩니다.

Android-KMP

withJava()를 호출하여 Java 컴파일을 선택해야 합니다. 이제 JVM 타겟이 더 통합된 설정을 위해 kotlin { androidLibrary {} } 블록 내에서 직접 구성됩니다. 여기에서 jvmTarget를 설정하면 Android 타겟의 Kotlin 및 Java 컴파일 모두에 적용됩니다.

// build.gradle.kts

kotlin {
  android {
    //  Opt-in to enable Java source compilation
    withJava()
    // Configure the JVM target for both Kotlin and Java sources
    compilerOptions {
      jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
    }
  }
  // ...
}

// Project Structure:
// └── src
//     └── androidMain
//         ├── kotlin
//         │   └── com/example/MyKotlinClass.kt
//         └── java
//             └── com.example/MyJavaClass.java

기존 플러그인

Java 컴파일이 기본적으로 사용 설정되었습니다. Java 및 Kotlin 소스의 JVM 타겟은 compileOptions를 사용하여 android 블록에 설정되었습니다.

// build.gradle.kts

android {
  // ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

kotlin {
  androidTarget {
    compilations.all {
      kotlinOptions.jvmTarget = "1.8"
    }
  }
}

5. androidComponents을 사용하여 빌드 변형과 상호작용

빌드 아티팩트와 프로그래매틱 방식으로 상호작용하는 데는 androidComponents 확장 프로그램을 계속 사용할 수 있습니다. Variant API는 대부분 동일하게 유지되지만 플러그인이 단일 변형만 생성하므로 새로운 AndroidKotlinMultiplatformVariant 인터페이스는 더 제한적입니다.

따라서 빌드 유형 및 제품 버전과 관련된 속성은 변형 객체에서 더 이상 사용할 수 없습니다.

Android-KMP

이제 onVariants 블록이 단일 변형을 반복합니다. nameartifacts과 같은 일반 속성은 계속 액세스할 수 있지만 빌드 유형별 속성은 액세스할 수 없습니다.

// build.gradle.kts

androidComponents {
  onVariants { variant ->
      val artifacts = variant.artifacts
  }
}

기존 플러그인

변형이 여러 개인 경우 빌드 유형별 속성에 액세스하여 태스크를 구성할 수 있습니다.

// build.gradle.kts

androidComponents {
  onVariants(selector().withBuildType("release")) { variant ->
    // ...
  }
}

6. Android 라이브러리 종속 항목의 변형 선택

KMP 라이브러리가 Android용 단일 변형을 생성합니다. 하지만 변형이 여러 개 있는 표준 Android 라이브러리 (com.android.library)에 의존할 수 있습니다 (예: free/paid 제품 버전) 프로젝트가 종속 항목에서 변형을 선택하는 방식을 제어하는 것은 일반적인 요구사항입니다.

Android-KMP

새 플러그인은 kotlin.android.localDependencySelection 블록 내에서 이 로직을 중앙 집중화하고 명확히 합니다. 이렇게 하면 단일 변형 KMP 라이브러리에 선택될 외부 종속 항목의 변형이 훨씬 명확해집니다.

// build.gradle.kts
kotlin {
  android {
    localDependencySelection {
      // For dependencies with multiple build types, select 'debug' first, and 'release' in case 'debug' is missing
      selectBuildTypeFrom.set(listOf("debug", "release"))

      // For dependencies with a 'type' flavor dimension...
      productFlavorDimension("type") {
        // ...select the 'typeone' flavor.
        selectFrom.set(listOf("typeone"))
      }
    }
  }
}

기존 플러그인

buildTypes and productFlavors 블록 내에서 종속 항목 선택 전략을 구성했습니다. 여기에는 라이브러리에 없는 차원의 기본 버전을 제공하기 위해 missingDimensionStrategy를 사용하거나 특정 버전 내에서 matchingFallbacks를 사용하여 검색 순서를 정의하는 것이 포함되는 경우가 많았습니다.

API 사용에 관한 자세한 내용은 매칭 오류 해결을 참고하세요.

플러그인 API 참조

새 플러그인의 API 노출 영역은 com.android.library와 다릅니다. 새 DSL 및 인터페이스에 관한 자세한 내용은 다음 API 참조를 확인하세요.