K2 컴파일러가 Kotlin 2.0에 들어왔어요

kotlin 2.0에 추가된 새로운 기능과 다양한 개선 사항을 확인해 보세요!

작성일 2023년 03월 06일

안녕하세요, IMQA 노성현입니다.
kotlin을 개발하고 있는 JetBrain 블로그에 따르면 K2 컴파일러가 Kotlin 2.0에 공식적으로 포함되었다고 합니다.

K2 컴파일러는 JetBrains에서 개발한 Kotlin 프로그래밍 언어의 공식 컴파일러입니다. Kotlin은 자바 가상 머신(JVM) 상에서 실행되는 오픈 소스 프로그래밍 언어로, 안드로이드 앱 개발뿐만 아니라 서버 개발까지 다양한 분야에서 사용되고 있습니다.

K2 컴파일러는 Kotlin 코드를 바이트 코드로 변환하여 JVM에서 실행 가능한 형태로 만들어줍니다. 이를 통해 Kotlin으로 작성된 프로그램을 다양한 플랫폼에서 실행할 수 있으며, 또한 자바와의 상호 운용성을 보장합니다.

참고 영상

최근에는 Kotlin 2.0 버전이 출시되었습니다. 이 버전에서는 다양한 기능 개선과 새로운 기능이 추가되었는데요. 타입 추론 기능이 개선되어 더욱 정확하고 안전한 타입 추론이 가능해졌고, 코루틴(coroutine) 기능이 개선되어 더욱 간편하고 유연한 비동기 프로그래밍이 가능해졌습니다.

또한, 새로운 플랫폼인 Kotlin/Native가 추가되었는데요. Kotlin/Native는 네이티브 코드로 컴파일되어 실행되는 Kotlin 애플리케이션을 개발할 수 있게 해줍니다. 이를 통해 모바일 기기나 임베디드 시스템 등에서 Kotlin으로 개발된 애플리케이션을 실행할 수 있게 됩니다.

그리고 Kotlin 2.0에서는 더욱 강력한 라이브러리가 지원됩니다. 예를 들어, kapt(Kotlin 어노테이션 프로세서)와 함께 사용할 수 있는 Dagger 2와 같은 의존성 주입 프레임워크를 사용하여 쉽게 객체 간 의존성을 관리할 수 있습니다. 또한 Jetpack Compose와 같은 새로운 UI 프레임워크를 사용하여 더욱 직관적이고 간편한 UI를 구성할 수 있습니다.

다음은 Dagger 2와 kapt를 사용하여 의존성 주입을 처리하는 코드의 예시입니다.

@Module
class MyModule {
    @Provides
    fun provideUserService(apiService: ApiService): UserService {
        return UserServiceImpl(apiService)
    }
    
    @Provides
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
    
    @Provides
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("<https://example.com>")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}

@Component(modules = [MyModule::class])
interface MyComponent {
    fun inject(activity: MyActivity)
}

위의 코드에서 MyModule 클래스는 객체를 제공하는 메서드를 가지고 있는 모듈 클래스입니다. @Provides 어노테이션을 사용하여 객체를 제공하는 메서드를 정의하고, 필요한 객체 간 의존성을 주입합니다.

MyComponent 인터페이스는 의존성 주입을 처리하는 컴포넌트 인터페이스입니다. @Component 어노테이션을 사용하여 컴포넌트를 정의하고 모듈 클래스를 포함시킵니다.

class MyActivity : AppCompatActivity() {
    @Inject
    lateinit var userService: UserService
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val component = DaggerMyComponent.create()
        component.inject(this)
        
        // userService를 사용하여 작업을 수행합니다.
        // ...
    }
}

MyActivity 클래스에서 userService 필드에 @Inject 어노테이션을 사용하여 의존성 주입을 처리합니다. onCreate 메서드에서 DaggerMyComponent.create() 메서드를 사용하여 컴포넌트를 생성하고, component.inject(this) 메서드를 사용하여 의존성 주입을 수행합니다.

위의 코드에서는 MyModule 클래스에서 RetrofitApiService 객체를 생성하여 UserService 객체를 만들어 반환하고 있습니다. 이렇게 만든 UserService 객체는 MyActivity 클래스에서 필드 주입을 통해 사용할 수 있습니다.

위와 같이 Dagger 2를 사용하여 객체 간 의존성을 관리할 수 있으며 이를 통해 코드를 더욱 유연하게 구성할 수 있습니다.

Kotlin 2.0은 이전 버전보다 더욱 강력하고 다양한 기능을 제공하여 더욱 빠르고 안전한 개발을 가능하게 합니다. 예를 들어 Kotlin 2.0에서는 함수형 프로그래밍을 보다 쉽게 할 수 있도록 람다 식과 확장 함수 기능이 개선되었습니다. 또한 inline 함수와 reified 타입 파라미터 기능이 추가되어 런타임에서의 타입 안정성을 보장하면서도 성능을 향상시킬 수 있게 되었습니다.

예를 들어 아래와 같이 applyIf라는 inline 함수를 만들어 볼 수 있습니다.

inline fun <T> T.applyIf(condition: Boolean, block: T.() -> Unit): T {
    return if (condition) {
        this.apply(block)
    } else {
        this
    }
}

위의 코드에서 applyIf 함수는 conditiontrue일 경우 block 함수를 호출하여 this 객체에 대한 작업을 수행한 후 반환합니다. conditionfalse인 경우 this 객체를 그대로 반환합니다. 이렇게 만든 applyIf 함수는 inline 함수로 정의되어 있기 때문에 함수 호출 시 인라인(복사 및 붙여넣기) 되어 실행됩니다.

또한, reified 타입 파라미터 기능을 사용하면 함수에서 제네릭 타입 파라미터에 대한 런타임 정보를 쉽게 얻을 수 있습니다. reified 타입 파라미터는 함수의 타입 파라미터 앞에 reified 키워드를 붙여서 사용할 수 있으며 이를 통해 함수에서 타입 파라미터에 대한 런타임 정보를 쉽게 얻을 수 있습니다.

예를 들어 아래와 같이 find라는 inline 함수를 만들어 볼 수 있습니다.

inline fun <reified T> Iterable<*>.findInstance(): T? {
    return this.firstOrNull { it is T } as T?
}

위의 코드에서 findInstance함수는 Iterable 객체에서 T 타입에 해당하는 첫 번째 객체를 반환합니다. T 타입 파라미터 앞에 reified 키워드가 붙어있기 때문에 함수 내부에서 T 타입에 대한 런타임 정보를 쉽게 얻을 수 있습니다.

Kotlin 2.0에서는 안드로이드 앱 개발에 적합한 새로운 라이브러리인 Android KTX가 추가되었습니다. Android KTX는 Kotlin에서 안드로이드 개발을 더욱 쉽고 간편하게 만들어주는 라이브러리로, 뷰(View)나 쉐어드 프리퍼런스(Shared Preferences)와 같은 안드로이드 API를 사용할 때 불필요한 코드를 줄여주어 개발 생산성을 향상시킵니다.

// 기존 코드
val textView = findViewById<TextView>(R.id.text_view)
textView.text = "Hello, World!"

// KTX 라이브러리를 사용한 코드
text_view.text = "Hello, World!"

// 기존 코드
val sharedPreferences = getSharedPreferences("my_preferences", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putString("name", "John")
editor.putInt("age", 30)
editor.apply()

// KTX 라이브러리를 사용한 코드
val sharedPreferences = getPreferences()
sharedPreferences.edit {
    putString("name", "John")
    putInt("age", 30)
}

또한, Kotlin 2.0에서는 Kotlin DSL(Domain Specific Language)을 개발하는 데 유용한 라이브러리인 Kotlinx.serialization이 추가되었습니다. 이 라이브러리를 사용하면 JSON과 같은 데이터 포맷을 쉽게 다룰 수 있으며 빠르고 안전한 직렬화/역 직렬화를 가능하게 합니다.

Kotlinx.serialization을 사용하려면 먼저 Gradle 파일에 아래와 같은 의존성을 추가해야 합니다.

implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0"

JSON 형식으로 직렬화하려면 Json 객체를 생성하여 사용하면 됩니다.

import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class User(val name: String, val age: Int)

fun main() {
    val user = User("Alice", 25)
    val json = Json.encodeToString(user)
    println(json)
}

JSON 형식으로 역 직렬화하려면 Json 객체를 생성하여 사용하면 됩니다.

fun main() {
    val json = """{"name":"Alice","age":25}"""
    val user = Json.decodeFromString<User>(json)
    println(user)
}

마지막으로 Kotlin 2.0은 Kotlin 커뮤니티의 참여를 촉진하기 위해 더욱 개방적인 방향으로 발전하고 있습니다. 이를 통해 더욱 다양한 아이디어와 기술이 Kotlin 생태계에 기여될 것으로 기대됩니다.

Kotlin 2.0의 등장으로 Kotlin은 더욱 강력하고 안정적인 프로그래밍 언어로 자리 잡았습니다. Kotlin은 자바와의 상호 운용성, 함수형 프로그래밍 지원, 높은 생산성, 안드로이드 개발 등 다양한 이유로 많은 개발자들에게 인기 있는 언어가 되었습니다. 앞으로도 Kotlin은 계속해서 발전하며 다양한 분야에서 사용될 것으로 기대됩니다.

참고자료

The K2 Compiler is going stable in Kotlin 2.0 | The Kotlin Blog
We’ve been working on a new frontend for the Kotlin compiler (code-named “K2”) for quite a while. The new frontend is already available for preview – we’re continually polishing and stabilizing it and plan to make it the default compiler frontend in a future Kotlin release. We’ve decided to name thi…
Kotlin roadmap | Kotlin

Share on

Tags

IMQA 뉴스레터 구독하기

국내외 다양한 기술 소식을 선별하여 매월 전달해드립니다. IMQA 뉴스레터를 통해 기술 이야기를 함께해보세요.

구독하기