이번에 리드 안드로이드 개발자로 참여한 <terning>에서 프로젝트 초기세팅을 담당하게 되었다.
그래서 나는 Clean Architecture를 기반으로 멀티 모듈을 사용해 프로젝트를 세팅하고자 했다.
그 과정을 이제부터 소개하겠다.
Multi Module
멀티 모듈이란, 말 그대로 하나의 애플리케이션을 여러 개의 독립적인 모듈(Module)로 나누어 개발하는 방식을 말한다.
멀티 모듈을 사용하면 각 모듈마다 기능이 독립적으로 존재하기 때문에 개발하기 용이하다. 더불어 각 모듈에 대한 의존성 분리도 명확해지기 때문에 이를 도입하고자 했다.
안드로이드 스튜디오에서 멀티 모듈을 만드는 방법은 그리 어렵지 않다.
아래 루트를 따라서 클릭해주면 된다.
- app 모듈 우클릭 > New > Module
각 모듈마다 알맞는 템플릿을 선택해 준다.
- feature (UI의 기능을 하는 모듈) : Android Library
- domain (순수한 자바, 코틀린 코드로 이루어진 모듈) : Java or Kotlin Library
- data (비즈니스 로직을 작성하는 모듈) : Android Library
각 모듈의 의존성을 본인이 구상한 바에 맞게 연결해 준다.
dependencies {
implementation(project(":core"))
implementation(project(":data"))
implementation(project(":domain"))
implementation(project(":feature"))
}
위는 app 모듈의 의존성이다.
app 모듈의 경우 모든 모듈을 알고 있어야 하므로 내가 생성한 모든 모듈을 넣어주었다.
terning의 경우 모듈 의존성을 그래프로 나타내면 이와 같다.
마지막으로 각 모듈에 맞는 그래들 파일을 작성해주면 된다.
app 모듈의 그래들 파일만 예시로 가지고 와봤다.
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.hilt)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.ksp)
}
android {
namespace = "com.terning.point"
compileSdk = libs.versions.compileSdk.get().toInt()
defaultConfig {
applicationId = "com.terning.point"
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = libs.versions.versionCode.get().toInt()
versionName = libs.versions.versionName.get()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
buildConfigField(
"String",
"NATIVE_APP_KEY",
gradleLocalProperties(rootDir, providers).getProperty("native.app.key"),
)
manifestPlaceholders["NATIVE_APP_KEY"] =
gradleLocalProperties(rootDir, providers).getProperty("nativeAppKey")
}
buildTypes {
debug {
buildConfigField(
"String",
"BASE_URL",
gradleLocalProperties(rootDir, providers).getProperty("base.url")
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = libs.versions.jvmTarget.get()
}
buildFeatures {
compose = true
buildConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExtensionVersion.get()
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
excludes += "/META-INF/gradle/incremental.annotation.processors"
}
}
}
VersionCatalog
위 각 모듈의 그래들 코드를 보면 Gradle Version Catalog 방식을 사용한 흔적을 찾을 수 있을 것이다.
version catalog는 의존성과 버전을 한 곳에서 관리할 수 있도록 도와주는 기능이다.
이는 libs.versions.toml 파일에서 작성해 주면 된다.
총 세 가지 카테고리로 이루어져 있다.
- 1. versions
- libraries와 plugins에서 사용되는 버전 정보를 담는다.
[versions]
lottieVersion = "6.0.0"
- 2. libraries
- 의존성 정보를 담는다.
- 기존의 라이브러리에서 :을 통해 구분하여 group : name : version.ref 로 나타낸다.
- 그래들에서 사용할 때는 아래처럼 사용해주면 된다.
[libraries]
lottie = {group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottieVersion"}
dependencies {
implementation(libs.lottie)
}
- 3. plugins
- 플러그인 정보를 담는다.
- 그래들에서 사용할 때는 아래처럼 사용해주면 된다.
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
plugins {
alias(libs.plugins.android.library)
}
KAPT -> KSP 마이그레이션
- KAPT는 java로 작성되어 있지만, KSP는 kotlin을 기반으로 작성되어 있기 때문에 효율적이며, 더 빠른 컴파일 타임을 제공한다.
KSP를 사용하기 위해선 먼저 프로젝트 단의 그래들에 명시해준다.
plugins {
alias(libs.plugins.ksp) apply false
}
이때 버전 카탈로그에는 다음과 같이 작성이 되어 있다.
ksp = "1.9.0-1.0.12"
[plugins]
ksp = {id = "com.google.devtools.ksp", version.ref = "ksp"}
그리고 모듈 단의 그래들에 아래처럼 작성해주면 된다.
plugins {
alias(libs.plugins.ksp)
}
트러블슈팅 기록
컴포즈로 멀티모듈을 생성하다 보면 아래와 같은 오류 메세지를 볼 수 있을 것이다.
Execution failed for task ':feature:mergeDebugAndroidTestJavaResource'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.MergeJavaResWorkAction
> 2 files found with path 'META-INF/gradle/incremental.annotation.processors' from inputs:
이 에러는 두 개의 라이브러리(hilt-compiler와 dagger-compiler)가 동일한 리소스 파일을 포함하고 있어서 발생한 것이다.
이를 해결하기 위해 build.gradle 파일의 android 블록에 packagingOptions를 추가하여 충돌을 해결하였다.
android {
packagingOptions {
resources {
excludes += 'META-INF/gradle/incremental.annotation.processors'
}
}
}
마무리
프로젝트 초기세팅을 하는 것은 안드로이드에 대한 기본 지식을 다질 수 있는 좋은 기회라고 생각한다.
앱이 어떻게 이루어져 있는지, 어떤 방식으로 구축해야 효율적인지를 생각하며 개발하니 아키텍처에 대한 지식을 얻어갈 수 있었다.
내가 프로젝트 초기세팅을 한 과정이 담긴 PR 링크도 남기도록 하겠다.
📍프로젝트 초기세팅 PR: https://github.com/teamterning/Terning-Android/pull/2
[ADD/#1] 프로젝트 초기 세팅 by leeeyubin · Pull Request #2 · teamterning/Terning-Android
closed [ADD] 프로젝트 초기 세팅 #1 ⛳️ Work Description gradle 기초 세팅 manifest 기초 세팅 naviagtion 세팅 모듈 세팅 myApp 추가 확장함수 추가 디렉토리 별 dummy 파일 만들어두기 themes 기초 세팅 타이포
github.com
'Develop > Android' 카테고리의 다른 글
[Android] Dokka 문서화 총 정리 (+with 자동 배포) (0) | 2024.08.12 |
---|---|
[Android] 카카오 소셜 로그인 구현하기 (Kakao SDK) (0) | 2024.07.06 |
[Android] Nullable, NonNull, Kotlin scope function (1) | 2024.01.23 |
[Android] 아키텍처 패턴 (2) | 2024.01.23 |
[Android] 코루틴과 Channel (0) | 2024.01.23 |