안드로이드 개발을 할 buildSrc와 TOML, 둘 다 안드로이드 프로젝트의 설정 및 의존성 관리를 위한 좋은 방법이지만, 각각의 장단점이 있습니다. 하지만 최근 저는 buildSrc 대신 TOML 을 채택하여 사용하고 있고, 그 이유는 다음과 같습니다.
buildSrc를 사용하는 이유
buildSrc는 Gradle 빌드 스크립트의 재사용 가능한 코드(플러그인, 의존성 관리 등)를 작성할 수 있는 커스텀 Gradle 프로젝트입니다.
빌드 로직 중앙화 및 재사용:
여러 모듈에서 공통으로 사용하는 빌드 로직을 buildSrc에 모아서 관리하면 코드 중복을 줄이고 유지보수를 용이하게 할 수 있습니다.
예를 들어, 모든 모듈에 적용되는 기본 설정, 플러그인, 의존성 버전 등을 buildSrc에서 정의하고 각 모듈의 빌드 스크립트에서 간편하게 참조할 수 있습니다.
Kotlin DSL 활용:
buildSrc는 Kotlin 기반의 DSL (Domain Specific Language)을 사용하여 빌드 스크립트를 작성할 수 있도록 지원합니다.
Kotlin의 강력한 표현력과 안전성을 활용하여 더욱 명확하고 유지보수하기 쉬운 빌드 스크립트를 작성할 수 있습니다.
IDE 지원:
buildSrc는 안드로이드 스튜디오의 코드 자동 완성, 네비게이션, 리팩토링 등의 기능을 지원합니다.
이를 통해 빌드 스크립트 작성의 생산성을 높이고 오류를 줄일 수 있습니다.
프로젝트 통합:
buildSrc는 프로젝트의 일부로 빌드되어 프로젝트와 함께 버전 관리됩니다.
따라서 빌드 스크립트를 별도로 관리할 필요 없이 프로젝트와 함께 일관성 있게 관리할 수 있습니다.
buildSrc 사용 예시
1. 의존성 버전 관리:
buildSrc/src/main/kotlin/Dependencies.kt
object Dependencies {
const val kotlinVersion = "1.9.0"
const val coreKtxVersion = "1.9.0"
const val appCompatVersion = "1.6.1"
// ...
}
app/build.gradle.kts
dependencies {
implementation("androidx.core:core-ktx:${Dependencies.coreKtxVersion}")
implementation("androidx.appcompat:appcompat:${Dependencies.appCompatVersion}")
// ...
}
2. 커스텀 빌드 로직:
buildSrc/src/main/kotlin/ReleaseSigningConfig.kt
import org.gradle.api.Project
import java.io.FileInputStream
import java.util.Properties
fun Project.configureReleaseSigning() {
val keystorePropertiesFile = rootProject.file("keystore.properties")
if (keystorePropertiesFile.exists()) {
val keystoreProperties = Properties()
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
getByName("release") {
signingConfig = signingConfigs.getByName("release")
}
}
}
}
app/build.gradle.kts
apply(plugin = "com.android.application")
// ...
configureReleaseSigning()
정리를 해보면 buildSrc는 빌드 설정을 중앙 집중화하고 재사용성을 높이는 데 도움이 됩니다. 또한 Dependencies 객체를 사용하여 의존성 버전을 관리하면, 여러 모듈에서 동일한 버전을 사용하도록 보장하고 버전 업데이트를 용이하게 할 수 있습니다.
릴리즈 빌드 서명 설정과 같이 반복적으로 사용되는 빌드 로직을 buildSrc에 함수로 정의하여 모듈 빌드 스크립트에서 간편하게 호출할 수 도 있고, Kotlin 확장 함수를 활용하여 빌드 스크립트를 더욱 간결하고 읽기 쉽게 작성할 수 있습니다.
buildSrc에서 TOML로 넘어가려는 이유
장점:
- 유연성: Kotlin 코드를 사용하여 복잡한 로직과 조건부 설정을 구현할 수 있습니다.
- IDE 지원: 안드로이드 스튜디오의 코드 자동 완성, 네비게이션, 리팩토링 등의 기능을 활용할 수 있습니다.
- 프로젝트 통합: 빌드 스크립트의 일부로 빌드되어 프로젝트와 함께 버전 관리됩니다.
단점:
- 빌드 시간 증가: buildSrc 코드를 컴파일해야 하므로 빌드 시간이 약간 증가할 수 있습니다.
- 학습 곡선: Kotlin 및 Gradle 빌드 스크립트에 대한 이해가 필요합니다.
- 의존성 업데이트 지원 부족: 안드로이드 스튜디오의 자동 업데이트 지원을 받을 수 없습니다.
위 장단점 중에 저는 존성 업데이트 지원 부족이 가장 큰 요인이였습니다. 또한 별도 커스텀 빌드 로직을 구성하여 사용하지 않았기에 유지 보수성이 더 좋은 다른 대안이 필요 하였습니다.
TOML (Tom's Obvious, Minimal Language) 이란?
libs.versions.toml 예시
[versions]
kotlin = "1.8.0"
compose = "1.3.0"
coroutines = "1.6.0"
[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
[plugins]
android-application = { id = "com.android.application", version = "7.0.2" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
build.gradle.kts 예시
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
compileSdk = 31
...
}
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.compose.ui)
implementation(libs.compose.material)
implementation(libs.coroutines.core)
}
장점:
간결성: TOML은 간단하고 읽기 쉬운 구문을 제공합니다.
의존성 관리 도구와의 호환성: Dependabot, RenovateBot 등의 도구를 사용하여 의존성 업데이트를 자동화할 수 있습니다.
다른 언어와의 호환성: 다양한 언어에서 파싱하기 쉬운 형식입니다.
단점:
제한적인 표현력: 복잡한 로직이나 조건부 설정을 구현하기 어려울 수 있습니다.
프로젝트 외부 관리: TOML 파일은 일반적으로 프로젝트 외부에서 관리되므로 별도의 버전 관리가 필요합니다.
결론
저는 현재 커스텀 빌드 로직 보다는 버전 통합 관리에 좀 더 포커싱하고 있었고 그에 따라 TOML을 사용하여 의존성 관리를 자동화하는 것이 유리하다고 생각합니다.
하지만, 프로젝트에 복잡한 빌드 로직이나 조건부 설정이 필요한 경우, buildSrc가 더 적합할 수 있습니다. 이 경우, 의존성 업데이트는 수동으로 관리하거나, 외부 도구를 활용하여 자동화하는 방법을 찾아야 합니다.
어떤 방법을 선택하든, 프로젝트의 특성과 팀의 상황을 고려하여 가장 효율적인 방법을 선택하는 것이 중요합니다.
감사합니다.
안드로이드/Android 의 (Compose) - 데이터 선택 가능한 피커 만들기 (Picker) (1) | 2024.01.07 |
---|---|
안드로이드/Android 의 (Native) - 미디어 스캐너 사용 방법(MediaScanner) (0) | 2024.01.07 |
안드로이드/Android 의 (Compose) - 스낵바 사용 방법(Snackbar) (0) | 2024.01.07 |
안드로이드/Android 의 (Compose TextField) - 입력한 텍스트 데이터의 포맷 설정하기(visualTransformation) (1) | 2024.01.03 |
안드로이드/Android 의 (Compose) - 뒤로가기 이벤트 제어하기 (BackHandler) (0) | 2024.01.02 |