Multi Module에서 버전을 관리하는 방법은 여러가지가 있습니다. 저는 그중에서 buildSrc 방식을 계속 사용해왔습니다. 그러던 중 면접 준비를 하면서 버전 관리 방법이 여러가지 있고 Version Catalog에 대해서 알았습니다.
이에 대해 찾아보면서 하나의 파일로 버전을 관리하기 때문에 더 편해보여서 공부하고 이를 예제 프로젝트에 적용해봤습니다.
그래서 Version Catalog을 어떻게 적용하는지, buildSrc 방식에서 Version Catalog로 이전 한 과정에 대해서 작성해보려고 합니다.
이렇게 하면 libs.versions.toml 파일이 생성됩니다. libs.versions.toml은 초기에 다음과 같은 형식을 보여줍니다.
이 섹션들에는 다음과 같은 정보를 정의하면 됩니다.
위에서 언급한 것 처럼 libraries 섹션에는 의존성 정보들을 정의하면 됩니다.
ex)
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha01")
위와 같은 의존성을 추가하기 위해서는 다음과 같이 작성하면 됩니다.
[versions]
androidx-core-ktx = "1.9.0"
androidx-lifecycle_runtime-ktx = "2.7.0"
androidx-lifecycle_runtime-compose = "2.6.0-alpha01"
[libraries]
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core-ktx" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidx-lifecycle_runtime-ktx" }
androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle_runtime-compose" }
그리고 build.gradle.kts의 의존성 섹션에 다음과 같이 정의를 하면 추가가 됩니다.
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.runtime.compose)
Version Catalog에서 의존성을 정의하는 방법에 대한 위의 예시를 통해, path를 사용하여 module과 group을 지정하는 것을 확인할 수 있습니다. module에는 전체 의존성을, group에는 ':'(콜론)을 기준으로 앞부분을 group으로, 뒷부분을 name으로 정의합니다.
저의 경우, module은 특정 모듈의 path를 지정할 때, group은 여러 모듈을 포함하는 group의 path를 지정할 때 사용하였습니다.
따라서 동일한 path를 가진 경우에는 group으로 선언하였고, 그렇지 않은 경우에는 module로 정의하였습니다. 이로 인해 lifecycle 의존성은 group으로, core ktx 의존성은 module로 정의된 것을 확인할 수 있습니다.
plugins 섹션에는 plugin 정보를 정의하면 됩니다.
ex)
plugins {
id("com.android.application") version "8.0.1" apply false
}
위의 plugin을 추가하기 위해서는 다음과 같이 작성하면 됩니다.
[versions]
gradle = "8.0.1"
[plugins]
android-application = { id = "com.android.application", version.ref = "gradle" }
그리고 build.gradle.kts의 plugins 섹션에 다음과 같이 정의를 하면 추가가 됩니다.
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(libs.plugins.android.application) apply false
}
bundles을 사용하면 여러 의존성을 한번에 추가할 수 있습니다.
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" }
compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "ui" }
compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
compose-ui-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
compose-material = { module = "androidx.compose.material3:material3-android", version.ref = "compose-material" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
hilt-navigation = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hilt-navigation" }
[bundles]
compose = [ "activity-compose", "compose-bom", "compose-ui", "compose-ui-graphics", "compose-ui-preview", "compose-material", "navigation-compose", "hilt-navigation" ]
이렇게 bundles에 여러 의존성을 묶으면 다음과 같이 간단하게 의존성들을 추가할 수 있습니다.
implementation(libs.bundles.compose)
bundles 적용 전 | bundles 적용 후 |
이렇게 보면 사용하는 이유를 확실하게 체감하실 것이라 생각합니다.
Multi Module에서 각 모듈들의 버전들을 하나의 파일에서 관리해서 편했습니다. 특히 bundles를 사용하여 불필요한 코드를 줄여 코드 가독성을 높일 수 있어 매력적으로 느껴졌습니다.
하지만 처음 접했을 땐 뭔 소리인지 잘 이해가 안됐습니다. 개인 마다 다르게 생각할 수 있지만 저는 러닝 커브가 높다고 느껴졌습니다.
그런데 적용 후에는 장점이 더 크다고 생각합니다. 다른 분들도 적용해보는 거 추천합니다.