본문 바로가기

Android/Tech

Kapt, 그리고 KSP

Unsplash, Mauricio Santos.

GDG Korea 슬랙 채널에서 Dagger 가 KSP 를 지원한다는 소식을 보았고, Kapt 와 KSP 에 대해 제대로 알아보고 정리하고 싶어 포스팅합니다.

 


Kapt

Kapt(Kotlin Annotation Processing Tool) 은 어노테이션 프로세싱을 지원하기 위한 Kotlin Compiler Plugin 이며, Java 의 apt(Annotation Processing Tool) 과 유사한 기능을 제공합니다. Kotlin 1.0.5 까지는 Annotation Processing 을 위해 apt 를 사용하였으나, Kotlin 이 널리 사용되기 시작하면서 그다음 버전인 Kotlin 1.0.6 부터는 Kapt 가 제공되었습니다.

 

특징

  • 호환성
    • Kapt 는 apt 와 호환 가능합니다. 그러므로, 큰 불편 없이 apt 에서 Kapt 로 마이그레이션이 가능합니다.
  • 성능
    • Kapt 는 증분 컴파일(Parallel build) 을 지원하여 빌드 성능을 향상합니다.
  • 정확성
    • Kapt 는 Kotlin 기반 소스 코드에 적합하도록 설계되었기 때문에, apt 보다 더 정확한 Kotlin 코드를 Generate 할 수 있습니다.

증분 빌드(Parallel build)

Kapt 와 apt 의 가장 큰 차이점이 아닐까 싶은데요. 증분 빌드는 추가된 부분에 대해서만 빌드하는 기능입니다. 기존에 빌드했던 부분에 대해서는 별도로 추가의 빌드가 진행되지 않으므로 성능상 이점을 가질 수 있는 것이고요.

 

GlideModule 이나 Hilt 의 경우 Annotation 이 굉장히 많음을 확인할 수 있습니다. 특히 Hilt 쪽은 사용할 때에도 끊임없이 Annotation 을 작성해줘야 하므로, Hilt 가 Kapt 를 지원하는 것은 어쩌면 당연한 일일 수도 있겠네요.

 

 

그림으로 간단히 표현해 봤습니다. Kapt 를 이용하는 Annotation Processing 은 새롭게 추가된 부분에 대해서만 추가 빌드를 수행하므로, 기존의 apt 빌드보다 훨씬 빠르게 빌드가 가능한 것입니다.

 

빌드에 걸리는 시간을 테스트하고 싶은데, 제가 사용하고 있는 Hilt 버전(2.44)에서는 Kapt 가 없으면 애초에 빌드가 되지 않도록 막아두어서 그러질 못하네요. 아쉽습니다.

 

증분 빌드 외에도, 별도의 추가 개발이나 개선이 없는 경우, 특정 코드 작성을 통하여 영구적으로 빌드 성능을 개선시킬 수 있습니다. 소스 파일 전체에 변경이 없거나, Annotation 쪽은 건드리지 않고 함수 본문만 변경된 경우에 해당합니다. 다음 주소는 관련 내용입니다.

 

 

kapt compiler plugin | Kotlin

 

kotlinlang.org

In Android

kapt "com.google.dagger:hilt-android-compiler:${hilt_version}"
kapt "com.github.bumptech.glide:compiler:${glide_version}"

 

Kapt 의존성이 필요한 라이브러리로는 유명한 DI 라이브러리인 Dagger-Hilt 와 이미지 처리 라이브러리인 Glide 정도가 생각이 납니다. 아마 이 외에도 여럿 있을 것 같습니다. 특히 Hilt 에는 꼭 필요한데요. Hilt 를 프로젝트에 적용할 때마다 Kapt 관련 의존성을 빠뜨려서 빌드 실패를 겪게 되는 경우가 몇 번 있었습니다만, 이젠 Kapt 가 어떤 역할을 수행하는지 알았으니, 다시는 빠트릴 일은 없을 것 같습니다.

 


KSP(Kotlin Symbol Processing)

KSP 는 코틀린에서 보다 경량화된 Compiler Plugin 개발을 위한 API 입니다. KSP 로 구현된 Compiler Plugin 은 코틀린의 기능을 더욱 잘 활용할 수 있다고 합니다. KSP 를 활용하여 개발된 Annotation Processor 는 기존 Kapt 대비 최대 두 배 정도 더 빠르게 빌드를 수행할 수 있다고 합니다. 

 

 

kapt에서 KSP로 이전  |  Android 개발자  |  Android Developers

주석 프로세서의 사용을 kapt에서 KSP로 이전합니다.

developer.android.com

 

안드로이드 공식 문서에는 다소 간략하게 작성되어 있습니다. KSP 를 왜 사용하여야 하는지 알기 위해 Kotlin 공식 문서 중 KSP 페이지를 방문해 봤습니다.

 

왜 KSP 를 사용해야 하는가?

1. 사용하기 쉽다.

사실 저와 같은 주니어 레벨 개발자들에게 Compiler Plugin 을 개발하는 것은 평범한 아이디어일 수 없을 겁니다. 그럼에도 불구하고, 언젠가 필요에 의해 사용하게 될 수도 있겠지요.

어찌 되었든, KSP 는 사용하기 쉽다고 합니다. 컴파일러 변경 사항을 숨기고, 이를 사용하는 프로세서의 유지 및 관리  노력을 최소하도록 설계 되었습니다. 또한, 향후 다른 플랫폼과의 호환을 위해 JVM 과의 연관성도 대폭 줄였다고 하네요!

 

2. 학습 곡선이 낮다.

Kotlin Compiler Plugin 을 개발하려면 kotlinc 에 대한 이해와 지식이 필요한데요, KSP 는 그렇지 않다고 합니다. 잘 정의된 API 를 통해 대부분의 컴파일러 변경 사항을 숨기는 것을 목표로 하여 개발되었습니다. (꼭 필요한 경우를 제외하고)

발군의 성능을 보이는 것은 맞지만, 성능에만 집착한 것은 아닙니다. 단순성을 위해 성능에 대한 욕심을 조금은 내려놓았다고 합니다.

 

3. Kapt 와 비교

Kapt 는 Kotlin 코드를 Java Annotation Processor 가 참조하고자 하는 정보들을 유지하는 Java 스텁으로 컴파일합니다. 이 스텁들을 생성하는데에 빌드 총 소요 시간의 약 1/3을 사용한다고 합니다.(사실 Kapt 도 빠른 편이긴 합니다) KSP 로 전환하면 컴파일러에서 소요되는 시간을 즉시 25% 정도 축소시킬 수 있다고 합니다.

 

단순화된 Glide 버전을 구현하여 직접 테스트한 결과도 포함되어 있는데, Kotlin 컴파일 시간은 21.55초, Kapt 는 8.67초, KSP는 1.15초가 걸렸다고 작성되어 있습니다.

 

다음은 위 내용의 원문이 작성되어 있는 Kotlin 공식 문서입니다.

 

 

Why KSP | Kotlin

 

kotlinlang.org

 


 

Room, Glide 등과 같이 익숙한 라이브러리들은 이미 KSP 를 지원하고 있다고 하니, 빌드 속도 개선에 관심이 많으신 분들께서는 사용해보시는 것을 추천드립니다. 저는 Hilt 에 대한 지원이 정식 릴리즈 된다면 바로 사용해 볼 생각입니다.