Kotlin Multiplatform Mobile (KMM)으로 본 플랫폼 간 코드 공유

현재 모바일 앱 개발은 주로 안드로이드와 iOS, 두 가지 주요 플랫폼에서 이루어지고 있습니다. 각각의 플랫폼은 고유한 프로그래밍 언어와 개발 도구를 사용하며, 이로 인해 개발자들은 종종 두 플랫폼에 대해 별도의 코드베이스를 유지하게 됩니다. 이는 개발과 유지 관리의 복잡성을 증가시키고, 코드의 재사용성을 제한하며, 일관된 사용자 경험을 제공하는데 어려움을 초래합니다.

하지만 이제 Kotlin Multiplatform Mobile (KMM)이라는 새로운 도구를 통해 이런 문제들을 해결할 수 있게 되었습니다. KMM은 안드로이드와 iOS 플랫폼 간에 공유할 수 있는 공통 로직을 Kotlin으로 작성하게 해줍니다. 이렇게 함으로써, 개발자들은 각 플랫폼의 고유한 기능들을 최대한 활용하면서도, 코드의 재사용성을 향상시키고, 일관된 사용자 경험을 제공할 수 있게 됩니다.

KMM이 주목받는 주된 이유는 개발 효율성과 일관된 사용자 경험 제공 능력 때문입니다. 일반적으로 안드로이드와 iOS 앱은 각각의 개발 환경에서 별도로 개발되어야 합니다. 이렇게 되면 동일한 기능을 가진 앱을 두 플랫폼 모두에 배포하려면 코드를 두 번 작성해야 하는 문제가 발생합니다. 이는 시간과 노력을 많이 소모하며, 불필요한 중복성을 초래합니다.

그러나 KMM을 사용하면 이런 문제를 크게 줄일 수 있습니다. KMM은 공통 로직을 한번에 작성하여 두 플랫폼 모두에 적용할 수 있게 해줍니다. 이는 개발 시간을 크게 줄일 수 있을 뿐만 아니라, 앱의 일관성도 향상시키는 효과가 있습니다. 즉, 두 플랫폼에서 앱의 동작이 동일하게 작동하도록 보장할 수 있습니다.

또한, KMM은 각 플랫폼의 고유한 기능들을 최대한 활용하면서도, 코드의 재사용성을 향상시키는 데 큰 장점이 있습니다. 이는 플랫폼 간에 중복되는 코드를 최소화하고, 개발 효율성을 높이는 데 도움이 됩니다.

KMM은 Kotlin이라는 뛰어난 언어를 기반으로 하며, 안드로이드 개발자들에게 익숙한 언어이기 때문에 쉽게 접근할 수 있습니다. 이러한 이유들로 인해 KMM은 현재 모바일 앱 개발 분야에서 크게 주목받고 있습니다.


KMM의 아키텍처

Kotlin Multiplatform Mobile (KMM)의 구조와 동작 방식은 플랫폼 간 코드 공유를 최적화하기 위해 설계되었습니다. KMM 프로젝트는 크게 두 가지 부분으로 나뉩니다: “공유 코드”와 “플랫폼 별 코드”.

공유 코드는 여러 플랫폼에서 동일하게 동작하는 코드입니다. 이는 플랫폼에 독립적인 비즈니스 로직, 데이터 처리, 네트워크 요청 등에 사용됩니다. 여기에는 플랫폼에 구애받지 않는 Kotlin 표준 라이브러리와 같은 다양한 멀티플랫폼 라이브러리(예: Ktor, kotlinx.serialization 등)를 활용할 수 있습니다.

플랫폼 별 코드는 특정 플랫폼에만 적용되는 코드로, 플랫폼 고유의 기능이나 UI를 처리하는 데 사용됩니다. 각 플랫폼 별 코드는 공유 코드의 동작에 영향을 주지 않으며, 이를 통해 안드로이드와 iOS의 고유한 기능을 최대한 활용할 수 있습니다.

KMM의 중요한 아키텍처 요소는 “Expect/Actual” 패턴입니다. 공유 코드가 특정 플랫폼의 기능이나 API를 사용해야 하는 경우, “Expect” 키워드를 사용하여 해당 기능이나 API를 선언하고, 각 플랫폼의 코드에서는 “Actual” 키워드를 사용하여 실제 구현을 제공합니다. 이 패턴을 통해, 공유 코드는 플랫폼 별 코드에 의존하지 않으면서도 특정 플랫폼의 기능을 활용할 수 있습니다.

이러한 구조와 동작 방식을 통해 KMM은 개발자에게 플랫폼 간 코드 재사용성을 최대화하고, 동시에 각 플랫폼의 고유한 기능을 활용하는 능력을 제공합니다. 이는 개발 효율성을 높이는 데 크게 기여합니다.


KMM 프로젝트 설정

Kotlin Multiplatform Mobile(KMM)은 상당히 간편하게 프로젝트를 설정할 수 있게 해줍니다. 여기서는 KMM 프로젝트의 기본 설정 방법과 간단한 예제를 통해 KMM을 이해하는 방법을 소개하겠습니다.

  1. KMM 프로젝트 설정

먼저, KMM은 IntelliJ IDEA와 Android Studio의 Kotlin 플러그인을 통해 지원됩니다. 이 중 어떤 것을 사용하더라도 KMM 프로젝트를 생성하는 데 문제가 없습니다.

  • IntelliJ IDEA를 사용할 경우:
    File -> New -> Project를 선택하고, ‘Kotlin’을 선택한 다음, ‘Mobile Android/iOS’를 선택합니다.
  • Android Studio를 사용할 경우:
    File -> New -> New Project를 선택하고, ‘KMM Application’을 선택합니다.

위의 단계를 거치면 기본 KMM 프로젝트가 생성됩니다. 이 프로젝트는 ‘shared’라는 공유 모듈과 ‘androidApp’, ‘iosApp’이라는 두 개의 플랫폼 별 모듈로 구성됩니다. 공유 코드는 ‘shared’ 모듈에, 플랫폼 별 코드는 각 플랫폼 모듈에 배치됩니다.

  1. 간단한 예제로 KMM 이해하기

이제 간단한 예제를 통해 KMM의 동작을 이해해 보겠습니다. ‘shared’ 모듈에 다음과 같은 공유 함수를 작성해 봅시다.

expect fun platformName(): String

이 함수는 현재 플랫폼의 이름을 반환하는 함수입니다. 그러나 ‘expect’ 키워드를 사용했기 때문에, 이 함수의 실제 구현은 각 플랫폼 별 코드에서 제공해야 합니다.

다음으로, ‘androidMain’과 ‘iosMain’ 디렉토리에 각각 아래의 ‘actual’ 함수를 구현합니다.

  • Android에서:
actual fun platformName(): String {
    return "Android"
}
  • iOS에서:
actual fun platformName(): String {
    return "iOS"
}

마지막으로, 이 함수를 호출하여 각 플랫폼에서 실행해 봅시다.

  • Android에서:
println("Running on ${platformName()}")
  • iOS에서:
print("Running on \(platformName())")

이렇게 하면 각 플랫폼에서 앱을 실행할 때 “Running on Android”와 “Running on iOS”라는 메시지를 출력하게 됩니다.

이 예제를 통해, KMM을 사용하여 공유 코드를 작성하고, 플랫폼 별 코드를 통해 이를 구체화하는 방법을 간략하게 살펴보았습니다. KMM을 이용하면 이런 식으로 플랫폼 간 코드 재사용성을 높이면서도, 각 플랫폼의 고유한 기능을 활용할 수 있습니다.


실제 앱 예제로 KMM 이해해보기

다음으로, 실제 앱 개발에서 필요한 로직인 데이터 저장, 네트워킹, UI 처리 등을 공유 코드로 어떻게 구현하는지 보여주는 심화 예제를 살펴보겠습니다. 이 예제에서는 간단한 뉴스 앱을 만들어보는 것을 목표로 합니다.

데이터 저장:

이 앱에서는 사용자가 읽은 뉴스 기사의 제목을 로컬에 저장하는 기능을 구현하겠습니다. 이를 위해 Kotlin의 멀티플랫폼 라이브러리 중 하나인 kotlinx.serializationSQLDelight를 사용하겠습니다. kotlinx.serialization은 JSON 직렬화를, SQLDelight은 데이터베이스 작업을 간소화해줍니다.

먼저, 공유 코드에서 데이터 모델을 정의하겠습니다. 이 모델은 @Serializable 어노테이션을 사용하여 직렬화할 수 있도록 합니다.

@Serializable
data class NewsArticle(val title: String, val link: String, val isRead: Boolean)

그 다음, SQLDelight를 사용하여 로컬 데이터베이스에서 뉴스 기사를 저장하고 조회하는 방법을 정의합니다.

네트워킹:

뉴스 기사를 가져오기 위해, 우리는 공유 코드에서 HTTP 요청을 해야 합니다. 이를 위해 Ktor라는 멀티플랫폼 라이브러리를 사용하겠습니다.

Ktor 클라이언트를 사용하여 뉴스 기사를 가져오는 함수를 구현하겠습니다. 이 함수는 공유 코드에서 호출할 수 있습니다.

suspend fun fetchNews(): List<NewsArticle> {
    // Ktor client setup and request
}

UI 처리:

UI 처리는 플랫폼 별 코드에서 수행되어야 합니다. 그러나 공유 코드에서 UI 로직을 정의하는 것이 가능합니다.

예를 들어, 뉴스 기사를 읽은 후 해당 기사를 읽었다고 표시하는 로직을 공유 코드에서 정의할 수 있습니다. 이를 위해, ViewModel에서 isRead 프로퍼티를 업데이트하는 함수를 구현하겠습니다.

fun markAsRead(article: NewsArticle) {
    // Update the 'isRead' property in the database
}

각 플랫폼에서는 이 ViewModel을 사용하여 UI를 업데이트하고 사용자의 액션을 처리합니다. 이 방식을 통해, UI 로직의 일부를 공유 코드에서 처리할 수 있습니다.

이렇게, KMM을 사용하면 실제 앱 개발에 필요한 다양한 로직을 공유 코드로 구현할 수 있습니다. 이를 통해 개발 효율성을 높이고, 코드의 재사용성을 극대화할 수 있습니다.

이번에는 더욱 심화된 예제를 통해 Kotlin Multiplatform Mobile (KMM)를 깊게 이해해보겠습니다. 이번 예제에서는 사용자 인증, 웹소켓 통신, 앱 세팅 등의 기능을 구현하는 실시간 채팅 앱을 만들어 보겠습니다.

사용자 인증:

이 채팅 앱에서는 사용자 인증 기능을 구현해야 합니다. 이를 위해 Firebase Authentication 서비스를 사용하겠습니다. Firebase는 안드로이드와 iOS 모두를 지원하므로, 각 플랫폼에서 Firebase SDK를 설정하고, 공유 코드에서 사용자 인증 API를 호출하도록 하겠습니다.

expect class FirebaseAuthService {
    suspend fun signIn(email: String, password: String): User
    suspend fun signUp(email: String, password: String): User
}

expect 키워드를 사용하여 FirebaseAuthService 클래스를 선언하고, 각 플랫폼에서 actual 키워드를 사용하여 이를 구현합니다. 이 클래스는 사용자 로그인 및 회원가입 기능을 제공합니다.

웹소켓 통신:

웹소켓을 사용하여 실시간 채팅 기능을 구현하겠습니다. 이를 위해 Ktor 라이브러리의 웹소켓 클라이언트를 사용하겠습니다.

expect class WebSocketClient {
    fun connect()
    fun send(message: String)
    fun close()
}

WebSocketClient 클래스는 웹소켓 연결, 메시지 전송, 연결 해제 기능을 제공합니다. 이 클래스도 각 플랫폼에서 actual 키워드를 사용하여 구현합니다.

앱 세팅:

사용자가 앱 세팅을 변경할 수 있도록, 공유 코드에서 앱 세팅을 저장하고 불러오는 기능을 구현하겠습니다. 이를 위해 kotlinx.serializationkotlinx.preferences 라이브러리를 사용하겠습니다.

@Serializable
data class AppSettings(val darkMode: Boolean)

expect class AppSettingsStore {
    fun save(settings: AppSettings)
    fun load(): AppSettings
}

AppSettingsStore 클래스는 앱 세팅을 저장하고 불러오는 기능을 제공합니다. 이 클래스 역시 각 플랫폼에서 actual 키워드를 사용하여 구현합니다.

이처럼, KMM을 사용하면 실제 앱 개발에 필요한 다양한 로직을 공유 코드로 구현할 수 있습니다. 이를 통해 개발 효율성을 높이고, 코드의 재사용성을 극대화할 수 있습니다.


KMM의 장단점

이제 Kotlin Multiplatform Mobile (KMM)의 장단점에 대해 알아보겠습니다.

장점:

  • 코드 재사용: KMM의 가장 큰 장점은 코드 재사용성입니다. 비즈니스 로직, 네트워킹, 데이터 저장 등의 로직을 공유 코드로 작성하면, 이를 안드로이드와 iOS에서 동시에 사용할 수 있습니다. 이로 인해 중복 코드를 줄이고, 개발 시간을 절약할 수 있습니다.
  • 유지 관리 용이성: 코드가 중앙화되어 있으므로, 유지 관리가 더욱 쉽습니다. 공통 로직에 대한 수정이나 개선 사항은 한 곳에서 처리하면 되므로, 코드의 일관성을 유지하는 데에도 유리합니다.
  • 일관된 사용자 경험 제공: 공유 코드를 통해 동일한 비즈니스 로직을 제공함으로써, 사용자에게 일관된 사용자 경험을 제공할 수 있습니다. 이는 브랜드 이미지를 향상시키는 데에도 도움이 됩니다.

단점:

  • 플랫폼 별 코드 작성 필요: UI와 같은 플랫폼 특화적인 부분은 각 플랫폼에서 별도로 작성해야 합니다. 따라서, 완전히 플랫폼 독립적인 개발이 가능한 것은 아닙니다.
  • 초기 학습 곡선: KMM은 새로운 개념을 많이 도입하므로, 초기에는 학습 곡선이 높을 수 있습니다. 특히, expect/actual 메커니즘, 멀티플랫폼 라이브러리 등에 익숙해져야 합니다.

KMM은 이와 같은 장단점을 가지고 있지만, 대체로 장점이 많아 다양한 개발 상황에서 뛰어난 선택지가 될 수 있습니다. 이 기술을 통해 안드로이드와 iOS 앱 개발의 효율성을 크게 향상시킬 수 있습니다.


결론: KMM의 현재 상태와 미래 전망

이제까지 Kotlin Multiplatform Mobile (KMM)의 아키텍처, 설정 방법, 실제 앱 개발 예제, 그리고 장단점에 대해 알아보았습니다. KMM은 현재도 많은 개발자들에게 인기를 끌고 있고, 그 가능성이 널리 인정받고 있는 기술입니다.

KMM을 통해 안드로이드와 iOS 앱의 비즈니스 로직을 공유하면, 중복 코드를 줄이고, 유지 관리를 용이하게 하며, 일관된 사용자 경험을 제공할 수 있습니다. 반면에, UI와 같은 플랫폼 특화적인 부분은 각 플랫폼에서 별도로 작성해야 하고, 초기 학습 곡선이 존재한다는 단점이 있습니다.

하지만, KMM은 계속해서 발전하고 있으며, 이러한 단점들을 극복하기 위한 다양한 노력이 진행되고 있습니다. 예를 들어, Jetpack Compose for Desktop과 SwiftUI를 통해 멀티플랫폼 UI를 구현하는 연구가 진행되고 있습니다. 이러한 발전 속에서 KMM의 가능성은 더욱 크게 될 것으로 보입니다.

그럼에도 불구하고, KMM이 모든 상황에서 최고의 해결책은 아닙니다. 항상 프로젝트의 요구사항, 팀의 기술적 역량, 예산 등을 고려해야 합니다.

이 글을 읽고 KMM에 대한 흥미가 생겼다면, 실제로 한 번 시도해보는 것을 추천합니다. 초기 학습 곡선이 있을 수 있지만, 한 번 익히고 나면 이를 통해 많은 이점을 얻을 수 있습니다. 안드로이드와 iOS 개발을 효율적으로 진행하고자 하는 개발자들에게 KMM은 매우 가치 있는 도구가 될 것입니다.

Leave a Comment