Gradle 모범 사례
Gradle 모범 사례 (Gradle best practices)
Gradle은 많은 Kotlin 프로젝트에서 빌드 과정을 자동화하고 관리하는 데 사용하는 빌드 시스템이에요. Gradle을 최대한 활용해 빌드를 관리하고 기다리는 시간을 줄이고, 코드를 쓰는 데 더 많은 시간을 쓰는 것이 중요하죠. 여기서는 프로젝트를 구성(organize)하고 최적화(optimize)하는 두 가지 핵심 영역으로 나눈 모범 사례를 소개할게요.
본문
구성하기 (Organize)
이 섹션은 Gradle 프로젝트를 구조화해서 명확성, 유지보수성, 확장성을 높이는 데 초점을 맞춰요.
Kotlin DSL 사용하기 (Use Kotlin DSL)
전통적인 Groovy DSL 대신 Kotlin DSL을 사용하세요. 언어를 하나 더 배울 필요가 없어지고, 엄격한 타입 지정의 이점도 얻을 수 있어요. 엄격한 타입 지정 덕분에 IDE가 리팩터링과 자동 완성을 더 잘 지원해서 개발이 효율적으로 이뤄져요.
Gradle의 Kotlin DSL primer에서 더 자세한 정보를 찾을 수 있고, Kotlin DSL이 새 Gradle 빌드의 기본이 된다는 Gradle 블로그도 읽어 보세요.
버전 카탈로그 사용하기 (Use a version catalog)
libs.versions.toml 파일의 버전 카탈로그를 사용하면 의존성 관리를 중앙화할 수 있어요. 프로젝트 전반에서 버전, 라이브러리, 플러그인을 일관되게 정의하고 재사용할 수 있게 되죠.
[versions]
kotlinxCoroutines = "1.11.0"
[libraries]
kotlinxCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
그리고 build.gradle.kts 파일에는 다음과 같은 의존성을 추가해요.
dependencies {
implementation(libs.kotlinxCoroutines)
}
의존성 관리 기초에 관한 Gradle 문서에서 더 알아보세요.
컨벤션 플러그인 사용하기 (Use convention plugins)
여러 빌드 파일에서 공통으로 쓰는 빌드 로직을 캡슐화하고 재사용하려면 컨벤션 플러그인을 사용하세요. 공통 설정을 플러그인으로 옮기면 빌드 스크립트를 단순화하고 모듈화할 수 있어요. 초기 설정은 시간이 걸릴 수 있지만, 한 번 완성해 두면 유지보수하고 새로운 빌드 로직을 추가하기가 쉬워져요.
컨벤션 플러그인에 관한 Gradle 문서에서 더 알아보세요.
최적화하기 (Optimize)
이 섹션은 Gradle 빌드의 성능과 효율성을 높이기 위한 전략을 다뤄요.
로컬 빌드 캐시 사용하기 (Use local build cache)
로컬 빌드 캐시를 사용하면 다른 빌드가 만들어 둔 출력물을 재사용해서 시간을 절약할 수 있어요. 빌드 캐시는 이전에 만든 어떤 빌드의 출력물이든 가져와 쓸 수 있어요.
빌드 캐시에 관한 Gradle 문서에서 더 알아보세요.
구성 캐시 사용하기 (Use configuration cache)
구성 캐시는 아직 모든 핵심 Gradle 플러그인을 지원하지 않아요. 최신 정보는 Gradle의 지원 플러그인 표를 확인하세요.
구성 캐시를 사용하면 구성 단계의 결과를 캐시해서 이후 빌드에서 재사용하므로 빌드 성능이 크게 개선돼요. Gradle이 빌드 구성이나 관련 의존성에 변화가 없다고 감지하면 구성 단계를 건너뛰죠. 구성 캐시는 단일 프로젝트 안에서 독립적인 작업들을 병렬로 실행할 수 있게 해서 빌드 성능을 더 높여요. 게다가 org.gradle.parallel 속성을 암시적으로 활성화해서 서로 다른 프로젝트의 작업들이 병렬로 실행될 수 있게 해줘요. 구성 캐시에 대해 더 자세히는 Gradle 문서에서 알아보세요.
여러 타깃의 빌드 시간 개선하기 (Improve build times for multiple targets)
멀티플랫폼 프로젝트에 여러 타깃이 있으면 build나 assemble 같은 작업이 타깃마다 같은 코드를 여러 번 컴파일해서 컴파일 시간이 길어질 수 있어요. 특정 플랫폼을 적극적으로 개발하고 테스트 중이라면 해당하는 linkDebug* 작업을 대신 실행하세요.
자세한 내용은 컴파일 시간 개선 팁을 참고하세요.
kapt에서 KSP로 옮기기 (Migrate from kapt to KSP)
kapt 컴파일러 플러그인에 의존하는 라이브러리를 사용한다면, Kotlin Symbol Processing (KSP) API를 사용하는 방식으로 바꿀 수 있는지 확인해 보세요. KSP API는 애노테이션 처리 시간을 줄여 빌드 성능을 개선해요. KSP는 중간 Java 스텁을 생성하지 않고 소스 코드를 직접 처리하기 때문에 kapt보다 빠르고 효율적이에요. 마이그레이션 단계에 대한 안내는 마이그레이션 가이드를 참고하세요.
모듈화 사용하기 (Use modularization)
모듈화는 중간 규모 이상의 프로젝트에서만 이점이 있어요. 마이크로서비스 아키텍처 기반 프로젝트에는 이점을 주지 못하죠.
모듈화된 프로젝트 구조를 사용하면 빌드 속도가 빨라지고 병렬 개발이 쉬워져요. 프로젝트를 루트 프로젝트 하나와 하나 이상의 서브프로젝트로 구성하세요. 변경이 서브프로젝트 중 하나에만 영향을 주면 Gradle은 해당 서브프로젝트만 다시 빌드해요.
.
└── root-project/
├── settings.gradle.kts
├── app subproject/
│ └── build.gradle.kts
└── lib subproject/
└── build.gradle.kts
Gradle로 프로젝트 구조화하기에 관한 Gradle 문서에서 더 알아보세요.
CI/CD 설정하기 (Set up CI/CD)
CI/CD 과정을 설정하면 증분 빌드와 의존성 캐싱을 활용해 빌드 시간을 크게 줄일 수 있어요. 이 이점을 보려면 영구 저장소(persistent storage)를 추가하거나 원격 빌드 캐시를 사용해야 해요. GitHub 같은 일부 제공자는 이 서비스를 거의 기본 제공하므로, 이 과정이 꼭 시간이 많이 걸리는 것은 아니에요.
지속적 통합 시스템에서 Gradle 사용하기에 관한 Gradle 커뮤니티 쿡북을 살펴보세요.
원격 빌드 캐시 사용하기 (Use remote build cache)
로컬 빌드 캐시와 마찬가지로 원격 빌드 캐시도 다른 빌드의 출력물을 재사용해 시간을 절약할 수 있게 해줘요. 마지막 빌드뿐 아니라 누군가 이전에 실행한 어떤 빌드의 작업 출력물이든 가져올 수 있어요.
원격 빌드 캐시는 캐시 서버를 사용해 빌드 간에 작업 출력물을 공유해요. 예를 들어 CI/CD 서버가 있는 개발 환경에서는 서버의 모든 빌드가 원격 캐시를 채워요. 메인 브랜치를 체크아웃해서 새 기능을 시작할 때 바로 증분 빌드에 접근할 수 있죠.
다만 인터넷 연결이 느리면 캐시된 결과를 전송하는 것이 로컬에서 작업을 실행하는 것보다 느려질 수 있다는 점을 기억하세요.
빌드 캐시에 관한 Gradle 문서에서 더 알아보세요.