본문 바로가기

안드로이드/멀티 모듈

[안드로이드 멀티 모듈] 9. AndroidPresentationUIConventionPlugin 만들기


지난 포스팅에서는 화면은 없지만 Compose와 관련된 컨벤션 플러그인을 만들어서 designsystem 모듈에 적용했습니다.

이번 포스팅에서는 화면이 존재하고 Compose와 관련된 모듈을 위한 AndroidPresentationUIConventionPlugin을 만들겠습니다.

해당 플러그인은 home, login, board 등 화면을 담당하는 UI Layer 모듈에 적용되는 컨벤션 플러그인입니다.

AndroidPresentationUIConventionPlugin 및 ComposeDependencies가 추가된 모습
AndroidPresentationUIConventionPlugin 및 ComposeDependencies가 추가된 모습

1. AndroidPresentationUIConventionPlugin 만들기

이번에는 화면이 존재하는 Compose 컨벤션 플러그인을 만들고 있습니다.
그래서 이전 포스팅에서 만든 컨벤션 플러그인을 pluginManager를 통해 적용하고, Compose 화면을 위한 의존성을 추가해줘야 합니다.

// AndroidPresentationUIConventionPlugin.kt
class AndroidPresentationUIConventionPlugin: Plugin<Project> {
    override fun apply(target: Project) {
        target.run {
            pluginManager.run {
                apply("multi.module.android.library.compose")
            }

            dependencies {
                addUILayerDependencies(target)
            }
        }
    }
}


재사용성을 위해서 Compose 화면과 관련된 의존성을 addUILayerDependencies라는 유틸 함수를 통해 추가했습니다.
유틸함수는 아래와 같이 dependencies 블록 스코프에 대한 확장함수로 구현했습니다.

// ComposeDependencies.kt
fun DependencyHandlerScope.addUILayerDependencies(project: Project) {
    add("implementation", project(":core:presentation:designsystem"))

    add("implementation", project.libs.findBundle("compose").get())
    add("debugImplementation", project.libs.findBundle("compose.debug").get())
    add("androidTestImplementation", project.libs.findLibrary("androidx.ui.test.junit4").get())
}


화면과 관련된 모듈은 designsystem 모듈에 의존하고 있으며, Compose 관련 의존성은 관리를 편하게 하기 위해서 아래와 같이 libs.versions.toml 파일에 bundles로 묶어서 처리했습니다. 자세한 코드는 포스팅 하단의 github repository를 확인해 보시면 됩니다.

// libs.versions.toml
...

[libraries]
...
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
...

[bundles]
compose = [
    "androidx-activity-compose",
    "androidx-lifecycle-runtime-compose",
    "androidx-lifecycle-viewmodel-compose",
    "androidx-material3",
    "androidx-ui",
    "androidx-ui-graphics",
    "androidx-ui-tooling-preview",
]
compose-debug = [
    "androidx-ui-tooling",
    "androidx-ui-test-manifest",
]

2. AndroidPresentationUIConventionPlugin 적용하기

Gradle에서 컨벤션 플러그인을 인식하기 위해서 libs.versions.toml에 id를 추가하고, build-logic 모듈에 추가하겠습니다. 해당 단계에서 하는 작업은 이전 포스팅과 동일합니다.

// libs.versions.toml
...

# Custom Convention Plugin
...
multi-module-android-presentation-ui = { id = "multi.module.android.presentation.ui", version = "unspecified" }
// build.gradle.kts (Module :build-logic-convention)
...

gradlePlugin {
   plugins {
     
      ...
      
      register("androidPresentationUI") {
         id = "multi.module.android.presentation.ui"
         implementationClass = "AndroidPresentationUIConventionPlugin"
      }
   }
}


그리고 Compose 화면을 위한 모듈에 AndroidPresentationUIConventionPlugin을 적용합니다.
여기서는 home:presentation 모듈뿐이지만 login, mypage, board 등 다양한 모듈에 적용할 수 있습니다.

// build.gradle.kts (:home:presentation)
plugins {
    alias(libs.plugins.multi.module.android.presentation.ui)
}

android {
    namespace = "com.multi.module.home.presentation"
}

dependencies {
    implementation(projects.home.domain)
}

3. 정리

Compose로 구성된 Presentation 레이어를 위한 AndroidPresentationUIConventionPlugin을 만들었습니다.
실제 프로젝트에서 멀티 모듈 아키텍처를 구현했다면 해당 컨벤션 플러그인이 가장 많이 사용될 것 같습니다.

다음 포스팅에서는 Room, Hilt 등을 위한 컨벤션 플러그인을 만들 예정입니다.

이번 포스팅의 결과물은 아래 Github Repository의 9-AndroidPresentationUIConventionPlugin 브랜치를 확인하시면 됩니다.

GitHub - taein8935/multi-module-template-aos

Contribute to taein8935/multi-module-template-aos development by creating an account on GitHub.

github.com