한 번 작성하고 더 빠르게 배포하세요: Kotlin Multiplatform으로 iOS와 Android 로직 통합하기
Sharing business logic between iOS and Android using Kotlin Multiplatform

한 번 작성하고 더 빠르게 배포하세요: Kotlin Multiplatform으로 iOS와 Android 로직 통합하기

Advertisement

Here is a high-quality blog post written for My Core Pick.


한 번 작성하고 더 빠르게 배포하기: Kotlin Multiplatform으로 iOS와 Android 로직 통합하기

모바일 개발 프로세스에 근본적인 문제가 있다는 것을 깨달았던 날이 기억납니다.

결제 흐름(checkout flow)에 버그가 있었습니다.

Android 팀이 화요일에 고쳤습니다.

iOS 팀이 목요일에 정확히 똑같은 버그를 고쳤습니다.

우리는 두 개의 다른 팀에 같은 로직을 작성하고, 같은 규칙을 검증하고, 같은 JSON 응답을 파싱하도록 비용을 지불하고 있었습니다.

비효율적으로 느껴졌는데, 실제로 그랬기 때문입니다.

수년 동안 업계의 해결책은 Flutter나 React Native 같은 "크로스 플랫폼" 프레임워크였습니다.

하지만 이는 종종 네이티브 사용자 인터페이스(UI)를 희생하거나 속도를 저하시키는 성능 브리지(bridge)를 다루는 것을 의미했습니다.

그때 Kotlin Multiplatform(KMP)이 등장했습니다.

KMP는 다른 약속을 했습니다. 로직은 공유하고, UI는 네이티브로 유지하라는 것이었죠.

오늘 저는 KMP가 왜 현대 모바일 아키텍처를 위한 저의 Core Pick인지, 그리고 어떻게 코드를 한 번만 작성하여 그 어느 때보다 빠르게 배포할 수 있는지 설명해 드리겠습니다.

"한 번 작성하면 어디서든 실행된다(Write Once, Run Everywhere)"의 문제점

Image

오랫동안 모바일 개발의 성배는 어디서나 실행되는 단일 코드베이스였습니다.

React Native나 Flutter 같은 프레임워크는 자체 UI를 렌더링하여 이를 해결하려고 합니다.

기본적으로 "네이티브 iOS 및 Android 버튼은 무시하고 우리 버튼을 사용하세요"라고 말하는 셈입니다.

이는 많은 앱에서 잘 작동합니다.

하지만 때로는 약간 이질감이 느껴집니다.

애니메이션이 딱 들어맞지 않거나, 프레임워크가 아직 지원하지 않는 새로운 iOS 기능이 출시되기도 합니다.

저는 사용자 경험(UX)에 있어서는 항상 순수주의자였습니다.

저는 제 iOS 앱이 SwiftUI나 UIKit을 사용하여 100% iOS 앱처럼 느껴지길 원합니다.

제 Android 앱은 Jetpack Compose를 사용하여 100% Android 앱처럼 느껴지길 원합니다.

하지만 데이터 유효성 검사 로직을 두 번 작성하고 싶지는 않습니다.

네트워킹 계층을 두 번 작성하고 싶지도 않습니다.

여기서 Kotlin Multiplatform이 판도를 바꿉니다.

이것은 "한 번 작성하면 어디서든 실행되는" 솔루션이 되려고 하지 않습니다.

이것은 "로직을 한 번 작성하면 어디서든 실행되는(Write Logic Once, Run Everywhere)" 솔루션입니다.

KMP의 실제 작동 방식 (내부 구조)

Image

KMP를 처음 접하신다면, 아키텍처가 다소 마법처럼 보일 수 있습니다.

하지만 실제로는 매우 표준적인 프로그래밍 개념에 기반을 두고 있습니다.

KMP 프로젝트에는 공유 모듈(Shared Module)이 있습니다.

이 모듈에는 순수 Kotlin 코드가 포함됩니다.

여기에 여러분의 "비즈니스 로직"을 넣습니다.

비즈니스 로직이란 무엇인가요?

비즈니스 로직이라고 하면 애플리케이션의 두뇌를 의미합니다.

여기에는 백엔드로 API 호출을 수행하는 것이 포함됩니다.

로컬 데이터베이스에 데이터를 캐싱하는 것도 포함됩니다.

사용자 입력 유효성 검사(예: 이메일 주소가 유효한지 확인)도 포함됩니다.

앱에서 사용할 수 있는 객체로 JSON 데이터를 파싱하는 것도 포함됩니다.

컴파일러의 마법

프로젝트를 컴파일할 때 KMP는 기발한 작업을 수행합니다.

Android 앱의 경우, 평소처럼 Kotlin 코드를 Java 바이트코드로 컴파일합니다.

하지만 iOS 앱의 경우, 동일한 Kotlin 코드를 Apple 프레임워크로(LLVM을 사용하여) 컴파일합니다.

Xcode 입장에서 공유된 Kotlin 코드는 그저 Objective-C 또는 Swift 프레임워크처럼 보입니다.

여러분은 그것을 임포트(import)하고 함수를 호출합니다.

iOS 개발자는 이를 사용하기 위해 Kotlin을 작성하는 법을 알 필요조차 없습니다.

그저 fetchUser()라는 함수를 보고 호출하기만 하면 됩니다.

비밀 무기: Expect와 Actual

Image

KMP의 가장 강력한 기능 중 하나는 expectactual 메커니즘입니다.

때로는 공유 코드에서 플랫폼별 API에 액세스해야 할 때가 있습니다.

예를 들어, UUID를 생성해야 한다고 가정해 봅시다.

Android는 이를 iOS와 다르게 처리합니다.

공유 코드에서 expect 함수를 정의할 수 있습니다.

다음과 같이 생겼습니다: expect fun randomUUID(): String

이는 기본적으로 "문자열을 반환하는 함수가 있을 것이라고 예상(expect)하지만, 어떻게 작동하는지는 아직 모른다"라고 말하는 것입니다.

그런 다음 Android 소스 세트 내부에 Java 라이브러리를 사용하여 actual 구현을 작성합니다.

iOS 소스 세트 내부에는 Apple의 Foundation 라이브러리를 사용하여 actual 구현을 작성합니다.

이를 통해 필요할 때마다 네이티브 기능을 활용하면서도 상위 수준의 로직을 공유할 수 있습니다.

이는 다른 크로스 플랫폼 프레임워크가 종종 가지고 있는 "블랙박스" 제약을 제거합니다.

My Core Pick: KMP 기술 스택

KMP에 뛰어들기로 결정했다면 올바른 라이브러리가 필요합니다.

Retrofit이나 Room은 Android 전용 Java 라이브러리이므로 사용할 수 없습니다.

멀티플랫폼 호환 라이브러리가 필요합니다.

견고한 KMP 애플리케이션을 위한 "My Core Pick" 스택은 다음과 같습니다.

네트워킹: Ktor

Ktor는 마이크로서비스 및 웹 애플리케이션 생성을 위한 비동기 프레임워크지만, 훌륭한 HTTP 클라이언트를 생성합니다.

JetBrains(Kotlin 창시자)가 만들었으며 완벽하게 멀티플랫폼을 지원합니다.

iOS와 Android 전반에 걸쳐 헤더, 인증, 직렬화를 매끄럽게 처리합니다.

데이터베이스: SQLDelight

제가 가장 좋아하는 데이터베이스 도구입니다.

SQLDelight는 SQL 문에서 타입 안전한 Kotlin API를 생성합니다.

컴파일 중에 스키마를 검증합니다.

SQL 쿼리에 오타를 내면 코드가 컴파일되지 않습니다.

Android와 iOS 모두에서 SQLite로 실행되어 데이터 계층을 매우 견고하게 만듭니다.

의존성 주입: Koin

멀티플랫폼 환경에서 의존성 주입은 까다로울 수 있습니다.

Koin은 KMP와 아주 잘 어울리는 경량 주입 프레임워크입니다.

읽기 쉬운 특정 DSL(Domain Specific Language)을 사용합니다.

데이터베이스와 네트워크 클라이언트를 공유 ViewModel에 직접 주입할 수 있습니다.

동시성: Kotlin Coroutines

iOS와 Android에서 스레딩을 다루는 것은 콜백과 델리게이트의 악몽이었습니다.

Kotlin Coroutines를 사용하면 비동기 코드를 마치 동기 코드처럼 작성할 수 있습니다.

복잡한 백그라운드 작업을 백그라운드 스레드에서 실행하고 UI를 차단하지 않고 결과를 메인 스레드로 반환할 수 있습니다.

결정적으로, 이는 Swift의 async/await 패턴과 상호 운용되므로 iOS 개발자가 자연스럽게 사용할 수 있습니다.

팀을 위한 실제적인 이점

왜 회사에서 이것을 적극 지지해야 할까요?

속도, 일관성, 그리고 정신 건강의 세 가지로 요약됩니다.

1. 반복(Iteration) 속도

새로운 기능을 추가할 때 로직을 한 번 작성합니다.

단위 테스트를 한 번 작성합니다.

UI만 두 번 빌드하면 됩니다.

이로 인해 개발 시간이 크게 단축되며, 팀이 익숙해지면 보통 30~40% 정도 단축됩니다.

2. 일관성이 핵심이다

앞서 버그 수정을 언급했습니다.

KMP를 사용하면 공유 모듈에서 로직 버그를 수정할 때 두 플랫폼 모두에 대해 즉시 수정하게 됩니다.

iOS 앱과 Android 앱이 정확히 같은 방식으로 동작하도록 보장합니다.

가격을 같은 방식으로 계산할 것입니다.

목록을 같은 방식으로 정렬할 것입니다.

이는 QA 팀의 인지 부하를 크게 줄여줍니다.

3. 개발자의 정신 건강

Android 개발자들은 이미 Kotlin을 좋아합니다.

현대적이고 표현력이 풍부하며 안전한 언어입니다.

솔직히 iOS 개발자들은 Swift를 떠나는 것을 주저하곤 합니다.

하지만 KMP는 UI를 SwiftUI에 맡기기 때문에, iOS 개발자들은 통제권을 잃는다고 느끼지 않습니다.

그들은 여전히 아름다운 네이티브 인터페이스를 구축할 수 있습니다.

단지 JSON 파싱을 위한 지루한 상용구(boilerplate) 코드를 더 이상 작성할 필요가 없을 뿐입니다.

시작하기: 도입 전략

그렇다면 어떻게 시작해야 할까요?

내일 당장 전체 앱을 다시 작성하지 마세요.

그것은 재앙으로 가는 지름길입니다.

KMP는 점진적으로 도입하도록 설계되었습니다.

작고 격리된 모듈부터 시작하세요.

분석 로직일 수도 있습니다.

"뉴스 피드" 같은 간단한 기능일 수도 있습니다.

1단계: 설정

JetBrains에서 제공하는 Kotlin Multiplatform Wizard를 사용하세요.

폴더 구조와 Gradle 구성을 생성해 줍니다.

몇 시간의 구성 관련 골치 아픈 일을 덜어줍니다.

2단계: 모델 이동

데이터 모델(기본 클래스)을 공유 모듈로 이동하는 것으로 시작하세요.

이렇게 하면 두 앱이 같은 언어를 사용하게 됩니다.

3단계: 네트워킹 이동

모델이 공유되면 API 호출을 이동하세요.

공유 모듈에서 Retrofit(Android)과 Alamofire(iOS)를 Ktor로 교체하세요.

데이터를 네이티브 UI 계층으로 다시 전달하세요.

맺음말

모바일 개발 환경이 변화하고 있습니다.

우리는 iOS와 Android가 완전히 다른 세계인 고립된 접근 방식에서 벗어나고 있습니다.

또한 웹 기반 크로스 플랫폼 도구라는 "타협"을 지나치고 있습니다.

Kotlin Multiplatform은 그 접점(sweet spot)을 정확히 공략합니다.

중요한 부분(UI)에서는 플랫폼의 차이를 존중합니다.

필요한 부분(로직)에서는 유사성을 통합합니다.

더 빠르게 배포하고, 버그를 줄이고, 네이티브의 룩앤필을 유지하고 싶다면 KMP가 나아갈 길입니다.

이는 확실히 제 개발자 도구 상자 속의 Core Pick입니다.

다음 기능에 한번 시도해 보세요. 장담하건대, 다시는 같은 코드를 두 번 작성하고 싶지 않으실 겁니다.

🔥 Share this Insight

𝕏 Post
Sharing business logic between iOS and Android using Kotlin Multiplatform

한 번 작성하고 더 빠르게 배포하세요: Kotlin Multiplatform으로 iOS와 Android 로직 통합하기

Here is a high-quality blog post written for **My Core Pick**. *** # 한 번 작성하고 더 빠르게 배포하기: Kotlin M...

My Core Pick.
mycorepick.com

Advertisement

Back to Posts