Gradle Kotlin 컨벤션 플러그인으로 효율적으로 멀티 모듈 관리하기

Gradle Kotlin 컨벤션 플러그인으로
효율적으로 모듈 관리하기
윤영직 / 헤이딜러
멀티 모듈 프로젝트
멀티 모듈 프로젝트
:app
이게 바로 슈퍼앱!?
멀티 모듈 프로젝트
:app :domain :data
:local
:remote
멀티 모듈 프로젝트
:app
:feature:setting :feature:home :feature:car
:domain
:core-ui :designsystem
:data-xxx :network :navigation
멀티 모듈 프로젝트
❏ 빠른 빌드 시간
❏ 관심사 분리
❏ 테스트
❏ 그 밖의 여러가지 장점들...
A FEW
MOMENTS LATER
모듈이 점점 많아져요 👍
하지만 build.gradle
빌드 스크립트 중복 코드 😱
// build.gradle.kts
plugins {
id(“com.android.library”)
kotlin(“android”)
...
}
android {
minSdk = 24
compileSdk = 33
defaultConfig { ... }
...
}
dependencies { ... }
안드로이드 모듈이 모두 같은 플러그인을 사용합니다.
// build.gradle.kts
android {
compileSdk = 33
defaultConfig {
minSdk = 24
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
}
그 밖의 다른 동일한 코드도 많이 있습니다.
// build.gradle.kts (hilt)
plugins {
kotlin(“kapt”)
id("dagger.hilt.android.plugin")
...
}
android {
...
}
dependencies {
implementation(libs.hilt.android)
kapt(libs.hilt.android.compiler)
kaptAndroidTest(libs.hilt.android.compiler)
}
// build.gradle.kts (compose)
android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.testManifest)
}
// build.gradle.kts (:feature:home)
plugins {
...
}
android {
...
}
dependencies {
// compose…
implementation(project(“:core:designsystem”)
implementation(project(“:core:ui”)
implementation(project(“:core:domain”)
...
}
기능 모듈에서 공통으로 사용하는 의존성
빌드 로직 컨벤션
❏ 이처럼 모듈에는 재사용이 가능한 중복 코드들이 많이 있다.
❏ 어떤 로직을 재사용할지 정하는 것은 하나의 컨벤션이다.
❏ 모듈의 종류와 개수가 많아질수록 이러한 컨벤션은 더욱 중요하다!
❏ 그렇다면 빌드 로직을 어떤 방법으로 재사용 할 수 있을까?
Gradle Plugin
❏ 빌드 로직을 재사용할 수 있는 확장 기능
❏ Gradle Task를 추가하거나 설정을 관리
❏ id(“com.android.application”) 덕분에 앱이 실행할 수 있게 만들어짐
❏ 만약 이러한 플러그인이 없다면, 수많은 중복 코드를 작성해야 함
Gradle Plugin
Gradle Plugin
Script Plugin Binary Plugin
스크립트 코드를 별도 파일로 분리
apply(from=”common.gradle”)
apply(from=”project.gradle”)
...
Plugin 인터페이스를 구현하는 클래스 작성
플러그인 아이디를 등록해서 사용
plugins {
id(“my.custom.plugin”)
}
Gradle Plugin
Precompiled Script Plugin
Binary Plugin을 클래스로 작성하는 대신 xxx.gradle.kts 파일의
스크립트 형태로 간편하게 작성할 수 있는 확장 플러그인
- buildSrc/src/main/kotlin/common.android.gradle.kts
// build.gradle.kts
plugins {
id(“common.android”)
}
Script Plugin
// build.gradle.kts :feature:home
android {
compileSdk = 33
defaultConfig {
minSdk = 24
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
}
눈에 보이는 중복코드를 찾아 봅시다.
Script Plugin
// common.android.gradle
android {
minSdk = 24
defaultConfig {
compileSdk = 33
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring libs.android.desugarJdkLibs
}
Script Plugin
그대로 복사해서 groovy로 작성합니다.
groovy로 만든 이유는 잠시 후에...
// build.gradle.kts :feature:home
android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
...
}
Script Plugin
compose 관련 코드도 중복이 많이 있네요.
// common.android.compose.gradle
android {
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
implementation platform(libs.androidx.compose.bom)
implementation libs.androidx.compose.ui
implementation libs.androidx.compose.ui.tooling.preview
implementation libs.androidx.compose.material3
...
}
Script Plugin
마찬가지로 그대로 옮겨서 작성합니다.
// build.gradle.kts :feature:home
plugins {
kotlin(“kapt”)
id("dagger.hilt.android.plugin")
}
dependencies {
implementation(libs.hilt.android)
kapt(libs.hilt.android.compiler)
}
hilt는 플러그인 추가가 필요합니다.
Script Plugin
// common.android.hilt.gradle
apply plugin: 'com.google.dagger.hilt.android'
apply plugin: 'org.jetbrains.kotlin.kapt'
dependencies {
implementation libs.hilt.android
kapt libs.hilt.android.compiler
}
Script Plugin
// common.android.hilt.gradle
plugins { ... }
// Only Project and Settings build scripts can contain plugins {} blocks
apply plugin: 'com.google.dagger.hilt.android'
apply plugin: 'org.jetbrains.kotlin.kapt'
dependencies {
implementation libs.hilt.android
kapt libs.hilt.android.compiler
}
Script Plugin
plugins { }는 사용할 수 없습니다.
// build.gradle.kts :feature:home
plugins {
id(“com.android.library”)
kotlin(“android”)
}
apply(from=”common.android.gradle”)
apply(from=“common.android.compose.gradle”)
apply(from=”common.android.hilt.gradle”)
dependencies {
implementation(project(":core:domain"))
implementation(project(":core:designsystem"))
testImplementation(libs.junit4)
androidTestImplementation(libs.androidx.test.ext)
androidTestImplementation(libs.androidx.test.espresso.core)
}
Script Plugin
지금까지 작성한 파일은
apply를 이용해서 적용할 수 있습니다.
// build.gradle.kts :feature:setting
plugins {
id(“com.android.library”)
kotlin(“android”)
}
apply(from=”common.android.gradle”)
apply(from=“common.android.compose.gradle”)
apply(from=”common.android.hilt.gradle”)
dependencies {
implementation(project(":core:domain"))
implementation(project(":core:designsystem"))
testImplementation(libs.junit4)
androidTestImplementation(libs.androidx.test.ext)
androidTestImplementation(libs.androidx.test.espresso.core)
}
Script Plugin
다른 feature 모듈에서도 동일하지만,
문제는 또 다른 중복코드가 발생합니다.
// common.android.feature.gradle
apply(from=”common.android.gradle”)
apply(from=“common.android.compose.gradle”)
apply(from=”common.android.hilt.gradle”)
dependencies {
implementation(project(":core:domain"))
implementation(project(":core:designsystem"))
testImplementation(libs.junit4)
androidTestImplementation(libs.androidx.test.ext)
androidTestImplementation(libs.androidx.test.espresso.core)
}
Script Plugin
feature 컨벤션을 별도 파일로 분리합니다.
// build.gradle.kts :feature:home
plugins {
id(“com.android.library”)
kotlin(“android”)
}
apply(from=”common.android.feature.gradle”)
Script Plugin
이제는 3줄의 코드로 작성할 수 있습니다.
Script Plugin
❏ 가장 단순하고 빠르게 사용할 수 있는 빌드 로직 재사용 방법
❏ 그런데 왜 groovy로만 작성하나요?
Gradle Kotlin DSL은 타입에 안전하게 접근하기 때문에 Script Plugin을 사용할 수 없음
https://docs.gradle.org/current/userguide/kotlin_dsl.html#sec:kotlin_using_standard_api
Binary Plugin
app/
buildSrc/
src/main/kotlin/
AndroidLibraryPlugin.kt
AndroidHiltPlugin.kt
AndroidComposePlugin.kt
AndroidFeaturePlugin.kt
build.gradle.kts
core/
designsystem/
data/
feature/
home/
setting/
Binary Plugin
buildSrc에서 플러그인을 작성합니다.
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
dependencies {
implementation(libs.android.gradlePlugin)
implementation(libs.kotlin.gradlePlugin)
implementation(libs.hilt.gradlePlugin)
}
Binary Plugin
buildSrc를 사용하기 위한 kotlin-dsl
플러그인 작성을 위한 의존성을 추가합니다.
app/
buildSrc/
src/main/kotlin/
AndroidLibraryPlugin.kt
AndroidHiltPlugin.kt
AndroidComposePlugin.kt
AndroidFeaturePlugin.kt
build.gradle.kts
core/
designsystem/
data/
feature/
home/
setting/
AndroidLibraryPlugin Binary Plugin
다음으로 플러그인을 하나씩 작성합니다.
// build.gradle.kts :feature:home
plugins {
id(“com.android.library”)
kotlin(“android”)
}
AndroidLibraryPlugin Binary Plugin
안드로이드 모듈에서 항상 사용하는 플러그인
internal class AndroidLibraryPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
with(pluginManager) {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
}
...
}
}
AndroidLibraryPlugin Binary Plugin
다른 플러그인을 적용할 수 있습니다.
// build.gradle.kts :feature:home
android {
compileSdk = 33
defaultConfig {
minSdk = 24
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
}
AndroidLibraryPlugin Binary Plugin
안드로이드 버전 관련 설정 코드
internal class AndroidLibraryPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
...
extensions.configure<LibraryExtension> {
compileSdk = 33
defaultConfig.minSdk = 24
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
}
}
android { ... } 블록 접근을 위한 코드
AndroidLibraryPlugin Binary Plugin
// build.gradle.kts :feature:home
android {
compileSdk = 33
defaultConfig {
minSdk = 24
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
}
AndroidLibraryPlugin Binary Plugin
다른 코드도 동일한 방식으로 작성합니다.
internal class AndroidLibraryPlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
...
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
add("coreLibraryDesugaring",libs.findLibrary("android.desugarJdkLibs").get())
}
...
}
}
AndroidLibraryPlugin Binary Plugin
버전 카탈로그는 extensions으로 접근합니다.
// buildSrc/build.gradle.kts
gradlePlugin {
plugins {
register("androidLibrary") {
id = "convention.android.library"
implementationClass = "AndroidLibraryPlugin"
}
}
}
AndroidLibraryPlugin Binary Plugin
플러그인을 Gradle Project에 등록합니다.
id는 실제 적용할 때 사용됩니다.
app/
buildSrc/
src/main/kotlin/
AndroidLibraryPlugin.kt
AndroidHiltPlugin.kt
AndroidComposePlugin.kt
AndroidFeaturePlugin.kt
build.gradle.kts
core/
designsystem/
data/
feature/
home/
setting/
AndroidHiltPlugin Binary Plugin
Hilt 관련 플러그인도 이어서 작성합니다.
// build.gradle.kts :feature:home
plugins {
kotlin(“kapt”)
id(“dagger.hilt.android.plugin”)
}
dependencies {
implementation(libs.hilt.android)
kapt(libs.hilt.android.compiler)
kaptAndroidTest(libs.hilt.android.compiler)
}
AndroidHiltPlugin Binary Plugin
internal class AndroidHiltPlugin: Plugin<Project> {
override fun apply(target: Project) = with(target) {
with(pluginManager) {
apply("dagger.hilt.android.plugin")
apply("org.jetbrains.kotlin.kapt")
}
...
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
"implementation"(libs.findLibrary("hilt.android").get())
"kapt"(libs.findLibrary("hilt.android.compiler").get())
"kaptAndroidTest"(libs.findLibrary("hilt.android.compiler").get())
}
}
}
AndroidHiltPlugin Binary Plugin
// buildSrc/build.gradle.kts
gradlePlugin {
plugins {
register("androidHilt") {
id = "convention.android.hilt"
implementationClass = "AndroidHiltPlugin"
}
}
}
AndroidHiltPlugin Binary Plugin
app/
buildSrc/
src/main/kotlin/
AndroidLibraryPlugin.kt
AndroidHiltPlugin.kt
AndroidComposePlugin.kt
AndroidFeaturePlugin.kt
build.gradle.kts
core/
designsystem/
data/
feature/
home/
setting/
AndroidComposePlugin Binary Plugin
Compose 관련 플러그인을 작성합니다.
// build.gradle.kts :feature:home
android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
...
}
AndroidComposePlugin Binary Plugin
internal class AndroidComposePlugin: Plugin<Project> {
override fun apply(target: Project) = with(target) {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
val android = extensions.findByType<LibraryExtension>()
android?.run {
buildFeatures.compose = true
composeOptions.kotlinCompilerExtensionVersion =
libs.findVersion("androidxComposeCompiler").get().toString()
}
dependencies {
val bom = libs.findLibrary("androidx-compose-bom").get()
"implementation"(platform(bom))
"implementation"(libs.findLibrary("androidx.compose.material3").get())
"implementation"(libs.findLibrary("androidx.compose.ui").get())
"implementation"(libs.findLibrary("...").get())
}
}
}
AndroidComposePlugin Binary Plugin
// buildSrc/build.gradle.kts
gradlePlugin {
plugins {
register("androidCompose") {
id = "convention.android.compose"
implementationClass = "AndroidComposePlugin"
}
}
}
AndroidComposePlugin Binary Plugin
// build.gradle.kts :core:designsystem
plugins {
id(“convention.android.library”)
id(“convention.android.compose”)
}
// build.gradle.kts :core:data
plugins {
id(“convention.android.library”)
id(“convention.android.hilt”)
}
정의한 플러그인을 조합해서 사용합니다.
AndroidFeaturePlugin Binary Plugin
app/
buildSrc/
src/main/kotlin/
AndroidLibraryPlugin.kt
AndroidHiltPlugin.kt
AndroidComposePlugin.kt
AndroidFeaturePlugin.kt
build.gradle.kts
core/
designsystem/
data/
feature/
home/
setting/
AndroidFeaturePlugin Binary Plugin
feature 컨벤션을 위한 플러그인을 만듭니다.
internal class AndroidFeaturePlugin : Plugin<Project> {
override fun apply(target: Project) = with(target) {
with(pluginManager) {
apply("convention.android.library")
apply("convention.android.hilt")
apply("convention.android.compose")
}
dependencies {
"implementation"(project(":core:domain"))
"implementation"(project(":core:designsystem"))
...
}
}
AndroidFeaturePlugin Binary Plugin
앞서 등록한 플러그인 아이디를 사용합니다.
// buildSrc/build.gradle.kts
gradlePlugin {
plugins {
register("androidFeature") {
id = "convention.android.feature"
implementationClass = "AndroidFeaturePlugin"
}
}
}
AndroidFeaturePlugin Binary Plugin
// build.gradle.kts :feature:home
plugins {
id(“convention.android.feature”)
}
// build.gradle.kts :feature:car
plugins {
id(“convention.android.feature”)
}
// build.gradle.kts :feature:setting
plugins {
id(“convention.android.feature”)
}
이제 feature 모듈은 1줄로 끝입니다.
AndroidFeaturePlugin Binary Plugin
Binary Plugin
❏ 빌드 로직 캡슐화를 통해 보다 추상적이고 높은 확장성 제공
❏ 하지만, Kotlin DSL에 대한 이해도가 요구되어 🔥난이도가 높음🔥
❏ Gradle Task와 같은 동작을 조합해서 복잡한 기능 사용 가능
❏ feature 모듈의 컨벤션을 하나의 플러그인으로 만들 수 있음
Precompiled
Script Plugin
Precompiled Script Plugin
❏ 그런데 항상 클래스를 구현하면 귀찮지 않을까요?
❏ Script Plugin과 Binary Plugin의 특징을 모두 사용할 수 없을까?
https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins
- Binary Plugin을 클래스로 작성하는 대신 xxx.gradle.kts 파일의 스크립트 형태로 간편하게 작성할
수 있는 확장 플러그인
- buildSrc/src/main/kotlin/common.android.gradle.kts
// build.gradle.kts
plugins {
id(“common.android”)
}
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
`kotlin-precompiled-script-plugin`
}
abstract class KotlinDslPlugin : Plugin<Project> {
override fun apply(project: Project): Unit = project.run {
...
apply<PrecompiledScriptPlugins>()
}
}
플러그인은 kotlin-dsl에 포함되어 있습니다.
Precompiled Script Plugin
// build.gradle.kts :feature:home
plugins {
id(“com.android.library”)
kotlin(“android”)
}
android {
...
compileOptions { ... }
}
dependencies {
coreLibraryDesugaring(libs.android.desugarJdkLibs)
}
조금 전에 작성한 코드를 그대로 따라갑니다.
Precompiled Script Plugin
// buildSrc/src/main/java/convention.android.library.gradle.kts
plugins {
id(“com.android.library”)
kotlin(“android”)
}
android {
...
compileOptions { ... }
}
dependencies {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
coreLibraryDesugaring(libs.findLibrary("android.desugarJdkLibs").get())
}
Precompiled Script Plugin
libs는 extensions으로 접근해야 합니다.
작성한 이름이 플러그인 아이디가 됩니다.
// buildSrc/src/main/java/convention.android.compose.gradle.kts
android {
// ???
buildFeatures.compose = true
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
...
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
compose 관련 설정도 그대로 옮겨줍니다.
Precompiled Script Plugin
// buildSrc/src/main/java/convention.android.compose.gradle.kts
android {
// Expression 'android' cannot be invoked as a function.
// The function 'invoke()' is not found
buildFeatures.compose = true
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
...
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
하지만 android { } 에서 오류가 발생합니다
Precompiled Script Plugin
android { } 블록은 플러그인에 포함되어
있기 때문에 스크립트 영역에서는 인식 할 수
없는 문제가 있습니다.
plugins {
id(“com.android.library”)
}
android {
buildFeatures.compose = true
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
}
dependencies {
...
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
}
Precompiled Script Plugin
현재 구현처럼 플러그인을 추가하거나
// buildSrc/src/main/java/convention.android.compose.gradle.kts
fun Project.android(action: CommonExtension<*, *, *, *>.() -> Unit) {
val androidExtension = extensions.getByName("android")
if (androidExtension is CommonExtension<*, *, *, *>) {
androidExtension.apply(action)
}
}
android {
...
}
Precompiled Script Plugin
Kotlin DSL을 이용해 접근할 수 있습니다.
// buildSrc/src/main/java/convention.android.hilt.gradle.kts
plugins {
kotlin(“kapt”)
id(“dagger.hilt.android.plugin”)
}
dependencies {
"implementation"(libs.findLibrary("hilt.android").get())
"kapt"(libs.findLibrary("hilt.android.compiler").get())
"kaptAndroidTest"(libs.findLibrary("hilt.android.compiler").get())
}
Precompiled Script Plugin
다시 돌아와서 hilt 관련 코드도 작성합니다.
// buildSrc/src/main/java/convention.android.library.gradle.kts
// buildSrc/src/main/java/convention.android.compose.gradle.kts
// buildSrc/src/main/java/convention.android.hilt.gradle.kts
// build.gradle.kts
plugins {
id(“convention.android.library”)
id(“convention.android.compose”)
id(“convention.android.hilt”)
}
Precompiled Script Plugin
사용하면 플러그인이 자동으로 만들어집니다.
// buildSrc/src/main/java/convention.android.feature.gradle.kts
plugins {
id(“convention.android.library”)
id(“convention.android.compose”)
id(“convention.android.hilt”)
}
...
// build.gradle.kts :feature:home
plugins {
id(“convention.android.feature”)
}
Precompiled Script Plugin
마지막으로 feature 컨벤션을 작성합니다
어떤 방법을 사용해야 할까?
❏ 프로젝트 상황에 맞게 적절한 방법을 사용하기
❏ 컨벤션을 정하는 만큼 팀원들과 충분한 대화를 해주세요.
buildSrc
vs
build-logic
buildSrc vs build-logic
App #1 App #2 :lib
Reposiory
buildSrc
buildSrc vs build-logic
App #1 App #2 :lib
Repository #1 Repository #2 Repository #3
buildSrc vs build-logic
App #1 App #2 :lib
Repository #1 Repository #2 Repository #3
buildSrc ??? buildSrc ??? buildSrc ???
buildSrc vs build-logic
Repo #1
Repo #2
Repo #3
build-logic
:lib
:lib
Repo #4
root/
build-logic/
settings.gradle.kts
build.gradle.kts
src/main/kotlin/
convention.android.library.gradle.kts
convention.android.compose.gradle.kts
convention.android.hilt.gradle.kts
convention.android.feature.gradle.kts
library/
...
core/
...
build-logic
아까 작성한 파일은 그대로 옮겨줍니다.
// build-logic/settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
build-logic
Composite 빌드를 사용하기 때문에
settings.gradle.kts를 추가로 작성합니다.
버전 카탈로그는 명시적으로 추가합니다.
// settings.gradle.kts (app root project)
pluginManagement {
includeBuild("build-logic")
// includeBuild("shared/build-logic")
...
}
build-logic
build-logic을 빌드에 포함시킵니다.
만약 경로가 다르다면 맞춰서 작성합니다.
// build.gradle.kts :feature:home
plugins {
id(“convention.android.feature”)
}
사용하는 곳은 따로 변경할 필요 없습니다.
build-logic
buildSrc vs build-logic
buildSrc build-logic
- 단일 프로젝트
- 자주 변하지 않는 값 (앱 버전)
- 다중 프로젝트 및 레포지터리
- 빌드 로직을 루트 프로젝트에 종속성이
없도록 만들 때
- 빌드 로직을 뗐다 붙였다 하고 싶을 때
정리
❏ build.gradle을 효율적으로 관리하는 방법
❏ Gradle Plugin을 이용하여 빌드 로직에 대한 유지보수를 개선하기
❏ 우리팀의 빌드 로직 컨벤션을 정의해서 사용하기
❏ build-logic을 활용한 다른 프로젝트를 찾아보세요!
https://github.com/droidknights/DroidKnights2023_App/tree/main/build-logic
https://github.com/android/nowinandroid/tree/main/build-logic
https://github.com/chrisbanes/tivi/tree/main/gradle/build-logic
https://github.com/laco-dev/gradle-convention-plugins
정리
❏ 플러그인 만드는 것마저 귀찮다면?
❏ “Re:Android Studio 설정 살펴보기 및 생산성 올리기” 발표 채널고정
감사합니다
1 sur 83

Recommandé

Project Report on HTMLProject Report on HTML
Project Report on HTMLVijay Baidya
635 vues12 diapositives
Angularjs PPTAngularjs PPT
Angularjs PPTAmit Baghel
5.7K vues24 diapositives
Introduction to ASP.NETIntroduction to ASP.NET
Introduction to ASP.NETRajkumarsoy
16.8K vues21 diapositives

Contenu connexe

Tendances

AndroidAndroid
AndroidJindal Gohil
512 vues30 diapositives
Database in AndroidDatabase in Android
Database in AndroidMaryadelMar85
2.3K vues17 diapositives
JspJsp
JspPooja Verma
1.5K vues41 diapositives
Php PresentationPhp Presentation
Php PresentationManish Bothra
95.8K vues51 diapositives
react-slides.pptxreact-slides.pptx
react-slides.pptxDayNightGaMiNg
30 vues27 diapositives

Tendances(20)

AndroidAndroid
Android
Jindal Gohil512 vues
Database in AndroidDatabase in Android
Database in Android
MaryadelMar852.3K vues
JSON InjectionJSON Injection
JSON Injection
n|u - The Open Security Community38K vues
JspJsp
Jsp
Pooja Verma1.5K vues
Php PresentationPhp Presentation
Php Presentation
Manish Bothra95.8K vues
react-slides.pptxreact-slides.pptx
react-slides.pptx
DayNightGaMiNg30 vues
Android Data StoragefinalAndroid Data Storagefinal
Android Data Storagefinal
Nakka Srilakshmi611 vues
Android User InterfaceAndroid User Interface
Android User Interface
Shakib Hasan Sumon1.9K vues
Dart programming languageDart programming language
Dart programming language
Aniruddha Chakrabarti5.4K vues
Android intentsAndroid intents
Android intents
Siva Ramakrishna kv7K vues
FlutterFlutter
Flutter
Himanshu Singh25.9K vues
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
Vikash Singh71.1K vues
REST API Design & DevelopmentREST API Design & Development
REST API Design & Development
Ashok Pundit1.2K vues
Express jsExpress js
Express js
Manav Prasad6.6K vues
Android - Android Intent TypesAndroid - Android Intent Types
Android - Android Intent Types
Vibrant Technologies & Computers2.6K vues

Similaire à Gradle Kotlin 컨벤션 플러그인으로 효율적으로 멀티 모듈 관리하기

Mago3 d 워크샵Mago3 d 워크샵
Mago3 d 워크샵정대 천
76 vues47 diapositives

Similaire à Gradle Kotlin 컨벤션 플러그인으로 효율적으로 멀티 모듈 관리하기(20)

Gradle Kotlin 컨벤션 플러그인으로 효율적으로 멀티 모듈 관리하기