코틀린 2.0, 무엇이 변했을까?
최근 코틀린을 다룰 일이 없다가 스프링이란 것을 공부해보면서 뭐가 변했는지 알고가면 좋을 것 같아 코틀린 독스를 펼쳤다.
Docs - Whats new in Kotlin 2.0.0를 바탕으로 요약을 해보는 글을 적어보려한다.
솔직히 내용중에 알빠노싶은것도 많은데(어차피 쓰다보면 굳이 이것까지 알 필요없고 자연스레 이제 이런것도 되네 싶은 것들이나 사소한 개선들), 그래도 새 출발하는 마음으로 정리해보자.
결론부터 말하자면 그냥 코틀린을 쓰던 사람들이 특별히 따로 배워야할 문법은 없다고 봐도 무방하다.
주로 JVM과 K2에 대해서만 좀 다루었으므로 자세한 모든 사항은 위 링크를 참조하자.
Kotlin / JVM
Kotlin 2부터 Java 22를 타겟으로 하는 .class
파일을 생성할 수 있게 되었다.
Generation of lambda functions using invokedynamic
invokedynamic
이란 친구를 통해 람다 함수를 생성해내는 방식을 default로 변경했다고 한다.
이는 이전의 익명 클래스를 생성하는 방식보다 바이너리 크기를 감소시키며 효율적이라고 한다.
invokedynamic
은 JVM optimizations를 통해 추후 JVM의 개선으로 더 성능적으로 개선될 여지가 있는 방식이라고 한다.
현재는 세 가지 한계가 있다.
- 이것으로 만들어진 람다는 직렬화되지 못한다.
- 현재 실험적 API인 reflect()는 이것으로 만들어진 람다를 지원하지 않는다. (이 함수는 함수의 런타임 reflection을 도와주는 함수임)
- 람다에 대한
.toString()
의 가독성이 나쁠 수 있다.
특정 람다에 대해서 이전 구현을 유지하려면 @JvmSerializableLambda
를 람다에 붙이거나 컴파일러 옵션에 -Xlambdas=class
를 선언하여 전체 프로젝트에서 invokedynamic
을 비활성화시킬 수 있다고 한다.
The kotlinx-metadata-jvm-library is Stable
kotlin-metadata-jvm
란 이름으로 kotlinx
-> kotlin
으로 변경되었으며 이제부터 Kotlin의 release cycle에 따른다고 한다.
이는 Kotlin/JVM 컴파일러로 생성된 바이너리 파일의 메타데이터를 읽거나 수정하는 패키지라고 한다.
Kotlin K2 컴파일러
코틀린의 새로운 컴파일러 K2가 안정화되어 출시되었다고 한다. 코틀린 2부턴 기본적으로 이 컴파일러를 쓰며 성능도 좋고 특히 KMP에서 쩐다고한다.
참 코틀린의 변화를 지켜보면, Jetbrains는 일을 굉장히 잘하는것같다.
K2 Migration Guide도 마련되어있다.
특히 아키텍쳐에 대해서 강조하는데,
- call resolution 및 type inference 개선
- 새로운 기능 도입에 대한 손쉬운 sugaring
- 빠른 컴파일
- IDE에서도 굳굳
등이 있다고 한다.
Smart cast improvements
난 지금까지도 코틀린이 굉장히 똑똑한 언어라고 생각했는데 더 똑똑해진것같다.
대략 다음과 같이 자동 형변환이 개선되었다고 한다.
이 내용들은 정리는 해놨지만 자세히 몰라도 된다. 그냥 IDE와 컴파일러를 믿고 더 편해졌네 정도를 직접 코딩하면서 느낄 수 있으면 된다.
Local variables and further scopes
대략 이런 느낌으로 if
밖에 선언된 변수의 타입 추론의 결과도 더 똑똑하게 추론해준다는 의미같다.
fun petAnimal(animal: Any) {
val isCat = animal is Cat
if (isCat) {
// In Kotlin 2.0.0, the compiler can access
// information about isCat, so it knows that
// animal was smart-cast to the type Cat.
// Therefore, the purr() function can be called.
// In Kotlin 1.9.20, the compiler doesn't know
// about the smart cast, so calling the purr()
// function triggers an error.
animal.purr()
}
}
Type checks with logical or operator
||
연산자에서 타입을 체크하는 is
가 여러개 있을 때 if
문 을 통과한다면 Lower Common Ancestor 타입으로 형변환이 된다고 한다.
원래는 Any
로 되었다고 한다.
fun signalCheck(signalStatus: Any) {
if (signalStatus is Postponed || signalStatus is Declined) {
// signalStatus is smart-cast to a common supertype Status
signalStatus.signal()
// Prior to Kotlin 2.0.0, signalStatus is smart cast
// to type Any, so calling the signal() function triggered an
// Unresolved reference error. The signal() function can only
// be called successfully after another type check:
// check(signalStatus is Status)
// signalStatus.signal()
}
}
Inline functions
인라인 함수는 이제 callsInPlace
로 취급되어 인라인 함수의 람다 인자가 항상 호출 시점에 불릴 것이므로(non-escaping) 참조누수가 없다는 것을 컴파일러가 인지할 수 있게 되었다.
따라서 이 정보를 바탕으로 컴파일러는 인라인 함수의 람다 인자 내부에서 다른 변수가 누수되지 않음을 알기 때문에 쓸데없는 옵셔널 체이닝이 줄어들게 되었다.
interface Processor {
fun process()
}
inline fun inlineAction(f: () -> Unit) = f()
fun nextProcessor(): Processor? = null
fun runProcessor(): Processor? {
var processor: Processor? = null
inlineAction {
// In Kotlin 2.0.0, the compiler knows that processor
// is a local variable, and inlineAction() is an inline function, so
// references to processor can't be leaked. Therefore, it's safe
// to smart-cast processor.
// If processor isn't null, processor is smart-cast
if (processor != null) {
// The compiler knows that processor isn't null, so no safe call
// is needed
processor.process()
// In Kotlin 1.9.20, you have to perform a safe call:
// processor?.process()
}
processor = nextProcessor()
}
return processor
}
properties with function types
코틀린 2 전에는 class의 properties가 함수 타입이면 smart-cast가 되지 않던 버그가 있었는데 고쳐졌다고 한다.
Exception handling
smart cast의 정보가 catch
, finally
에도 잘 전달이 된다고 한다.
Increment and decrement operators
++
나 --
연산자 이후 객체의 타입이 변환될 수 있음을 컴파일러가 이해할 수 없었으나 이제 가능하다.
Kotlin Multiplatform Improvements
난 솔직히 KMP에 대해서 잘 모르고 써본적도 없다. 주로 안드로이드 개발을 위해 JVM에서의 코틀린을 사용해보았을 뿐이라서 해당 내용은 스킵한다.
IDE에서 K2를 활성화하는 법
다음과 같이 활성화할 수 있다.
In your IDE, go to Settings | Languages & Frameworks | Kotlin and select the Enable K2 mode option. The IDE will analyze your code using its K2 mode. |
Comments