Gradle 프로젝트 구성하기
Gradle 프로젝트 구성하기
Kotlin 프로젝트를 Gradle로 빌드하는 방법을 알아볼게요. 빌드 스크립트 파일 build.gradle(.kts)에 Kotlin Gradle 플러그인을 추가하고, 그 안에서 프로젝트 의존성을 구성하면 돼요.
본문
Gradle로 Kotlin 프로젝트를 빌드하려면, 빌드 스크립트 파일 build.gradle(.kts)에 Kotlin Gradle 플러그인을 추가하고 그 안에서 프로젝트의 의존성을 구성해야 해요.
플러그인 적용하기
Kotlin Gradle 플러그인을 적용하려면 Gradle 플러그인 DSL의 plugins{} 블록을 사용하면 돼요:
plugins {
// Replace `<...>` with the plugin name appropriate for your target environment
kotlin("<...>") version "2.4.20"
// For example, if your target environment is JVM:
// kotlin("jvm") version "2.4.20"
}
plugins {
// Replace `<...>` with the plugin name appropriate for your target environment
id 'org.jetbrains.kotlin.<...>' version '2.4.20'
// For example, if your target environment is JVM:
// id 'org.jetbrains.kotlin.jvm' version '2.4.20'
}
프로젝트를 구성할 때는 Kotlin Gradle 플러그인(KGP)이 사용 가능한 Gradle 버전과 호환되는지 확인해야 해요. 아래 표는 완전히 지원되는 Gradle과 Android Gradle 플러그인(AGP)의 최소·최대 버전을 보여줘요:
| KGP version | Gradle min and max versions | AGP min and max versions |
|---|---|---|
| 2.4.20 | 7.6.3–9.7.0 | 8.5.2–9.3.1 |
| 2.4.0-2.4.10 | 7.6.3–9.5.0 | 8.5.2–9.1.0 |
| 2.3.20–2.3.21 | 7.6.3–9.3.0 | 8.2.2–9.0.0 |
| 2.3.10 | 7.6.3–9.0.0 | 8.2.2–9.0.0 |
| 2.3.0 | 7.6.3–9.0.0 | 8.2.2–8.13.0 |
| 2.2.20–2.2.21 | 7.6.3–8.14 | 7.3.1–8.11.1 |
| 2.2.0–2.2.10 | 7.6.3–8.14 | 7.3.1–8.10.0 |
| 2.1.20–2.1.21 | 7.6.3–8.12.1 | 7.3.1–8.7.2 |
| 2.1.0–2.1.10 | 7.6.3–8.10* | 7.3.1–8.7.2 |
| 2.0.20–2.0.21 | 6.8.3–8.8* | 7.1.3–8.5 |
| 2.0.0 | 6.8.3–8.5 | 7.1.3–8.3.1 |
| 1.9.20–1.9.25 | 6.8.3–8.1.1 | 4.2.2–8.1.0 |
최신 릴리스까지의 Gradle과 AGP 버전도 사용할 수는 있지만, 그럴 경우 deprecation 경고를 만나거나 일부 새로운 기능이 동작하지 않을 수 있다는 점을 기억해두세요.
예를 들어, Kotlin Gradle 플러그인과 kotlin-multiplatform 플러그인 2.4.20은 프로젝트가 컴파일되기 위해서 최소 Gradle 버전 7.6.3을 요구해요.
비슷하게, 완전히 지원되는 최대 버전은 9.7.0이에요. 이 버전에는 deprecated된 Gradle 메서드·속성이 없고, 현재 Gradle 기능을 모두 지원해요.
이전 KGP 버전
| KGP version | Gradle min and max versions | AGP min and max versions |
|---|---|---|
| 1.9.0–1.9.10 | 6.8.3–7.6.0 | 4.2.2–7.4.0 |
| 1.8.20–1.8.22 | 6.8.3–7.6.0 | 4.1.3–7.4.0 |
| 1.8.0–1.8.11 | 6.8.3–7.3.3 | 4.1.3–7.2.1 |
| 1.7.20–1.7.22 | 6.7.1–7.1.1 | 3.6.4–7.0.4 |
| 1.7.0–1.7.10 | 6.7.1–7.0.2 | 3.4.3–7.0.2 |
| 1.6.20–1.6.21 | 6.1.1–7.0.2 | 3.4.3–7.0.2 |
프로젝트 안의 Kotlin Gradle 플러그인 데이터
기본적으로 Kotlin Gradle 플러그인은 지속적인(persistent) 프로젝트별 데이터를 프로젝트 루트의 .kotlin 디렉터리에 저장해요.
이 동작을 구성하기 위해 프로젝트 gradle.properties 파일에 추가할 수 있는 속성들이 있어요:
| Gradle property | Description |
|---|---|
kotlin.project.persistent.dir |
프로젝트 레벨 데이터가 저장되는 위치를 구성. 기본값: <project-root-directory>/.kotlin |
kotlin.project.persistent.dir.gradle.disableWrite |
.gradle 디렉터리에 Kotlin 데이터를 쓰는 것을 비활성화할지(구버전 IDEA와의 하위 호환용) 제어. 기본값: false |
JVM을 대상으로 할 때
JVM을 대상으로 하려면 Kotlin JVM 플러그인을 적용하면 돼요.
plugins {
kotlin("jvm") version "2.4.20"
}
plugins {
id "org.jetbrains.kotlin.jvm" version "2.4.20"
}
version은 이 블록 안에서 리터럴이어야 하며, 다른 빌드 스크립트에서 적용될 수 없어요.
Kotlin과 Java 소스
Kotlin 소스와 Java 소스는 같은 디렉터리에 저장할 수도 있고, 서로 다른 디렉터리에 둘 수도 있어요.
기본 관례는 서로 다른 디렉터리를 사용하는 거예요:
project
- src
- main (root)
- kotlin
- java
기본 관례를 사용하지 않는다면, 해당하는 sourceSets 속성을 업데이트해야 해요:
sourceSets.main {
java.srcDirs("src/main/myJava", "src/main/myKotlin")
}
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
main.java.srcDirs += 'src/main/myJava'
}
관련 컴파일 태스크의 JVM 대상 호환성 확인
빌드 모듈에는 서로 관련된 컴파일 태스크가 있을 수 있어요. 예를 들어:
compileKotlin과compileJavacompileTestKotlin과compileTestJava
이런 관련 태스크에 대해 Kotlin Gradle 플러그인은 JVM 대상 호환성을 확인해요. kotlin 확장 또는 태스크의 jvmTarget 속성 값과 java 확장 또는 태스크의 targetCompatibility 값이 다르면 JVM 대상 비호환성이 발생해요. 예를 들어: compileKotlin 태스크는 jvmTarget=1.8인데 compileJava 태스크는 targetCompatibility=15인(또는 상속받는) 경우죠.
이 검사의 동작을 프로젝트 전체에 대해 구성하려면 gradle.properties 파일의 kotlin.jvm.target.validation.mode 속성을 다음으로 설정하면 돼요:
error– 플러그인이 빌드를 실패시킴; Gradle 8.0+ 프로젝트의 기본값.warning– 플러그인이 경고 메시지를 출력; Gradle 8.0 미만 프로젝트의 기본값.ignore– 플러그인이 검사를 건너뛰고 어떤 메시지도 만들지 않음.
build.gradle(.kts) 파일에서 태스크 레벨로도 구성할 수 있어요:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile>().configureEach {
jvmTargetValidationMode.set(org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode.WARNING)
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile.class).configureEach {
jvmTargetValidationMode = org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode.WARNING
}
JVM 대상 비호환성을 피하려면 툴체인을 구성하거나 JVM 버전을 수동으로 맞춰주세요.
대상이 호환되지 않으면 뭐가 잘못될 수 있나요
Kotlin과 Java 소스셋의 JVM 대상을 수동으로 설정하는 방법은 두 가지가 있어요:
- Java 툴체인 설정을 통한 암묵적인 방법.
kotlin확장 또는 태스크의jvmTarget속성과java확장 또는 태스크의targetCompatibility를 설정하는 명시적인 방법.
JVM 대상 비호환성은 다음 경우에 발생해요:
jvmTarget과targetCompatibility를 서로 다른 값으로 명시적으로 설정한 경우.- 기본 구성을 쓰는데 JDK가
1.8이 아닌 경우.
빌드 스크립트에 Kotlin JVM 플러그인만 있고 JVM 대상에 대한 추가 설정이 없을 때, JVM 대상의 기본 구성을 살펴볼게요:
plugins {
kotlin("jvm") version "2.4.20"
}
plugins {
id "org.jetbrains.kotlin.jvm" version "2.4.20"
}
빌드 스크립트에 jvmTarget 값에 대한 명시적 정보가 없으면 그 기본값은 null이고, 컴파일러는 이를 기본값 1.8로 변환해요. targetCompatibility는 현재 Gradle의 JDK 버전과 같으며, (Java 툴체인 방식을 쓰지 않는 한) 여러분의 JDK 버전과도 같아요. JDK 버전이 17이라고 가정하면, 여러분이 게시한 라이브러리 아티팩트는 자신이 JDK 17+와 호환된다고 선언할 거예요: org.gradle.jvm.version=17 — 그런데 이건 틀린 거예요. 이 경우 바이트코드 버전은 1.8인데도 이 라이브러리를 추가하려면 메인 프로젝트에서 Java 17을 사용해야 해요. 이 문제를 해결하려면 툴체인을 구성하세요.
Gradle Java 툴체인 지원
Gradle 6.7에서 Java 툴체인 지원이 도입됐어요. 이 기능을 사용하면:
- Gradle과 다른 JDK·JRE를 사용해 컴파일, 테스트, 실행 파일을 돌릴 수 있어요.
- 아직 릴리스되지 않은 언어 버전으로 코드를 컴파일하고 테스트할 수 있어요.
툴체인 지원 덕분에 Gradle은 로컬 JDK를 자동 감지하고, 빌드에 필요한 누락된 JDK를 설치할 수 있어요. 이제 Gradle 자체는 아무 JDK에서든 실행될 수 있고, 메이저 JDK 버전에 의존하는 태스크에는 여전히 원격 빌드 캐시 기능을 재사용할 수 있어요.
Kotlin Gradle 플러그인은 Kotlin/JVM 컴파일 태스크의 Java 툴체인을 지원해요. JS와 네이티브 태스크는 툴체인을 사용하지 않아요. Kotlin 컴파일러는 항상 Gradle 데몬이 실행되고 있는 JDK 위에서 돌아가요. Java 툴체인은:
- JVM 대상에 사용할 수 있는
-jdk-home옵션을 설정해요. - 사용자가
jvmTarget옵션을 명시적으로 설정하지 않으면compilerOptions.jvmTarget을 툴체인의 JDK 버전으로 설정해요. 사용자가 툴체인을 구성하지 않으면jvmTarget필드는 기본값을 사용해요. JVM 대상 호환성에 대해 더 알아보세요. - 어떤 Java compile, test, javadoc 태스크가 사용할 툴체인을 설정해요.
kapt워커가 어떤 JDK에서 실행되는지에 영향을 줘요.
툴체인을 설정하려면 다음 코드를 사용하면 돼요. <MAJOR_JDK_VERSION> 자리표시자를 사용하고 싶은 JDK 버전으로 바꿔주세요:
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>))
}
// Or shorter:
jvmToolchain(<MAJOR_JDK_VERSION>)
// For example:
jvmToolchain(17)
}
kotlin {
jvmToolchain {
languageVersion = JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)
}
// Or shorter:
jvmToolchain(<MAJOR_JDK_VERSION>)
// For example:
jvmToolchain(17)
}
kotlin 확장을 통해 툴체인을 설정하면 Java 컴파일 태스크의 툴체인도 함께 업데이트된다는 점에 유의하세요.
java 확장을 통해서도 툴체인을 설정할 수 있고, Kotlin 컴파일 태스크가 그것을 사용해요:
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>))
}
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)
}
}
Gradle 8.0.2 이상을 사용한다면 툴체인 리졸버 플러그인도 추가해야 해요. 이 타입의 플러그인은 툴체인을 어느 리포지토리에서 다운로드할지 관리해요. 예를 들어 settings.gradle(.kts)에 다음 플러그인을 추가해주세요:
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version("1.0.0")
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
foojay-resolver-convention의 버전이 여러분의 Gradle 버전과 일치하는지 Gradle 사이트에서 확인하세요.
특정 태스크에 (로컬 JDK 포함) 아무 JDK나 설정하려면 Task DSL을 사용하면 돼요.
Kotlin 플러그인의 Gradle JVM 툴체인 지원에 대해 더 알아보세요.
Task DSL로 JDK 버전 설정하기
Task DSL을 사용하면 UsesKotlinJavaToolchain 인터페이스를 구현하는 어떤 태스크에든 아무 JDK 버전을 설정할 수 있어요. 현재 이 태스크들은 KotlinCompile과 KaptTask예요. Gradle이 메이저 JDK 버전을 검색하길 원한다면, 빌드 스크립트의 <MAJOR_JDK_VERSION> 자리표시자를 바꿔주세요:
val service = project.extensions.getByType<JavaToolchainService>()
val customLauncher = service.launcherFor {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>))
}
project.tasks.withType<UsesKotlinJavaToolchain>().configureEach {
kotlinJavaToolchain.toolchain.use(customLauncher)
}
JavaToolchainService service = project.getExtensions().getByType(JavaToolchainService.class)
Provider<JavaLauncher> customLauncher = service.launcherFor {
it.languageVersion = JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)
}
tasks.withType(UsesKotlinJavaToolchain::class).configureEach { task ->
task.kotlinJavaToolchain.toolchain.use(customLauncher)
}
또는 로컬 JDK의 경로를 지정하고 <LOCAL_JDK_VERSION> 자리표시자를 해당 JDK 버전으로 바꿀 수도 있어요:
tasks.withType<UsesKotlinJavaToolchain>().configureEach {
kotlinJavaToolchain.jdk.use(
"/path/to/local/jdk", // Put a path to your JDK
JavaVersion.<LOCAL_JDK_VERSION> // For example, JavaVersion.17
)
}
컴파일러 태스크 연결하기
한 컴파일이 다른 컴파일의 컴파일된 출력을 사용하도록, 컴파일 사이에 그런 관계를 설정해 컴파일들을 연결할 수 있어요. 컴파일을 연결하면 컴파일 사이에 internal 가시성이 생겨요.
Kotlin 컴파일러는 각 대상의 test와 main 컴파일처럼 일부 컴파일을 기본적으로 연결해요. 커스텀 컴파일 하나가 다른 컴파일과 연결된다는 것을 표현해야 한다면, 자신만의 연결된 컴파일을 만들면 돼요.
IDE가 소스셋 사이의 가시성 추론을 위해 연결된 컴파일을 지원하게 하려면 build.gradle(.kts)에 다음 코드를 추가해주세요:
val integrationTestCompilation = kotlin.target.compilations.create("integrationTest") {
associateWith(kotlin.target.compilations.getByName("main"))
}
integrationTestCompilation {
kotlin.target.compilations.create("integrationTest") {
associateWith(kotlin.target.compilations.getByName("main"))
}
}
여기서 integrationTest 컴파일은 main 컴파일과 연결되는데, 이로써 기능 테스트에서 internal 객체에 접근할 수 있게 돼요.
Java Modules(JPMS) 활성화 상태로 구성하기
Kotlin Gradle 플러그인이 Java Modules와 함께 동작하게 하려면, 빌드 스크립트에 다음 줄을 추가하고 YOUR_MODULE_NAME을 여러분의 JPMS 모듈 참조(예: org.company.module)로 바꿔주세요:
tasks.named("compileJava", JavaCompile::class.java) {
// Provide compiled Kotlin classes to javac – needed for Java/Kotlin mixed sources to work
val mainOutput: FileCollection = sourceSets["main"].output
options.compilerArgumentProviders.add(CommandLineArgumentProvider {
listOf("--patch-module", "YOUR_MODULE_NAME=${mainOutput.asPath}")
})
}
tasks.named("compileJava", JavaCompile.class) {
// Provide compiled Kotlin classes to javac – needed for Java/Kotlin mixed sources to work
FileCollection mainOutput = sourceSets["main"].output
options.compilerArgumentProviders.add(new CommandLineArgumentProvider() {
@Override
Iterable<String> asArguments() {
return ["--patch-module", "YOUR_MODULE_NAME=${mainOutput.asPath}"]
}
})
}
더 알아보기:
기타 세부사항
컴파일 태스크에서 아티팩트 사용 비활성화
드물지만 순환 의존성(circular dependency) 오류로 인해 빌드 실패를 겪을 수 있어요. 예를 들어 컴파일이 여러 개 있고, 한 컴파일이 다른 컴파일의 모든 internal 선언을 볼 수 있으며, 생성된 아티팩트가 두 컴파일 태스크의 출력 모두에 의존하는 경우예요:
FAILURE: Build failed with an exception.
What went wrong:
Circular dependency between the following tasks:
:lib:compileKotlinJvm
--- :lib:jvmJar
\--- :lib:compileKotlinJvm (*)
(*) - details omitted (listed previously)
이 순환 의존성 오류를 고치기 위해 archivesTaskOutputAsFriendModule라는 Gradle 속성을 추가했어요. 이 속성은 컴파일 태스크에서 아티팩트 입력의 사용을 제어하고, 그 결과로 태스크 의존성이 생성되는지 여부를 결정해요.
기본적으로 이 속성은 true로 설정되어 태스크 의존성을 추적해요. 순환 의존성 오류를 만난다면 컴파일 태스크에서 아티팩트 사용을 비활성화해 태스크 의존성을 제거하고 순환 의존성 오류를 피할 수 있어요.
컴파일 태스크에서 아티팩트 사용을 비활성화하려면 gradle.properties 파일에 다음을 추가해주세요:
kotlin.build.archivesTaskOutputAsFriendModule=false
Lazy한 Kotlin/JVM 태스크 생성
Kotlin 1.8.20부터 Kotlin Gradle 플러그인은 모든 태스크를 등록하고, dry run에서는 구성하지 않아요.
컴파일 태스크 destinationDirectory의 비기본 위치
Kotlin/JVM KotlinJvmCompile/KotlinCompile 태스크의 destinationDirectory 위치를 덮어쓴다면 빌드 스크립트를 업데이트해야 해요. JAR 파일의 sourceSets.main.outputs에 sourceSets.main.kotlin.classesDirectories를 명시적으로 추가해줘야 해요:
tasks.jar(type: Jar) {
from sourceSets.main.outputs
from sourceSets.main.kotlin.classesDirectories
}
여러 플랫폼을 대상으로 할 때
여러 플랫폼을 대상으로 하는 프로젝트(멀티플랫폼 프로젝트)는 kotlin-multiplatform 플러그인이 필요해요.
plugins {
kotlin("multiplatform") version "2.4.20"
}
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.4.20'
}
다양한 플랫폼을 위한 Kotlin Multiplatform과 iOS 및 Android용 Kotlin Multiplatform에 대해 더 알아보세요.
Android를 대상으로 할 때
Android 애플리케이션을 만들 때는 Android Studio를 사용하는 것이 좋아요. Android Gradle 플러그인 사용법을 알아보세요.
웹을 대상으로 할 때
Kotlin은 Kotlin Multiplatform을 통해 웹 개발에 두 가지 접근 방식을 제공해요:
- JavaScript 기반(Kotlin/JS 컴파일러 사용)
- WebAssembly 기반(Kotlin/Wasm 컴파일러 사용)
두 접근 방식 모두 Kotlin Multiplatform 플러그인을 사용하지만, 지원하는 사용 사례는 달라요. 아래 절에서는 각 대상을 Gradle 빌드에서 어떻게 구성하고 언제 사용할지 설명할게요.
JavaScript를 대상으로 할 때
Kotlin/JS는 다음 목표가 있을 때 사용하면 좋아요:
- JavaScript/TypeScript 코드베이스와 비즈니스 로직을 공유
- Kotlin으로 공유 불가능한 웹 앱 구축
자세한 내용은 웹 개발을 참고해주세요.
JavaScript를 대상으로 할 때는 kotlin-multiplatform 플러그인을 사용해요:
plugins {
kotlin("multiplatform") version "2.4.20"
}
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.4.20'
}
브라우저에서 실행할지 Node.js 환경에서 실행할지 지정해 JavaScript 대상을 구성해요:
kotlin {
js().browser { // or js().nodejs
/* ... */
}
}
WebAssembly를 대상으로 할 때
여러 플랫폼에서 로직과 UI를 모두 공유하고 싶다면 Kotlin/Wasm을 사용하면 좋아요. 자세한 내용은 웹 개발을 참고해주세요.
JavaScript와 마찬가지로 WebAssembly(Wasm)를 대상으로 할 때도 kotlin-multiplatform 플러그인을 사용해요:
plugins {
kotlin("multiplatform") version "2.4.20"
}
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '2.4.20'
}
요구사항에 따라 다음을 대상으로 할 수 있어요:
wasmJs: 브라우저나 Node.js에서 실행하기 위함wasmWasi: WASI(WebAssembly System Interface)를 지원하는 Wasm 환경(Wasmtime, WasmEdge 등)에서 실행하기 위함
웹 브라우저나 Node.js를 위해 wasmJs 대상을 구성해요:
kotlin {
wasmJs {
browser { // or nodejs
/* ... */
}
}
}
WASI 환경을 위해 Node.js 또는 Wasmtime으로 wasmWasi 대상을 구성해요:
kotlin {
wasmWasi {
nodejs { // or wasmtime
/* ... */
}
}
}
웹 대상의 Kotlin과 Java 소스
KGP는 Kotlin 파일에만 동작하므로, (프로젝트에 Java 파일이 있다면) Kotlin과 Java 파일을 분리해 두는 것이 좋아요. 분리해 두지 않는다면 sourceSets{} 블록에서 소스 폴더를 지정해주세요:
kotlin {
sourceSets["main"].apply {
kotlin.srcDir("src/main/myKotlin")
}
}
kotlin {
sourceSets {
main.kotlin.srcDirs += 'src/main/myKotlin'
}
}
KotlinBasePlugin 인터페이스로 구성 액션 트리거하기
어떤 Kotlin Gradle 플러그인(JVM, JS, Multiplatform, Native 등)이든 적용될 때마다 특정 구성 액션을 트리거하려면, 모든 Kotlin 플러그인이 상속하는 KotlinBasePlugin 인터페이스를 사용하면 돼요:
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin
// ...
project.plugins.withType<KotlinBasePlugin>() {
// Configure your action here
}
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin
// ...
project.plugins.withType(KotlinBasePlugin.class) {
// Configure your action here
}
의존성 구성하기
라이브러리에 의존성을 추가하려면 소스셋 DSL의 dependencies{} 블록에서 필요한 타입(예: implementation)의 의존성을 설정하면 돼요.
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.example:my-library:1.0")
}
}
}
kotlin {
sourceSets {
commonMain {
dependencies {
implementation 'com.example:my-library:1.0'
}
}
}
}
최상위 레벨에서 의존성 구성하기
멀티플랫폼 프로젝트에서 최상위 dependencies {} 블록을 사용해 공통 의존성을 구성할 수 있어요. 여기서 선언한 의존성은 commonMain 또는 commonTest 소스셋에 추가된 것처럼 동작해요.
최상위 dependencies {} 블록을 사용하려면 블록 앞에 @OptIn(ExperimentalKotlinGradlePluginApi::class) 어노테이션을 추가해 opt-in하면 돼요:
kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
}
}
kotlin {
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0'
}
}
플랫폼별 의존성은 해당 대상의 sourceSets {} 블록 안에 추가해주세요.
이 기능에 대한 피드백은 YouTrack에서 공유할 수 있어요.
의존성 타입
요구사항에 따라 의존성 타입을 선택하세요.
| Type | Description | When to use |
|---|---|---|
api |
컴파일 시와 런타임에 모두 사용되며 라이브러리 소비자에게 내보내짐. | 어떤 타입이든 api 의존성의 타입이 현재 모듈의 공개 API에서 사용된다면 api 의존성을 사용하세요. |
implementation |
현재 모듈의 컴파일과 런타임에 사용되지만, implementation 의존성을 가진 모듈에 의존하는 다른 모듈의 컴파일에는 노출되지 않음. |
모듈 내부 로직에 필요한 의존성에 사용하세요. 모듈이 게시되지 않는 엔드포인트 애플리케이션이라면 api 대신 implementation 의존성을 사용하세요. |
compileOnly |
현재 모듈의 컴파일에 사용되며 런타임이나 다른 모듈의 컴파일에는 사용할 수 없음. | 런타임에 타사 구현이 제공되는 API에 사용하세요. |
runtimeOnly |
런타임에 사용할 수 있지만 어떤 모듈의 컴파일에도 보이지 않음. |
표준 라이브러리에 대한 의존성
표준 라이브러리(stdlib)에 대한 의존성은 각 소스셋에 자동으로 추가돼요. 사용되는 표준 라이브러리 버전은 Kotlin Gradle 플러그인 버전과 같아요.
플랫폼별 소스셋에는 그에 대응하는 플랫폼별 라이브러리 변형이 사용되고, 나머지에는 공통 표준 라이브러리가 추가돼요. Kotlin Gradle 플러그인은 빌드 스크립트의 compilerOptions.jvmTarget 컴파일러 옵션에 따라 적절한 JVM 표준 라이브러리를 선택해요.
표준 라이브러리 의존성을 명시적으로 선언하면(예를 들어 다른 버전이 필요하다면), Kotlin Gradle 플러그인은 그것을 덮어쓰거나 두 번째 표준 라이브러리를 추가하지 않아요.
표준 라이브러리가 전혀 필요 없다면 gradle.properties 파일에 다음 Gradle 속성을 추가할 수 있어요:
kotlin.stdlib.default.dependency=false
전이 의존성의 버전 정렬
Kotlin 표준 라이브러리 버전 1.9.20부터 Gradle은 표준 라이브러리에 포함된 메타데이터를 사용해 전이 kotlin-stdlib-jdk7과 kotlin-stdlib-jdk8 의존성을 자동으로 정렬해요.
1.8.0–1.9.10 사이의 Kotlin 표준 라이브러리 버전에 의존성을 추가하는 경우(예: implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0")), Kotlin Gradle 플러그인은 이 Kotlin 버전을 전이 kotlin-stdlib-jdk7과 kotlin-stdlib-jdk8 의존성에 사용해요. 이렇게 하면 서로 다른 표준 라이브러리 버전으로 인한 클래스 중복을 피할 수 있어요. kotlin-stdlib-jdk7과 kotlin-stdlib-jdk8을 kotlin-stdlib로 병합하는 것에 대해 더 알아보세요. gradle.properties 파일의 kotlin.stdlib.jdk.variants.version.alignment Gradle 속성으로 이 동작을 비활성화할 수 있어요:
kotlin.stdlib.jdk.variants.version.alignment=false
버전을 정렬하는 다른 방법
- 버전 정렬에 문제가 있다면, Kotlin BOM으로 모든 버전을 정렬할 수 있어요. 빌드 스크립트에서
kotlin-bom에 플랫폼 의존성을 선언해주세요:
implementation(platform("org.jetbrains.kotlin:kotlin-bom:2.4.20"))
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.4.20')
- 표준 라이브러리 버전에 의존성을 추가하지 않았는데, 서로 다른 두 의존성이 각각 다른 구버전 Kotlin 표준 라이브러리를 전이적으로 가져온다면, 이 전이 라이브러리들의
2.4.20버전을 명시적으로 요구할 수 있어요:
dependencies {
constraints {
add("implementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk7") {
version {
require("2.4.20")
}
}
add("implementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk8") {
version {
require("2.4.20")
}
}
}
}
dependencies {
constraints {
add("implementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk7") {
version {
require("2.4.20")
}
}
add("implementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk8") {
version {
require("2.4.20")
}
}
}
}
- Kotlin 표준 라이브러리 버전
2.4.20에 의존성을 추가했는데(implementation("org.jetbrains.kotlin:kotlin-stdlib:2.4.20")), Kotlin Gradle 플러그인의 버전이 (1.8.0보다 오래된) 구버전이라면, 표준 라이브러리 버전에 맞도록 Kotlin Gradle 플러그인을 업데이트해주세요:
plugins {
// replace `<...>` with the plugin name
kotlin("<...>") version "2.4.20"
}
plugins {
// replace `<...>` with the plugin name
id "org.jetbrains.kotlin.<...>" version "2.4.20"
}
1.8.0이전 버전의kotlin-stdlib-jdk7/kotlin-stdlib-jdk8을 사용하고(예:implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:SOME_OLD_KOTLIN_VERSION")), 동시에kotlin-stdlib:1.8+를 전이적으로 가져오는 의존성이 있다면,kotlin-stdlib-jdk<7/8>:SOME_OLD_KOTLIN_VERSION을kotlin-stdlib-jdk*:2.4.20으로 바꾸거나 그 라이브러리에서 전이적kotlin-stdlib:1.8+를 제외하세요:
dependencies {
implementation("com.example:lib:1.0") {
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
}
}
dependencies {
implementation("com.example:lib:1.0") {
exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib"
}
}
테스트 라이브러리에 의존성 설정하기
kotlin.test API는 지원되는 모든 플랫폼에서 Kotlin 프로젝트를 테스트하는 데 사용할 수 있어요. commonTest 소스셋에 kotlin-test 의존성을 추가하면, Gradle 플러그인이 각 테스트 소스셋에 해당하는 테스트 의존성을 추론할 수 있어요.
Kotlin/Native 대상은 추가 테스트 의존성을 요구하지 않으며, kotlin.test API 구현이 내장되어 있어요.
kotlin {
sourceSets {
commonTest.dependencies {
implementation(kotlin("test")) // This brings all the platform dependencies automatically
}
}
}
kotlin {
sourceSets {
commonTest {
dependencies {
implementation kotlin("test") // This brings all the platform dependencies automatically
}
}
}
}
kotlin-test 의존성은 어떤 공유 또는 플랫폼별 소스셋에서도 사용할 수 있어요.
kotlin-test의 JVM 변형
Kotlin/JVM의 경우 Gradle은 기본적으로 JUnit 4를 사용해요. 따라서 kotlin("test") 의존성은 JUnit 4용 변형, 즉 kotlin-test-junit으로 해석돼요.
빌드 스크립트의 테스트 태스크에서 useJUnitPlatform() 또는 useTestNG()를 호출해 JUnit 5나 TestNG를 선택할 수 있어요. 다음 예시는 Kotlin Multiplatform 프로젝트용이에요:
kotlin {
jvm {
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
sourceSets {
commonTest.dependencies {
implementation(kotlin("test"))
}
}
}
kotlin {
jvm {
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
sourceSets {
commonTest {
dependencies {
implementation kotlin("test")
}
}
}
}
다음 예시는 JVM 프로젝트용이에요:
dependencies {
testImplementation(kotlin("test"))
}
tasks {
test {
useTestNG()
}
}
dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-test'
}
test {
useTestNG()
}
JVM에서 JUnit을 사용해 코드 테스트하는 방법을 알아보세요.
자동 JVM 변형 해석은 때때로 여러분의 구성에 문제를 일으킬 수 있어요. 그런 경우 필수 프레임워크를 명시적으로 지정하고 프로젝트 gradle.properties 파일에 다음 줄을 추가해 자동 해석을 비활성화할 수 있어요:
kotlin.test.infer.jvm.variant=false
빌드 스크립트에서 kotlin("test")의 변형을 명시적으로 사용했는데 호환성 충돌로 프로젝트 빌드가 멈췄다면, Compatibility guide의 이 이슈를 참고하세요.
kotlinx 라이브러리에 의존성 설정하기
멀티플랫폼 라이브러리를 사용하고 공유 코드에 의존해야 한다면, 공유 소스셋에서 한 번만 의존성을 설정하면 돼요. kotlinx-coroutines-core 또는 ktor-client-core 같은 라이브러리의 기본 아티팩트 이름을 사용해요:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
}
}
}
kotlin {
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0'
}
}
}
}
플랫폼별 의존성에 kotlinx 라이브러리가 필요하다면, 해당 플랫폼 소스셋에서도 라이브러리의 기본 아티팩트 이름을 사용할 수 있어요:
kotlin {
sourceSets {
jvmMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
}
}
}
kotlin {
sourceSets {
jvmMain {
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0'
}
}
}
}
리포지토리 선언하기
공개 리포지토리를 선언해 그 오픈소스 의존성을 사용할 수 있어요. repositories{} 블록에서 리포지토리 이름을 설정해주세요:
repositories {
mavenCentral()
}
repositories {
mavenCentral()
}
인기 있는 리포지토리로는 Maven Central과 Google의 Maven 리포지토리가 있어요.
같은 리포지토리를 둘 이상의 서브프로젝트에서 선언해야 한다면, settings.gradle(.kts) 파일의 dependencyResolutionManagement{} 블록에서 리포지토리를 중앙에 선언해주세요:
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
서브프로젝트에 선언된 리포지토리는 중앙에 선언된 리포지토리를 덮어써요. 이 동작을 제어하는 방법과 사용 가능한 옵션에 대한 자세한 내용은 Gradle 문서를 참고하세요.
생성된 소스 등록하기
생성된 소스를 등록하면 IDE, 서드파티 플러그인, 기타 도구가 생성된 코드와 일반 소스 파일을 구분할 수 있어요. 이렇게 하면 IDE 같은 도구가 UI에서 생성된 코드를 다르게 강조 표시하고, 프로젝트를 import할 때 생성 태스크를 트리거할 수 있어요. 생성된 소스를 등록하려면 KotlinSourceSet 인터페이스를 사용해요.
Kotlin 파일이 들어 있는 디렉터리를 등록하려면 build.gradle.kts 파일에서 SourceDirectorySet 타입의 generatedKotlin 속성을 사용해요. 예를 들어:
val generatorTask = project.tasks.register("generator") {
val outputDirectory = project.layout.projectDirectory.dir("src/main/kotlinGen")
outputs.dir(outputDirectory)
doLast {
outputDirectory.file("generated.kt").asFile.writeText(
// language=kotlin
"""
fun printHello() {
println("hello")
}
""".trimIndent()
)
}
}
kotlin.sourceSets.getByName("main").generatedKotlin.srcDir(generatorTask)
이 예시는 출력 디렉터리가 "src/main/kotlinGen"인 새 태스크 generator를 만들어요. 태스크가 실행되면 doLast {} 태스크 액션이 출력 디렉터리에 generated.kt 파일을 만들어요. 마지막으로 이 예시는 태스크의 출력을 생성된 소스로 등록해요.
Gradle 플러그인을 개발하고 있다면 allKotlinSources 속성을 사용해 KotlinSourceSet.kotlin과 KotlinSourceSet.generatedKotlin 속성에 등록된 모든 소스에 접근할 수 있어요.
다음 단계는?
더 알아보기:
- Compiler options and how to pass them.
- Incremental compilation, caches support, build reports, and the Kotlin daemon.
- Gradle basics and specifics.
- Support for Gradle plugin variants.