SlideShare a Scribd company logo
1 of 83
Download to read offline
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 설정 살펴보기 및 생산성 올리기” 발표 채널고정
감사합니다

More Related Content

What's hot

인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍Chris Ohk
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Modulearjun singh
 
なんとなくOAuth怖いって思ってるやつちょっと来い
なんとなくOAuth怖いって思ってるやつちょっと来いなんとなくOAuth怖いって思ってるやつちょっと来い
なんとなくOAuth怖いって思ってるやつちょっと来いRyo Ito
 
Git 더하기 GitHub(구름IDE 환경)
Git 더하기 GitHub(구름IDE 환경)Git 더하기 GitHub(구름IDE 환경)
Git 더하기 GitHub(구름IDE 환경)Junyoung Lee
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS DirectivesEyal Vardi
 
카카오톡의 서버사이드 코틀린
카카오톡의 서버사이드 코틀린카카오톡의 서버사이드 코틀린
카카오톡의 서버사이드 코틀린if kakao
 
ReactJS vs Vue.js — What to choose in 2019?
ReactJS vs Vue.js — What to choose in 2019?ReactJS vs Vue.js — What to choose in 2019?
ReactJS vs Vue.js — What to choose in 2019?Pixel Crayons
 
Keycloak Single Sign-On
Keycloak Single Sign-OnKeycloak Single Sign-On
Keycloak Single Sign-OnRavi Yasas
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practicesfloydophone
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1Shahzad
 
GitLab과 Kubernetes를 통한 CI/CD 구축
GitLab과 Kubernetes를 통한 CI/CD 구축GitLab과 Kubernetes를 통한 CI/CD 구축
GitLab과 Kubernetes를 통한 CI/CD 구축철구 김
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in DockerDocker, Inc.
 

What's hot (20)

Git and git flow
Git and git flowGit and git flow
Git and git flow
 
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
 
Angular 4 The new Http Client Module
Angular 4 The new Http Client ModuleAngular 4 The new Http Client Module
Angular 4 The new Http Client Module
 
なんとなくOAuth怖いって思ってるやつちょっと来い
なんとなくOAuth怖いって思ってるやつちょっと来いなんとなくOAuth怖いって思ってるやつちょっと来い
なんとなくOAuth怖いって思ってるやつちょっと来い
 
Vue.js
Vue.jsVue.js
Vue.js
 
An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.js
 
Git 더하기 GitHub(구름IDE 환경)
Git 더하기 GitHub(구름IDE 환경)Git 더하기 GitHub(구름IDE 환경)
Git 더하기 GitHub(구름IDE 환경)
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
 
Top java script frameworks ppt
Top java script frameworks pptTop java script frameworks ppt
Top java script frameworks ppt
 
카카오톡의 서버사이드 코틀린
카카오톡의 서버사이드 코틀린카카오톡의 서버사이드 코틀린
카카오톡의 서버사이드 코틀린
 
ReactJS vs Vue.js — What to choose in 2019?
ReactJS vs Vue.js — What to choose in 2019?ReactJS vs Vue.js — What to choose in 2019?
ReactJS vs Vue.js — What to choose in 2019?
 
MVVM & RxSwift
MVVM & RxSwiftMVVM & RxSwift
MVVM & RxSwift
 
Keycloak Single Sign-On
Keycloak Single Sign-OnKeycloak Single Sign-On
Keycloak Single Sign-On
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practices
 
Design Pattern For C# Part 1
Design Pattern For C# Part 1Design Pattern For C# Part 1
Design Pattern For C# Part 1
 
GitLab과 Kubernetes를 통한 CI/CD 구축
GitLab과 Kubernetes를 통한 CI/CD 구축GitLab과 Kubernetes를 통한 CI/CD 구축
GitLab과 Kubernetes를 통한 CI/CD 구축
 
Angular Data Binding
Angular Data BindingAngular Data Binding
Angular Data Binding
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in Docker
 
Support cours angular
Support cours angularSupport cours angular
Support cours angular
 
Git best practices workshop
Git best practices workshopGit best practices workshop
Git best practices workshop
 

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

안드로이드를 위한 Gradle 맛들이기
안드로이드를 위한 Gradle 맛들이기안드로이드를 위한 Gradle 맛들이기
안드로이드를 위한 Gradle 맛들이기DongHwan Yu
 
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java ProjectJi-Woong Choi
 
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트Ji-Woong Choi
 
Mago3 d 워크샵
Mago3 d 워크샵Mago3 d 워크샵
Mago3 d 워크샵정대 천
 
mago3D 기술 워크샵 자료(한국어)
mago3D  기술 워크샵 자료(한국어)mago3D  기술 워크샵 자료(한국어)
mago3D 기술 워크샵 자료(한국어)SANGHEE SHIN
 
Spring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodeSpring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodedpTablo
 
DevOps - CI/CD 알아보기
DevOps - CI/CD 알아보기DevOps - CI/CD 알아보기
DevOps - CI/CD 알아보기SeungYong Baek
 
gradle로 안드로이드 앱 빌드하기
gradle로 안드로이드 앱 빌드하기gradle로 안드로이드 앱 빌드하기
gradle로 안드로이드 앱 빌드하기Manjong Han
 
3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약Tae wook kang
 
Front end dev 2016 & beyond
Front end dev 2016 & beyondFront end dev 2016 & beyond
Front end dev 2016 & beyondJae Sung Park
 
Windows에서 go+eclipse 개발환경 구축
Windows에서 go+eclipse 개발환경 구축Windows에서 go+eclipse 개발환경 구축
Windows에서 go+eclipse 개발환경 구축Jaehoon Kim
 
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오Booseol Shin
 
20130709 gradle
20130709 gradle20130709 gradle
20130709 gradleSukjin Yun
 
빠르고 지속적으로 전달하기: Continuous Delivery for Android
빠르고 지속적으로 전달하기: Continuous Delivery for Android빠르고 지속적으로 전달하기: Continuous Delivery for Android
빠르고 지속적으로 전달하기: Continuous Delivery for AndroidSangkyoon Nam
 
Kotlin 2.0을 통해 알아보는 코틀린의 미래
Kotlin 2.0을 통해 알아보는 코틀린의 미래Kotlin 2.0을 통해 알아보는 코틀린의 미래
Kotlin 2.0을 통해 알아보는 코틀린의 미래Leonardo YongUk Kim
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
 
Single-page Application
Single-page ApplicationSingle-page Application
Single-page ApplicationSangmin Yoon
 
Bigdata with Google Cloud
Bigdata with Google CloudBigdata with Google Cloud
Bigdata with Google Cloud정출 김
 
[shaderx6]8.2 3d engine tools with c++cli
[shaderx6]8.2 3d engine tools with c++cli[shaderx6]8.2 3d engine tools with c++cli
[shaderx6]8.2 3d engine tools with c++cli종빈 오
 
Kubernetes on GCP
Kubernetes on GCPKubernetes on GCP
Kubernetes on GCPDaegeun Kim
 

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

안드로이드를 위한 Gradle 맛들이기
안드로이드를 위한 Gradle 맛들이기안드로이드를 위한 Gradle 맛들이기
안드로이드를 위한 Gradle 맛들이기
 
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
[오픈소스컨설팅]Gradle Basic - How to use Gradle in Java Project
 
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트
[오픈소스컨설팅] Docker를 활용한 Gitlab CI/CD 구성 테스트
 
Mago3 d 워크샵
Mago3 d 워크샵Mago3 d 워크샵
Mago3 d 워크샵
 
mago3D 기술 워크샵 자료(한국어)
mago3D  기술 워크샵 자료(한국어)mago3D  기술 워크샵 자료(한국어)
mago3D 기술 워크샵 자료(한국어)
 
Spring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCodeSpring Boot + React + Gradle in VSCode
Spring Boot + React + Gradle in VSCode
 
DevOps - CI/CD 알아보기
DevOps - CI/CD 알아보기DevOps - CI/CD 알아보기
DevOps - CI/CD 알아보기
 
gradle로 안드로이드 앱 빌드하기
gradle로 안드로이드 앱 빌드하기gradle로 안드로이드 앱 빌드하기
gradle로 안드로이드 앱 빌드하기
 
3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약3D 모델러 ADDIN 개발과정 요약
3D 모델러 ADDIN 개발과정 요약
 
Front end dev 2016 & beyond
Front end dev 2016 & beyondFront end dev 2016 & beyond
Front end dev 2016 & beyond
 
Windows에서 go+eclipse 개발환경 구축
Windows에서 go+eclipse 개발환경 구축Windows에서 go+eclipse 개발환경 구축
Windows에서 go+eclipse 개발환경 구축
 
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오
우분투에서 안드로이드 개발환경 갖추기 ; 안드로이드 스튜디오
 
20130709 gradle
20130709 gradle20130709 gradle
20130709 gradle
 
빠르고 지속적으로 전달하기: Continuous Delivery for Android
빠르고 지속적으로 전달하기: Continuous Delivery for Android빠르고 지속적으로 전달하기: Continuous Delivery for Android
빠르고 지속적으로 전달하기: Continuous Delivery for Android
 
Kotlin 2.0을 통해 알아보는 코틀린의 미래
Kotlin 2.0을 통해 알아보는 코틀린의 미래Kotlin 2.0을 통해 알아보는 코틀린의 미래
Kotlin 2.0을 통해 알아보는 코틀린의 미래
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
Single-page Application
Single-page ApplicationSingle-page Application
Single-page Application
 
Bigdata with Google Cloud
Bigdata with Google CloudBigdata with Google Cloud
Bigdata with Google Cloud
 
[shaderx6]8.2 3d engine tools with c++cli
[shaderx6]8.2 3d engine tools with c++cli[shaderx6]8.2 3d engine tools with c++cli
[shaderx6]8.2 3d engine tools with c++cli
 
Kubernetes on GCP
Kubernetes on GCPKubernetes on GCP
Kubernetes on GCP
 

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