고급 스크립팅 & 커스텀 플러그인
1. 고급 스크립팅 개념
1.1 Groovy vs. Kotlin DSL
Gradle 빌드 스크립트는 기본적으로 Groovy DSL을 사용하지만, Kotlin DSL(kts)도 지원합니다.
1. Groovy DSL
• 기존 빌드 스크립트에서 오랫동안 사용되어 왔습니다.
• 동적 타이핑 언어라, IDE 지원(코드 자동 완성, 타입 체크)이 제한적일 수 있습니다.
2. Kotlin DSL(kts)
• 정적 타이핑 기반이라 IDE에서 자동 완성, 타입 안전성을 더 잘 제공해줍니다.
• 최근 프로젝트에서 도입이 늘어나고 있으며, 함수 시그니처나 프로퍼티를 IDE가 인식해주므로 개발 생산성이 높아집니다.
둘 중 어느 것을 쓰더라도 Gradle 기능 자체는 동일하지만, Kotlin DSL을 사용하면 코드 가독성과 유지보수 측면에서 이점이 있을 수 있습니다.
2. BuildSrc & Version Catalog
2.1 BuildSrc
Gradle에서 빌드 스크립트 관련 로직(함수, 상수, 도우미)을 따로 모아두고 싶다면, 프로젝트 루트에 buildSrc 폴더를 만들고 Kotlin(또는 Groovy) 소스 파일을 배치할 수 있습니다.
1. buildSrc 폴더 구조
project-root
└ buildSrc
└ src
└ main
└ kotlin
└ MyBuildLogic.kt
2. 자동 컴파일 & 클래스패스 반영
• buildSrc 내에 작성한 코드는 빌드 스크립트 실행 전에 자동 컴파일되어, 모든 하위 모듈에서 바로 사용할 수 있습니다.
• 예: MyBuildLogic.kt에 공통 함수 fun androidLibraryConfig(...) { ... }를 정의해두면, 각 모듈의 build.gradle.kts에서 손쉽게 호출 가능.
2.2 Version Catalog
Version Catalog는 Gradle 7.x 이상에서 지원하는 기능으로, 프로젝트 전역에서 사용하는 라이브러리 버전과 디펜던시를 한 곳에 모아 관리할 수 있습니다.
• gradle/libs.versions.toml 파일에 라이브러리와 버전을 명시한다.
• 각 모듈의 빌드 스크립트에서 libs를 통해 참조한다.
예시(libs.versions.toml):
[versions]
kotlin = "1.8.0"
coroutines = "1.6.4"
[libraries]
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" }
• 사용 시:
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.coroutines.core)
}
• 버전과 라이브러리를 중앙에서 관리하므로 버전 충돌이나 업그레이드 시 매우 편리합니다.
3. 커스텀 태스크 & 자동화
3.1 Gradle 태스크(Task) 작성
빌드 과정에서 특정 스크립트를 실행하거나, 파일을 전처리하려면 Custom Task를 만들 수 있습니다.
tasks.register("helloTask") {
group = "Custom"
description = "Prints a greeting"
doLast {
println("Hello from custom Gradle task!")
}
}
• tasks.register("helloTask")를 통해 태스크를 등록하고, gradlew helloTask 명령으로 실행할 수 있습니다.
• doFirst, doLast 블록에 원하는 로직(파일 복사, 리소스 생성, API 호출 등)을 작성하면 됩니다.
3.2 Task Dependencies
여러 태스크 간 의존관계를 설정해 순차적으로 실행시키는 것도 가능하다.
tasks.register("prepareData") {
doLast {
println("Preparing data...")
}
}
tasks.register("processData") {
dependsOn("prepareData")
doLast {
println("Processing data...")
}
}
• processData 실행 시, 자동으로 prepareData를 먼저 실행한다.
4. 커스텀 플러그인 작성
4.1 왜 커스텀 플러그인인가?
커스텀 플러그인은 빌드 스크립트 로직을 더 깔끔하게 캡슐화하여, 여러 프로젝트에서 쉽게 재사용할 수 있도록 한다.
• 여러 모듈에서 공통으로 사용하는 빌드 설정이나 태스크가 많을 때, 이를 플러그인 형태로 배포하면 프로젝트마다 손쉽게 적용이 가능하다.
4.2 플러그인 구조
• 플러그인 클래스: Gradle의 Plugin<Project> 인터페이스를 구현한다.
• META-INF/gradle-plugins/ 디렉터리 내에 플러그인 ID를 정의한 .properties 파일을 생성한다.
예시(MyCustomPlugin.kt):
plugins {
`java-gradle-plugin`
`maven-publish`
}
gradlePlugin {
plugins {
create("myCustomPlugin") {
id = "com.example.mycustomplugin"
implementationClass = "com.example.MyCustomPlugin"
}
}
}
• 이렇게 배포된 플러그인은 id "com.example.mycustomplugin" 형태로 다른 빌드 스크립트에서 선언해 사용할 수 있다.
5. Kotlin DSL 예시 (build.gradle.kts)
plugins {
id("com.android.application")
kotlin("android")
// 커스텀 플러그인을 적용해볼 수도 있음
}
android {
compileSdk = 33
defaultConfig {
applicationId = "com.example.app"
minSdk = 21
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("debug") {
// debug-specific config
}
getByName("release") {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android.txt"),
"proguard-rules.pro"
)
}
}
}
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.coroutines.core)
// ...
}
• Gradle Kotlin DSL(kts)을 사용하면 위처럼 정적 타입 지원을 받을 수 있으며, IDE 자동완성이 원활하다.
• dependencies 블록에서 Version Catalog의 libs 객체를 참조하는 모습을 볼 수 있다.
마무리
Gradle 빌드를 더욱 세련되게 다룰 수 있는 고급 스크립팅 & 커스텀 플러그인 기법을 소개했습니다.
1. Kotlin DSL로 빌드 스크립트를 작성하면, 가독성과 자동 완성을 대폭 개선할 수 있습니다.
2. BuildSrc와 Version Catalog를 통해 공통 로직과 라이브러리 버전을 체계적으로 관리합니다.
3. 커스텀 태스크와 커스텀 플러그인으로 반복되는 설정이나 작업을 캡슐화해, 여러 프로젝트에서 재사용할 수 있습니다.