Android 멀티 모듈에 build-logic 적용

PanaxW·2일 전
0

Android

목록 보기
21/21

⚙️ 목표

  • 안드로이드 프로젝트를 멀티 모듈 구조로 변경하면서 build.gradle.kts 파일이 많아 관리가 힘든 문제 발생
  • common.gradle파일을 사용해 공통되는 부분을 줄였지만, 여전히 파일을 하나하나 관리해야 함
  • build-logic 모듈을 사용해 플러그인 형태로 관리하려고 함

🧱 build-logic 모듈 생성

  • build-logic모듈 생성

    • Android 모듈과 Kotlin 모듈 둘 다 해봤는데 되는 것 같음
  • 테스트, 리소스 등 불필요한 파일은 정리

🧭 설정 파일 구성

🔧 build-logic/settings.gradle.kts

해당 파일이 없으면 직접 생성해야함함

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }

    // 버전 카탈로그 사용할 수 있게 설정정
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

🔧 프로젝트의 settings.gradle.kts

pluginManagement {
    includeBuild("build-logic")
}

❗ 모듈을 만들면 추가되는 include(":build-logic")는 제거

📦 라이브러리 정의 (libs.versions.toml)

[versions]
kotlin = "2.0.0"
androidGradlePlugin = "8.5.0"
org-jetbrains-kotlin-android = "1.9.24"

[libraries]
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }
kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "org-jetbrains-kotlin-android" }
compose-compiler-gradle-plugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }

📜 build-logic/build.gradle.kts

plugins {
    `kotlin-dsl`
    `kotlin-dsl-precompiled-script-plugins`
}

dependencies {
    implementation(libs.android.gradlePlugin)
    implementation(libs.kotlin.gradlePlugin)
    compileOnly(libs.compose.compiler.gradle.plugin)
}

🛠️ 코드 작성 예시

✅ 공통 확장 함수 (Extension.kt)

필수는 아니지만 있으면 편함

/**
 * Application extension
 */
internal val Project.applicationExtension: CommonExtension<*, *, *, *, *, *>
    get() = extensions.getByType<ApplicationExtension>()

/**
 * Library extension
 */
internal val Project.libraryExtension: CommonExtension<*, *, *, *, *, *>
    get() = extensions.getByType<LibraryExtension>()

/**
 * Android extension
 */
internal val Project.androidExtension: CommonExtension<*, *, *, *, *, *>
    get() = runCatching { libraryExtension }
        .recoverCatching { applicationExtension }
        .onFailure { println("Could not find Library or Application extension from this project") }
        .getOrThrow()

/**
 * version catalog
 */
internal val ExtensionContainer.libs: VersionCatalog
    get() = getByType<VersionCatalogsExtension>().named("libs")

✅ Compose 설정 함수 (ComposeAndroid.kt)

internal fun Project.configureComposeAndroid() {

    // plugin
    with(plugins) {
        apply("org.jetbrains.kotlin.plugin.compose")
    }

    // library
    val libs = extensions.libs
    androidExtension.apply {
        dependencies {
            val bom = libs.findLibrary("androidx-compose-bom").get()
            add("implementation", platform(bom))
            add("androidTestImplementation", platform(bom))

            add("implementation", libs.findLibrary("androidx.compose.material3").get())
            add("implementation", libs.findLibrary("androidx.compose.ui").get())
            add("implementation", libs.findLibrary("androidx.compose.ui.tooling.preview").get())
            
            add("androidTestImplementation", libs.findLibrary("androidx.test.ext").get())
            add("androidTestImplementation", libs.findLibrary("androidx.test.espresso.core").get())
            add("androidTestImplementation", libs.findLibrary("androidx.compose.ui.test").get())
            
            add("debugImplementation", libs.findLibrary("androidx.compose.ui.tooling").get())
            add("debugImplementation", libs.findLibrary("androidx.compose.ui.testManifest").get())
        }
    }

    extensions.getByType<ComposeCompilerGradlePluginExtension>().apply {
        enableStrongSkippingMode.set(true)
        includeSourceInformation.set(true)
    }
}

🔌 플러그인 적용 방법

방법 1: gradlePlugin DSL

다음 클래스 생성해야 함

internal class HiltAndroidPlugin : Plugin<Project> {

    override fun apply(target: Project) {
        with(target) {
            configureHiltAndroid()
        }
    }
}
gradlePlugin {
    plugins {
        register("androidHilt") {
            id = "test.android.hilt"
            implementationClass = "com.test.app.HiltAndroidPlugin"
        }
    }
}

사용 시

plugins {
    id("test.android.hilt")
}

방법 2: Precompiled 스크립트

  • 파일명: test.android.compose.gradle.kts
import com.example.build_logic.configureComposeAndroid

configureComposeAndroid()

사용 시

plugins {
    // 파일 이름으로 지정함
    id("test.android.compose")
}

⚠️ 주의 사항

  • build-logic에서 다른 프로젝트를 사용해야 할때 kotlin-dsl 같은 방식은 사용이 안되는 것 같음
// 됨
implementation(project(":core:ui"))

// 안됨
implementation(projects.core.ui)

📚 참고자료

✅ 정리

항목기존 방식build-logic 방식
유지보수공통 gradle 파일을 직접 import모듈 단위로 재사용
적용 위치build.gradle.kts마다 직접 설정plugins 선언으로 간편 적용
profile
Android Developer

0개의 댓글