Kotlin 프로젝트에서 어노테이션 프로세서 사용하기
- 다음의 경우 kapt를 사용하세요:
- Maven 프로젝트를 사용하는 경우.
- Gradle 프로젝트를 사용하지만, 필요한 Java 어노테이션 프로세서가 아직 KSP를 지원하지 않는 경우. 지원되는 라이브러리 목록 보기.
- 다음의 경우 KSP를 사용하세요:
- Gradle 프로젝트를 사용하고, 필요한 Java 어노테이션 프로세서가 KSP를 지원하는 경우.
- 자신만의 어노테이션 프로세서를 만들고 싶은 경우.
어노테이션 프로세서는 컴파일 시점에 소스 코드를 분석하여 보일러플레이트(boilerplate) 코드를 생성하거나, 사용법을 검증하거나, 기타 아티팩트를 생성합니다. Kotlin은 어노테이션 프로세서를 사용하는 두 가지 방법을 지원합니다:
kapt 컴파일러 플러그인은 Kotlin 소스 코드에서 스텁(stub) 파일을 생성한 다음, 해당 스텁에서 Java 어노테이션 프로세서를 실행하는 방식으로 작동합니다. 이 추가적인 스텁 생성 단계로 인해 빌드 시간이 느려지며, kapt가 확장 함수나 널 안전성과 같은 Kotlin 특유의 구조를 이해할 수 없음을 의미합니다.
kapt는 Maven과 Gradle을 모두 지원합니다. 모든 Maven 프로젝트와 MapStruct와 같이 아직 KSP를 채택하지 않은 프로세서 라이브러리를 사용하는 Gradle 프로젝트에 권장됩니다.
KSP 프레임워크는 스텁을 생성하지 않고 Kotlin 우선(Kotlin-first) API를 통해 Kotlin 소스 코드를 직접 읽습니다. Kotlin 고유의 기능을 네이티브하게 이해하며 kapt보다 빌드 속도가 빠릅니다.
현재 KSP는 Gradle에 대해서만 공식 지원을 제공합니다. 자신만의 프로세서를 작성하거나 Dagger와 같이 KSP와 호환되는 라이브러리를 사용하는 경우에 권장됩니다.
Java 어노테이션 프로세서와 함께 kapt 사용하기
kapt를 사용하면 프로세서 자체를 변경하지 않고도 Kotlin 프로젝트에서 기존 Java 어노테이션 프로세서를 사용할 수 있습니다.
아래 예제는 컴파일 시점에 Java 빈(bean) 사이의 타입 안전한 매퍼 구현체를 생성하는 MapStruct 어노테이션 프로세서를 사용하는 방법을 보여줍니다.
빌드 파일에서
kapt플러그인을 적용하고dependencies섹션에 MapStruct를 추가합니다:xml<properties> <kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget> <mapstruct.version>1.6.3</mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${mapstruct.version}</version> </dependency> </dependencies> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <extensions>true</extensions> <executions> <execution> <id>kapt</id> <goals> <goal>kapt</goal> </goals> <configuration> <sourceDirs> <sourceDir>src/main/kotlin</sourceDir> <sourceDir>src/main/java</sourceDir> </sourceDirs> <aptMode>stubs</aptMode> <annotationProcessorPaths> <annotationProcessorPath> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> </annotationProcessorPath> </annotationProcessorPaths> </configuration> </execution> </executions> </plugin>compile실행 전에kotlin-maven-plugin의kapt골(goal) 실행을 추가합니다.aptMode옵션을 사용하여 어노테이션 프로세싱 수준을 구성합니다.
kotlinplugins { kotlin("kapt") version "2.3.0" } dependencies { implementation("org.mapstruct:mapstruct:1.6.3") kapt("org.mapstruct:mapstruct-processor:1.6.3") }groovyplugins { id "org.jetbrains.kotlin.kapt" version "2.3.0" } dependencies { implementation "org.mapstruct:mapstruct:1.6.3" kapt "org.mapstruct:mapstruct-processor:1.6.3" }데이터 클래스와 매퍼 인터페이스를 정의합니다:
kotlinimport org.mapstruct.Mapper import org.mapstruct.factory.Mappers data class UserDto(val id: Long, val firstName: String, val lastName: String) data class UserEntity(val id: Long, val firstName: String, val lastName: String) @Mapper interface UserMapper { fun toDto(entity: UserEntity): UserDto fun toEntity(dto: UserDto): UserEntity companion object : UserMapper by Mappers.getMapper(UserMapper::class.java) }프로젝트를 빌드합니다. MapStruct는 생성된 소스 디렉토리에
UserMapperImpl클래스를 생성합니다.UserMapper컴패니언 객체를 사용하여 생성된 구현체를 호출합니다:kotlinfun main() { val entity = UserEntity(id = 1L, firstName = "John", lastName = "Doe") val dto = UserMapper.toDto(entity) println(dto) // UserDto(id=1, firstName=John, lastName=Doe) }
Gradle 프로젝트에서 KSP 사용하기
KSP를 사용하면 Gradle 프로젝트에서 기존 어노테이션 프로세서를 사용하거나, 소스 코드의 어노테이션을 기반으로 코드를 생성하는 고유한 프로세서를 만들 수 있습니다.
Java 어노테이션 프로세서와 함께 KSP 사용하기
Gradle 프로젝트의 경우, 호환되는 어노테이션 프로세서와 함께 KSP를 사용하세요. KSP는 kapt보다 빠르며 Kotlin 고유의 기능을 네이티브하게 이해할 수 있습니다. 이미 KSP를 지원하는 라이브러리 목록을 확인하세요.
아래 예제는 의존성 그래프를 위한 연결 코드를 생성하는 컴파일 시점 의존성 주입(dependency injection) 프레임워크인 Dagger를 사용하는 방법을 보여줍니다.
build.gradle(.kts)파일에서 KSP 플러그인을 적용하고dependencies블록에 Dagger를 추가합니다:kotlin// build.gradle.kts plugins { kotlin("jvm") version "2.3.0" id("com.google.devtools.ksp") version "2.3.3" } dependencies { implementation("com.google.dagger:dagger:2.59.2") ksp("com.google.dagger:dagger-compiler:2.59.2") }groovy// build.gradle plugins { id 'org.jetbrains.kotlin.jvm' version '2.3.0' id 'com.google.devtools.ksp' version '2.3.3' } dependencies { implementation 'com.google.dagger:dagger:2.59.2' ksp 'com.google.dagger:dagger-compiler:2.59.2' }KSP의 최신 버전을 찾으려면 GitHub Releases 페이지를 확인하세요.
Kotlin 클래스에 Dagger 어노테이션을 추가합니다:
kotlinimport javax.inject.Inject import javax.inject.Singleton import dagger.Component import dagger.Module import dagger.Provides @Singleton class UserRepository @Inject constructor() { fun getUser(): String = "John Doe" } @Module class AppModule { @Provides @Singleton fun provideUserRepository(): UserRepository = UserRepository() } @Singleton @Component(modules = [AppModule::class]) interface AppComponent { fun userRepository(): UserRepository }프로젝트를 빌드합니다. Dagger는
build/generated/ksp디렉토리에DaggerAppComponent와 같은 구현 클래스를 생성합니다. 코드에서 생성된 클래스를 사용합니다:kotlinfun main() { val appComponent = DaggerAppComponent.create() val userRepository = appComponent.userRepository() println("User: ${userRepository.getUser()}") // User: John Doe }
Dagger의 KSP 지원에 대한 자세한 내용은 해당 문서를 참조하세요.
자신만의 어노테이션 프로세서 만들기
KSP API를 사용하여 컴파일 시점에 코드를 생성하는 고유한 어노테이션 프로세서를 작성할 수 있습니다. 새로운 프로세서에는 세 가지 모듈이 필요합니다:
- 커스텀 어노테이션을 선언하는
annotation모듈. SymbolProcessor및SymbolProcessorProvider팩토리를 구현하는processor모듈.SymbolProcessor에는 주요 로직이 포함되며,SymbolProcessorProvider는 프로세서를 생성하고META-INF/services/경로에 프로바이더를 등록합니다.- KSP 플러그인을 적용하고, 프로세서에 의존하며, 어노테이션을 사용하는
app모듈.
단계별 전체 안내는 KSP 퀵스타트를 참조하세요.
