참고 자료
[Github - ComposeCookBook] : https://github.com/Gurupreet/ComposeCookBook
#Kotlin DSL
이 프로젝트에서는 많은 모듈로 이루어져 있는데 모듈의 build.gradle을 kotlin-dsl 을 사용하여 혁신(?)적으로 관리한다. (모듈이 많으면 gradle이 많아지는 단점이 있다.)
관련글
[우아한 형제들 기술 블로그Gradel Kotlin DSL 이야기 ] : https://techblog.woowahan.com/2625/
위 글을 통해 kotlin-dsl 에 대해 알아보았다. 개인적으로 배운 점&기억해야될 것들을 요약해보았다.
멀티 프로젝트(모듈)
프로젝트를 구성하다보면 공통된 기능과 코드를 하나의 모듈로 몰아놓고 역할에 따라서 각기 다른 모듈에서 참조하여 사용하는 방식을 사용한다.
하위 프로젝트에 대한 정의를 최상위 프로젝트에서 allprojects , subprojects 속성을 통해 각 프로젝트의 공통 속성과 작동을 정의할 수 있다. (모듈에 대해 좀 더 알아봐야 겠다..)
Gradle Kotlin DSL
내가 기존에 사용하고 있던 dsl은 확장자명이 .gradle 로 끝나는 Groovy DSL 이다. (DSL 이란 특정 분야에 최적화된 프로그래밍 언어를 뜻한다.) Groovy DSL 과 Kotlin DSL 을 비교해보자.
Groovy DSL / Kotlin DSL 비교
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 31
buildToolsVersion "31.0.0"
defaultConfig {
applicationId "com.example.composeuibasic"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.10'
}
}
Kotlin DSL
import com.guru.composecookbook.build.configurations.ProjectConfigs
import com.guru.composecookbook.build.dependencies.*
plugins {
id("com.android.application")
id("kotlin-android")
id("kotlin-kapt")
}
android {
compileSdk = ProjectConfigs.compileSdkVersion
defaultConfig {
applicationId = ProjectConfigs.applicationId
minSdk = ProjectConfigs.minSdkVersion
targetSdk = ProjectConfigs.targetSdkVersion
versionCode = 1
versionName = "1.0"
multiDexEnabled = true
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
useIR = true
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = ProjectConfigs.kotlinCompilerExtensionVersion
}
}
코틀린 DSL 은 모든 문자열을 큰 따옴표(")로 작성한다. (코틀린 문법을 따르므로 문자열은 " " 로 묶어서 표현함.)
import를 사용가능하다.
Kotlin DSL 의 장점
Kotlin DSL 은 코틀린 언어적 특징인 가독성이 좋고 간략한 코드를 사용하여 Gralde 스크립팅을 하는 것을 목적으로 한다. 이를 통해 얻을 수 있는 이점은 다음과 같다.
- 코드 자동완성 사용 가능
- 컴파일 타임에 에러 확인
- 코드 탐색
- 구문 강조
- 소스코드와 동일한 언어의 사용
Kotlin DSL 의 단점
당연히 단점도 존재한다.
Kotlin DSL 사용
1. Groovy DSL -> Kotlin DSL 변경
변경하는 법은 간단하다. 기존 .gradle 파일을 *.gradle.kts로 변경하면 된다.
예) build.gradle -> build.gradle.kts
2. buildSrc로 버전관리 하기
관련글
[Android Studio의 build.gradle 자동 완성을 위한 Kotlin 및 buildSrc를 사용한 Gradel 종속성 관리] :
buildSrc를 만드는 방법은 위 유튜브 동영상을 보면 이해할 수 있다.
추가적으로 build 캐시를 git에서 관리하지 않도록 .gitignore에 buildSrc/build 를 추가한다.
ComposeBook Kotlin DSL 사용법 분석
1. ProjectConfigs
sdk 에 대한 정보 / 앱 ID / kotlin 컴파일러 버전을 관리하는 object이다.object ProjectConfigs {
const val compileSdkVersion = 30
const val minSdkVersion = 21
const val targetSdkVersion = 30
const val applicationId = "com.guru.composecookbook"
const val kotlinCompilerExtensionVersion = Versions.compose
}
object Dependencies {
const val composeUi = "androidx.compose.ui:ui:${Versions.compose}"
const val composeUiTooling = "androidx.compose.ui:ui-tooling:${Versions.compose}"
const val composeMaterial = "androidx.compose.material:material:${Versions.compose}"
const val composeMaterialIconsExtended =
"androidx.compose.material:material-icons-extended:${Versions.compose}"
const val composeRuntimeLivedata =
"androidx.compose.runtime:runtime-livedata:${Versions.compose}"
// 생략..
internal val composeOfficialDependencies = listOf(
Dependencies.composeUi,
Dependencies.composeUiTooling,
Dependencies.composeMaterial,
Dependencies.composeMaterialIconsExtended,
Dependencies.composeRuntimeLivedata,
Dependencies.composeConstraintLayout,
Dependencies.composePaging,
Dependencies.composeViewModel,
Dependencies.composeActivity,
Dependencies.composeNavigation,
)
4. DependencyHandlerExtensions.kt
DependencyHandler 의 확장함수를 정의하는 부분이다. GroupDependencies의 리스트 변수들에 implementaion 을 붙여준다. build.gradle.ktx 에서 함수처럼 사용할 수 있다.
import org.gradle.api.artifacts.dsl.DependencyHandler
fun DependencyHandler.addComposeOfficialDependencies() {
composeOfficialDependencies.forEach {
add("implementation", it)
}
}
Module plugin 관리
plugins {
/**
* See [common-compose-module-configs-script-plugin.gradle.kts] file
*/
id("common-compose-module-configs-script-plugin")
}
dependencies {
implementation(project(":data"))
addComposeOfficialDependencies()
}
위 코드처럼 모듈의 id("common-compose-module-configs-script-plugin") 를 사용하여 plugin , kotlin android, android {} 블록을 불러와보자.
1. buildSrc의 build.gradle.kts 에 다음 의존성 추가
dependencies {
// in order to be able to use "kotlin-android" in the common script
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10")
// in order to recognize the "plugins" block in the common script
implementation("com.android.tools.build:gradle:7.1.0-alpha02")
// in order to recognize the "android" block in the common script
implementation("com.android.tools.build:gradle-api:7.1.0-alpha02")
}
2. buildSrc 폴더에 file 추가 common-compose-module-configs-script-plugin.gradle.kts / common-kotlin-module-configs-script-plugin.gradle.kts 추가 (두 파일의 차이는 Compose 전용 컴파일러 설정)
//compose module configs script
plugins {
id("com.android.library")
id("kotlin-android")
}
android {
compileSdk = ProjectConfigs.compileSdkVersion
defaultConfig {
minSdk = ProjectConfigs.minSdkVersion
targetSdk = ProjectConfigs.targetSdkVersion
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = ProjectConfigs.kotlinCompilerExtensionVersion
}
}
// kotlin-module-configs-script
plugins {
id("com.android.library")
id("kotlin-android")
id("kotlin-kapt")
}
android {
compileSdk = ProjectConfigs.compileSdkVersion
defaultConfig {
minSdk = ProjectConfigs.minSdkVersion
targetSdk = ProjectConfigs.targetSdkVersion
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
이제 plugins 에 id("common-compose-module-configs-script-plugin") 를 추가하면 첫 번째 compose script가 입력된다.
Kotlin DSL 을 사용하면 모듈들의 gradle 과 버전을 쉽게 관리할 수 있다는 것을 배웠다.
이번 기회를 통해 클린 아키텍처에 대해 관심이 생겼다.
핵심은 '어떻게 하면 좀 더 쉽게 유지보수를 하고 구조화할 수 있을까?' 인 거 같다.
작은 토이프로젝트에서는 이런 구조들이 필요 없을 가능성이 높지만, 앞으로 내가 만들 서비스들을 계속해서 발전시키려면 이런 구조들을 적용시키는 것이 좋을 거 같다.
클린 아키텍처 / 모듈에 대해 더 공부해 나가자.