티스토리 뷰

반응형

Intro

안드로이드 스튜디오를 사용하다보면 외부 라이브러리를 많이 사용하게 된다.

그러다보니 자연스레 build.gradle의 길이가 길어지고, 가독성이 떨어지게 된다.

현재 진행 중인 프로젝트를 신규 SDK로 마이그레이션 하다보니 문득 gradle이 너무 보기 싫다는 생각이 들었다.

 

또한, 최근에 프로젝트를 새로 생성하려고 하니 Kotlin DSL이 프로젝트 생성시 선택사항의 기본값으로 설정되어 있었다.

kotlin으로 통일하는게 그래도 조금은 나아보일까 하여, 선택해서 작성하게 되었다.

하지만 생각보다 코드가 길어지면서 좀... gradle 파일을 들춰보기 싫어지게 되었다.

 

특히 요즘 대부분의 프로젝트에 클린 아키텍처를 적용하다보니, 각 모듈마다 필요한 dependency가 중복되는 경우가 있다.

이런 경우에 특히 version sharing을 하기 위해, gradle의 extra를 사용하게 된다.

하지만 kotlin DSL에서는 개인적으로 이게 생각보다 보기가 싫다... 

코드는 가독성이 있어야한다고 생각하는데 이렇게 사용하게 되면, 정말 눈이 아프다.

// koin
    implementation("io.insert-koin:koin-core:${rootProject.extra["koin_version"]}")
    testImplementation("io.insert-koin:koin-test:${rootProject.extra["koin_version"]}")
    testImplementation("io.insert-koin:koin-test-junit4:${rootProject.extra["koin_version"]}")
    implementation("io.insert-koin:koin-android:${rootProject.extra["koin_version"]}")
    implementation("io.insert-koin:koin-android-compat:${rootProject.extra["koin_version"]}")
    implementation("io.insert-koin:koin-androidx-workmanager:${rootProject.extra["koin_version"]}")
    implementation("io.insert-koin:koin-androidx-navigation:${rootProject.extra["koin_version"]}")

    implementation("androidx.activity:activity-ktx:1.7.2")
    implementation("androidx.fragment:fragment-ktx:1.6.1")

    // Livedata and Lifecycle
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:${rootProject.extra["lifecycle_version"]}")
    kapt("androidx.lifecycle:lifecycle-compiler:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-common-java8:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-service:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-process:${rootProject.extra["lifecycle_version"]}")
    implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:${rootProject.extra["lifecycle_version"]}")
    testImplementation("androidx.lifecycle:lifecycle-runtime-testing:${rootProject.extra["lifecycle_version"]}")
    testImplementation("androidx.arch.core:core-testing:${rootProject.extra["arch_version"]}")

    // Retrofit and okhttp
    implementation("com.squareup.retrofit2:retrofit:${rootProject.extra["retrofit_version"]}")
    implementation("com.squareup.retrofit2:converter-gson:${rootProject.extra["retrofit_version"]}")
    implementation("com.google.code.gson:gson:${rootProject.extra["gson_version"]}")
    implementation("com.squareup.okhttp3:okhttp:${rootProject.extra["okhttp_version"]}")
    implementation("com.squareup.okhttp3:logging-interceptor:${rootProject.extra["okhttp_version"]}")

    // coroutines
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${rootProject.extra["coroutine_version"]}")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${rootProject.extra["coroutine_version"]}")

 

어떻게 이 문제를 해결해야 할까... 하다 찾은 방법이 바로 Version Catalog라는 것이다.

https://developer.android.com/studio/build/migrate-to-catalogs?hl=ko 

 

버전 카탈로그로 빌드 이전  |  Android 개발자  |  Android Developers

Gradle 구성 파일을 Gradle 버전 카탈로그로 이전합니다.

developer.android.com

반응형

 

 

Summary

developers에서 보다시피 libs.versions.toml 이라는 새로운 형식의 파일을 사용하게 된다.

.toml 이라는 확장자는 처음보아서 검색해 보았다.

https://toml.io/en/

 

TOML: Tom's Obvious Minimal Language

TOML already has implementations in most of the most popular programming languages in use today: C, C#, C++, Clojure, Dart, Elixir, Erlang, Go, Haskell, Java, Javascript, Lua, Objective-C, Perl, PHP, Python, Ruby, Swift, Scala... and plenty more.

toml.io

 

처음 봤을 땐, 다른 프레임워크들의 config 파일처럼 생겼다.

언어의 형식상, JSON이나 Swift의 Dictionary 같은 느낌이 든다.

생각보다 다양하게 사용되는 것 같았다.

 

이 방법에 대해 좀 더 깊게 공부하고 싶다하면 Gradle 공식 페이지의 사용방법을 공부하는 것을 추천한다.

https://docs.gradle.org/current/userguide/platforms.html

 

Sharing dependency versions between projects

Because platforms and catalogs both talk about dependency versions and can both be used to share dependency versions in a project, there might be a confusion regarding what to use and if one is preferable to the other. use catalogs to only define dependenc

docs.gradle.org

 

 

Dependency

자, 그럼 .toml 파일을 생성하는 방법부터 알아보자.

일단 Gradle 버전은 7.4 이상을 사용하는 것이 좋다.

7.4 미만의 버전은 직접 해당 파일의 경로를 지정해 주고, 설정하는 과정이 필요하다.

그리 복잡하진 않으나, Auto Generate되는 버전을 사용하는게 마이그레이션을 할 때, 가장 리스크를 줄인다고 생각한다.

 

먼저 Project로 바꾸어 준다.

 

이 중 gradle 폴더가 보이게 된다. 여기에 똑같이 마우스 오른쪽 > New > Version Catalog 를 선택하면 .toml 파일을 생성할 수 있다.

기본 네이밍은 libs가 지정된다. 다른 걸로 바꾸어도 좋다.

만약 libs가 아닌 다른 이름으로 하거나, 여러 개의 파일로 나누어서 설정하게 된다면, 각 .toml 파일들의 경로를 설정해 주어야 한다.

파일이 생성되면, 다음과 같은 파일이 보인다.

이 글의 가장 위에 있는 링크의 파일과 비슷한 형식의 파일이 생성된다.

 

 

Using

이제 실제로 적용해보자.

implementation("com.squareup.retrofit2:retrofit:${rootProject.extra["retrofit_version"]}")
implementation("com.squareup.retrofit2:converter-gson:${rootProject.extra["retrofit_version"]}")

위에는 kotlin DSL에서 쓰이는 방법 중 하나이다. extra를 사용해 version sharing을 한다.

실제로 많이 쓰이는 retrofit의 의존성을 version catalog로 추가해보자.

[versions]
retrofit = "2.9.0"

[libraries]
retrofit-core = { 
	module = "com.squareup.retrofit2:retrofit", 
	version.ref = "retrofit"
}

retrofit-converter-gson = { 
	module = "com.squareup.retrofit2:converter-gson", 
	version.ref = "retrofit" 
}

1. [versions] 에는 사용할 버전을 본인이 알아보기 쉬운 변수를 지정해 작성한다.

 

2. [libraries] 에는 dependency 경로를 작성한다.

 이때 변수명은 케밥케이스( " - " )를 활용해 작성하면 좋다.

 예를 들어, retrofit-core라고 작성했다면, gradle에서는 retrofit.core로 사용할 수 있다.

 module은 dependency의 경로를, version.ref는 위에 [versions]에 지정한 버전 변수를 가져온다.

 

 위와 같이 작성 후, 싱크를 돌리면, gradle에서 아래와 같이 사용할 수 있게 된다.

// Retrofit
implementation(libs.retrofit.core)
implementation(libs.retrofit.converter)

 

 나는 retrofit을 사용할 때, Okhttp와 Gson을 같이 활용한다.

[versions]
retrofit = "2.9.0"
gson = "2.9.0"
okhttp3 = "4.10.0"

[libraries]
retrofit-core = { 
	module = "com.squareup.retrofit2:retrofit", 
	version.ref = "retrofit"
}

retrofit-converter-gson = {
	module = "com.squareup.retrofit2:converter-gson",
	version.ref = "retrofit"
}

code-gson = {
	module = "com.google.code.gson:gson",
	version.ref = "gson" 
}

okhttp-core = { 
	module = "com.squareup.okhttp3:okhttp", 
	version.ref = "okhttp3" 
}

okhttp-logging-interceptor = { 
	module = "com.squareup.okhttp3:logging-interceptor", 
	version.ref = "okhttp3" 
}
// Retrofit, okhttp, gson
implementation(libs.retrofit.core)
implementation(libs.retrofit.converter.gson)
implementation(libs.code.gson)
implementation(libs.okhttp.core)
implementation(libs.okhttp.logging.interceptor)

 

3. [bundles]

 이 5줄보다 더 줄이고 싶다면, 아래와 같이 추가로 작성해 준다.

[bundles]
retrofit = [
    "retrofit-core",
    "retrofit-converter-gson",
    "code-gson",
    "okhttp-core",
    "okhttp-logging-interceptor"
]

 그리고 gradle로 가서 아래와 같이 사용한다.

 이렇게 사용하면 gradle에서는 단 한줄로 dependency 5개를 추가할 수 있다.

// Retrofit and okhttp
implementation(libs.bundles.retrofit)

 

4. [plugins]

 또한 plugins도 version catalog로 작성할 수 있다.

 대표적으로, 코틀린 플러그인을 작성해 보자.

 여기서 주의할 점은, plugins를 추가할 때는 'alias'를 사용한다는 점이다.

build.gradle.kts(project)

plugins {
    id("org.jetbrains.kotlin.android") version "1.8.0" apply false
}

build.gradle.kts(app)

plugins {
    id("org.jetbrains.kotlin.android")
}

 

 

version catalog에는 아래와 같이 사용한다.

[versions]
kotlin = "1.8.0"

[plugins]
kotlin-plugin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

build.gradle.kts(project)

plugins {
	alias(libs.plugins.kotlin.plugin) apply false
}

build.gradle.kts(app)

plugins {
	alias(libs.plugins.kotlin.plugin)
}

 

사실 이 방법이 무조건 좋다고 할 수는 없다.

하지만 얼마나 코드를 가독성 있게 작성하고, 재사용성을 올리는 가는 gradle이라고 예외는 없다고 생각한다.

그만큼 오픈소스를 적게 사용하는 프로젝트는 굳이 사용할 이유가 없을 것 같다.

오픈소스와 버전관리가 중요한 대형 프로젝트에서는 이 방법을 사용한다면, 가독성을 올리고, 마이그레이션 할 때 매우 편하게 사용할 수 있다고 생각한다.

 

* Source Code

https://github.com/rlwhd0716/tistory_library/tree/620f22ddbc1cf0ef3ae861e8a88d05c11e2bc179/Android/VersionCatalogExample

 

반응형

'Android' 카테고리의 다른 글

[Android] TTS 실행하기  (0) 2024.01.16
[Android] ImageView 회전시켜서 보여주기  (0) 2024.01.15
[Android] RecyclerView Decorator 사용하기  (0) 2023.11.04
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함