$30 off During Our Annual Pro Sale. View Details »

GDG DevFest2022 Songdo - KMM(Kotlin Multiplatform Mobile)

TaeHwan
November 19, 2022

GDG DevFest2022 Songdo - KMM(Kotlin Multiplatform Mobile)

내용에 포함된 링크
- Get started with Kotlin Multiplatform Mobile
https://kotlinlang.org/docs/multiplatform-mobile-getting-started.html
- Getting started with Kotlin Multiplatform Mobile | KMM Beta
https://www.youtube.com/watch?v=2yd6rVJdICU
- Making Your Android Application Work on iOS | Kotlin Multiplatform Mobile Beta
https://www.youtube.com/watch?v=CIZU_NNAZsA
- Sharing Data Layer Between Android and iOS | Kotlin Multiplatform Mobile Beta
https://www.youtube.com/watch?v=J3hDZ7PTBSk
- Kotlin Multiplatform Mobile을 활용한 데마에칸 드라이버앱 개발 이야기
https://deview.kr/data/deview/session/attach/6_Kotlin%20Multiplatform%20Mobile%EC%9D%84%20%ED%99%9C%EC%9A%A9%ED%95%9C%20%EB%8D%B0%EB%A7%88%EC%97%90%EC%B9%B8%20%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84%EC%95%B1%20%EA%B0%9C%EB%B0%9C%20%EC%9D%B4%EC%95%BC%EA%B8%B0.pdf

TaeHwan

November 19, 2022
Tweet

More Decks by TaeHwan

Other Decks in Programming

Transcript

  1. KMM? Kotlin Multiplatform Mobile Taehwan Lemontree Android GDG Korea Android

    Organizer
  2. 오늘의 발표는 = 결론부터 = KMM 소개를 해보고 = KMM

    설계가 중요한데 뭘 말할지 모르지만 오늘 KMM 사용에 대한 결론부터 정리하였고, KMM 소개와 설계에 대한 언급 정도를 진행합니다.
  3. 시작하기 전에 = 오늘 내용은 입문을 위한 내용 = 설계를

    어떻게 할지 = 제가 사용해 본 적은 없어요 하지만 전 아직 KMM을 써본 적이 없고, 써보자고 검토하지 않았어요. Android/iOS에서 적용하는 아키텍처가 상당히 차이가 크고, 이런 아키텍처는 데이터까지도 영향을 미칩니다. 만약 적용한다면 Data Layer 정도 만 적용할 것 같아요.
  4. Preview Preview라고 이름 짓고 결론부터

  5. 결론부터 = KMM을 잘 적용하려면 모듈화 필수! = 기존에 사용하던

    아키텍처의 공통화 필수 = 가능하다면 서버 개발자까지 포함한 데이터 모듈 개발 = 아직 UI는 하지 못해 완전한 통합은 어려워 = 어디까지 공통 개발할지 설계 필수 = 설득은 선택이 아닌 필수, 하지만 혼자서 하면 문제 X 결론은 KMM을 잘 적용하려면 모듈화가 필수입니다. 이미 생성되어 있는 프로젝트 자체가 모듈화되어있습니다 . 그래서 스파게티 안만들려면 모듈화를 잘 이해하고 설계하고 접근해야 합니다. 기존 프로젝트에 적용하려면 최소한의 아키텍처 공통화도 필수이고, 서버 개발자도 함께 하는 게 좋습니다. 데이터 레이어의 경우는 서버가 가장 잘 알죠. 아직 UI를 제공하지 않아서 완전하지 않아요. 단, 추후에 포함된다고 합니다. 당연히 어디까지 포함할지도 정해야 합니다. 데이터만 할지 비즈니스 로직까지 포함할지, 설득도 필요합니다. 이 발표에는 설득은 없습니다.
  6. 항상 하는 고민? = Android/iOS 하나로 개발하려면? 대표님이라면 고민할 거예요.

    Android/iOS 하나로 개발할 수 없을까? (비용 절감?) 개인적인 생각으론 하나로 개발은 할 수 있지만 플랫폼을 둘 다 이해를 잘해야 합니다.
  7. 멀티 플랫폼 개발을 선택하는 이유는?(유병욱 님 도움으로 정리) • 플로터,

    리엑트 네이티브 선택 ◦ 플로터를 선택한다면 전부다 새로 학습해야 하니 오히려 접근이 쉬울 수 있다 • 플로터의 장점 ◦ 빠른 UI 구축 ◦ 하나의 소스로 여러 플랫폼에 적용 가능 • 플로터의 단점 ◦ 공통으로 가능하지만 각각 플랫폼 이해도가 필요 ◦ 상태 관리와 같은 하나의 통일된 방법이 없다 ◦ Dart 언어의 생소함 플로터 개발자 유병욱 님의 도움으로 정리하였는데요. KMM에서의 내용과 상당히 유사한 부분이 많습니다. 이미 안드로이드 개발은 Compose를 활용합니다. 플로터도 선언형 UI를 작성하죠. 하나의 소스로 여러 플랫폼 역시 코틀린에서 가능합니다. 단점은 역시나 플랫폼 이해도가 필요합니다. KMM은 UI를 다 각각 플랫폼이 그려야 하기에 더 높은 이해도를 필요로 합니다. 그 외 다트라는 언어. 개인적으론 Java처럼 생겨서 너무 싫어합니다.
  8. KMM? 그럼 본론인 KMM

  9. Kotlin Multiplatform Mobile KMM은 Kotlin Multiplatform Mobile의 약자를 줄여서 KMM이라고

    합니다.
  10. 2020년 공개한 이후로 Beta 버전이 출시되었고, 아마도 내년쯤 정식 버전이

    배포 예정이라고합니다. 이 때 UI 까지 포함될 거라고 합니다. 그때쯤 되어야 활용도가 높지 않을까 생각됩니다. 다만 신규로 하는 프로젝트를 기존 안드로이드 개발자가 진행한다면 좋겠지만, iOS 개발자들은 선호하지 않을 수 있겠죠.
  11. KMM? • KMM Beta까지 오면서 ◦ 메모리 관리와 라이브러리 활용에

    대한 다양한 시도 ▪ Philips, Netflix, Baidu, VMWaer와 같은 회사에서 활용 중 • KMM Beta에서 제공하는 부분은? ◦ 공통 데이터 관리 가능 ◦ 공통 비즈니스 로직 관리 가능 KMM Beta까지 오기에 2년이 걸렸는데요. 메모리 관리나 라이브러리 및 프로젝트 구성에 대한 다양한 접근을 시도했다고 합하는데, 넷플릭스 바이두와 같은 회사들이 활용 중이라고 합니다. Beta 이긴 하지만 기존 익히 알려진 KMM 사용 가능 부분과 큰 차이는 없습니다. 공통 데이터 관리와 공통 비즈니스 로직 관리입니다. 아무래도 아직 KMM으로 완전한 플랫폼 하나를 만들기는 어려울 것 같습니다.
  12. KMM? • 현재 버전에서는 UI 공통화는 제공하지 않음 ◦ Android

    compose ◦ iOS SwiftUI ◦ feature에 포함. 기다려보자 그래도 추후에 UI를 포함할 예정이라고 합니다. 현재는 공통 코드 이후 Android는 xml 또는 compose로 구성하고, iOS는 SwiftUI를 활용할 수 있습니다.
  13. KMM? 그래서 소개하는 영상에서도 핵심은 Android/iOS의 코드 공유

  14. KMM? Common 코드가 제공되고, 이를 Android, iOS에서 활용합니다. 그리고 빌드

    결과물은 Android Build Tools를 활용하여 .dex로 뽑아주고, iOS는 LLVM을 활용해서 결과물을 만들어줍니다. 안드로이드는 KMM에서 사용할 수 있는 새로운 라이브러리와 모듈 분리 필요하고, 나머진 기존과 동일합니다. Common에서는 각각 플랫폼에 접근할 수 있는 라이브러리도 제공합니다.
  15. > Android/iOS에서 같은 로직 작업. 하지만 서로 다른 결과물을 보았다면?

    < KMM을 선택한다? 안드로이드/Kotlin 서버 개발자에겐 좋은 소식 아마 매우 많은 경험을 해보았을 건데 동일한 로직을 가지는 Android/iOS 개발에서 간혹 오류코드가 다르다는 이슈를 보셨을 겁니다. 누구는 서버에서 내려주는 코드로 최신화 시키고, 누구는 로컬에서 발생하는 오류를 그대로 두고 하는? 이런 공통적인 오류 처리 또는 공통적인 복잡한 산술연산에 대한 처리 등을 통합하여 관리할 수 있습니다. 사실 이것만으로도 KMM의 가치는 충분하다고 봅니다. 다만 iOS 개발자 입장에서는 귀찮은 부분이 생깁니다. 안드로이드 스튜디오로 개발해야 할 수도 있고요.
  16. KMM 학습 KMM 학습을 위한 내용을 소개합니다.

  17. KMM 입문 자료들 • KMM Guide ◦ Get started with

    Kotlin Multiplatform Mobile
  18. KMM 입문 자료들 • Youtube 영상 ◦ Getting started with

    Kotlin Multiplatform Mobile | KMM Beta ◦ Making Your Android Application Work on iOS | Kotlin Multiplatform Mobile Beta ◦ Sharing Data Layer Between Android and iOS | Kotlin Multiplatform Mobile Beta
  19. KMM 입문 자료들 • 네이버 데뷰 발표 내용 ◦ Kotlin

    Multiplatform Mobile을 활용한 데마에칸 드라이버앱 개발 이야기
  20. KMM 적용 KMM을 적용하려면 알아야 할 내용보단 설득하고, 어디까지 적용할지

    정리해야 합니다.
  21. KMM 적용 • UI를 제외한 Kotlin 코드를 기반한 Data logic,

    Business logic 공통화 가능 UI를 제외한 부분을 Data logic, Business logic을 통해 공통화 시키게 됩니다. 이때 플랫폼 별로 제공하는 코드도 common 모듈에서 처리합니다. 그리고 Android/iOS에서는 이를 가져다 쓰는 형태로 활용합니다. 앞에 소개 드린 네이버 데뷰 발표 자료를 참고하시면 동기화에 대한 이슈 트래킹 내용을 참고하실 수 있습니다.
  22. • Android 개발자 입장 ◦ 내가 원래 쓰던 코드를 그대로

    활용할 수 있다. ◦ 모듈 형태의 개발은 선택이 아닌 필수 조건(KMM 모듈) • iOS 개발자 입장 ◦ 굳이 코틀린을 학습해야 할까? ◦ 우리가 이미 적용해 쓰던 아키텍처가 있는데 이를 변경해야 하나? KMM을 활용한다면? 각자의 입장이 다 다를 수 있으니 대략 적어보면 Android 입장에서는 매우 좋습니다. 내가 원래 쓰던 코드 그대로 활용하고, 모듈 형태로의 접근, 안드로이드 스튜디오도 그대로 활용합니다. 그래서 바로 KMM을 도입하고 적용할 수 있습니다. iOS 개발자 입장에서는 코틀린을 학습해야 하고, 우리가 이미 적용한 아키텍처를 새로 또 변경해야 할 수 있습니다. 이 부분을 타협해야겠죠.
  23. • Android 개발자 입장 ◦ 모듈 형태를 잘 설계하고 이해하고

    있다면 바로 대응 가능 • iOS 개발자 입장 ◦ Android 개발자가 다 해주면 해볼 수 있다? • 또 다른 선택지 ◦ 어차피 새로 한다면 둘 다 모르는 플로터를 선택하는 것도 하나의 방법 ◦ 가장 좋은 방법은 공통 모듈을 만드는 별도의 팀 운영(현실적으로 가능할까?) 타협한다면? 그래도 타협해서 공통화의 이점을 적용해 본다면 안드로이드는 바로 적용하고 대응도 가능합니다. iOS 개발자 입장에서는 안드로이드 개발자를 따라가 보는 것이겠죠. 또 다른 선택지도 생각해 봅니다. 그럴 거면 플로터를 해볼까? 현재는 UI가 없자나? 아니면 UI 없으니 별도로 팀을 운영해 보자?
  24. • 공통화를 한다면 ◦ 어디까지 공통으로 할 것인가? ▪ 모델?

    ▪ 비즈니스? ▪ UI는?(추후 지원 예정) 어디까지 공통화할 것인가? 그럼 어디까지 공통화할 수 있을지를 고민해야 합니다. 앞으로 UI까지 나오면? 사실 이 고민은 안드로이드 개발자에게만 이점이 생길 수 있습니다.
  25. 정리하면 • 공통 로직을 누가 관리할 것인가? ◦ 안드로이드 개발자가

    우선 작업 후 공유가 현실적(네트워크, 비즈니스로직 등) • 서버 개발자가 해준다? ◦ 데이터 통신에 대한 처리를 서버 개발자가 처리해 준다? • 그래도 숙련도에 따라 혼자서 데이터 레이어부터 뷰 레이어까지 한 명이 작업하는 것이 가장 정리를 해보죠. 결국 현실적으론 안드로이드 개발자가 먼저 사전 진행하는 게 좋고, 가능하다면 서버 개발자도 함께 참여해 주는 게 좋습니다. 데이터 레이어에 대한 이해도는 서버 개발자와도 함께 협업할 수 있으니깐요. 그렇다고 하더라도 숙련도가 높으면 그냥 혼자서 뷰부터 데이터 레이어까지 모두 작업하는 게 빠릅니다. 보통 큰 로직이 없으니깐요. 데이터를 받아오고 쓰는 네트워크 레벨이 오히려 공통화 작업이 더 필요하기도 합니다.
  26. 서로 어긋나는 예외 처리와 데이터를 하나로 관리할 수 있다. 최소한의

    예외 처리를 하나로 통일할 수 있다는 관점만 있어도 적용해 볼 순 있습니다.
  27. KMM 어떻게 활용할까? 앞에서 얼마나 적용해 볼 것인가를 이야기했으니, 좀

    더 구체적으로 나열하면
  28. = 네트워크 통신 후 오류 처리 = 데이터 모듈(Data Layer)

    = 비즈니스 로직(View Logic) = 개인적으로 KMM은 설계를 잘 해야 한다고 생각 네트워크 통신 후 오류 처리 데이터 모듈 비즈니스 로직 그리고 이걸 잘하기 위한 설계가 필요합니다.
  29. 네트워크 통신 후 오류 처리 • 네트워크를 통한 데이터 처리를

    공통화 ◦ 공통 암호화 처리 ◦ 토큰에 대한 공통 처리 ◦ 오류에 대한 공통 처리 네트워크 통신 후 오류 처리는 중요한 부분이고, 공통화되어 있을 때 업무 효율이 증대될 수 있습니다. 공통 암호화 처리도 중요하고, 토큰 처리도, 오류에 대한 공통 처리 역시 중요합니다. 아무래도 이런 부분은 서버 입장에서도 Android 한번 iOS 한번 2번씩 대응이 필요한데 이를 공통화 시킬 수 있다면 한번 만 대응하고, 최신화도 빠르게 진행할 수 있습니다.
  30. 데이터 모듈(Data Layer) • Data layer에 대한 공통 처리 ◦

    Json 데이터를 공통으로 처리하고, 이를 Android/iOS에서 활용 가능하도록 개발 데이터 모듈이 가장 쉬운 접근입니다. Json으로 받아온 데이터를 파싱 하는 부분을 포함할 수 있는데, 이건 네트워크 쪽과 연결돼야 합니다. 그래서 둘 다 이루어지면 좋죠.
  31. 비즈니스 로직(View Logic) • ViewModel ◦ Data layer의 Repository를 활용한

    데이터 처리 ◦ View에 전달할 수 있는 형태로 개발(하지만 MVVM 형태로의 콜백이 다름) ◦ 비즈니스 로직까지 만 포함하고, 이를 매핑하는 class는 각자가 다시 추가 필요 비즈니스 로직은 선택입니다. 아무래도 View에 화면을 어떤 식으로 그려줄지, 데이터를 어떤 도구로 던져줄지가 Android/iOS가 매우 다를 겁니다. 이 부분을 하나로 처리하기란 어렵겠죠. 그래서 적용한 다고 하면 로직적인 부분만을 공통으로 처리하고(복잡한 계산, 실수를 유발하는 부분) 나머진 각자가 처리하는 것입니다. 매핑 클래스가 생기는 거라서 고민은 좀 더 필요합니다.
  32. 설계 설계라고 이름을 써두었지만 이미 많이 알고 있는 설계 방식을

    소개합니다.
  33. Android Guide app architecture • Data Layer이 1차적인 목표 •

    Domain Layer 선택 • UI Layer의 ViewModel의 공통 비즈니스 로직 처리 • 추후 UI까지 점령 안드로이드에서 가장 많이 사용하는 아키텍처입니다. 여기에서 목표를 정한다면 Data Layer을 우선 공통화시키고 비즈니스 로직을 처리할 수 있습니다. 아무래도 모듈로 분리 안 되어있다면 이런 코드를 분리하는 작업부터 시작해야 합니다.
  34. 모듈 단위로의 개발 • Android module 개발 - Now in

    android 참고 - Speaker Deck ◦ Android 모듈 개발은 Now in android를 참고 ◦ settings.gradle ▪ include(":core:model") ▪ include(":core:network") ▪ include(":feature:author") ▪ include(":feature:foryou") 그래서 선택할 수 있는 게 모듈입니다. 이미 모듈로 나누어져 있다면 이 모듈만 KMM으로 이동시키고 일부 대응만 하시면 됩니다. 아무래도 서로 다른 플랫폼 특성상 맞지 않을 부분들이 있는데 network와 이에 대한 모듈 등을 이동시키고 작업할 수 있을 것 같습니다. 모듈 단위로 코드를 개발하는 것은 서로 디펜던시의 연결고리를 느슨하게 하는 장점이 있습니다. 다만 DI를 적용하고 싶을 것인데 이 부분은 KMM에서 지원하는지 모르겠군요.
  35. KMM 모듈 단위에서 확장 가능 • KMM도 모듈 단위로의 설명

    KMM이 기본적으로 제공하는 모듈 형태를 보면 shared module로 분리되어 있습니다. 이 말은 기존 안드로이드 작업에서 module로 잘 분리되어 있다면 그대로 활용이 가능하다는 이야기입니다. 상황에 맞게 android/iOS 플랫폼 코드의 활용도 가능합니다.
  36. 정리하면 • 모듈 단위의 아키텍처 설계가 필요 • KMM에서 어디까지

    플랫폼 활용할 것인지 정해야 하고 • KMM을 어디까지 공유할 것인지도 정해야 함 정리하면 모듈 단위는 필수로 보입니다. DI를 활용하지 못하더라도 모듈 단위를 잘 분리해두면 KMM으로의 이동이 쉽습니다. 그리고 공통의 코드를 얼마나 분리하고 활용할 것인지도 고민이 필요합니다. 단순히 복잡한 로직에 대한 계산 코드를 KMM으로 활용할 수 있도록 한다? 도 역시 매우 좋은 선택지로 보입니다.
  37. 샘플 실행 샘플 코드를 살펴보겠습니다.

  38. Android Studio 활용 • iOS 개발을 해야 해서 Mac에서 진행해야

    함 • Android studio, Xcode, Kotlin Multiplatform Mobile plugin 필요 안드로이드 스튜디오를 활용하고, 안드로이드 스튜디오에서 플러그인을 설치해 주시면 활용 가능합니다. iOS 개발을 해야 해서 mac에서 활용됩니다.
  39. 새로운 프로젝트 생성 • Kotlin Multiplatform App • Kotlin Multiplatform

    Library 새로운 프로젝트 생성 시 2개의 옵션이 추가됨을 알 수 있습니다. Kotlin Multiplatform App과 Library입니다. 여기서는 앱을 선택하고 진행합니다.
  40. KMM을 위한 설정 추가 정의 안드로이드 설정이 끝나면 KMM 설정을

    할 수 있는데, android 기본 모듈 명과 iOS 기본 모듈 명을 지정하고, 공통 코드 모듈 명도 지정합니다. 그리고 마지막으로 iOS에서 활용할 framework을 지정해 줍니다. 여기서는 Regular framework을 선택합니다.
  41. KMM 프로젝트 • androidApp : android 앱 관련 모듈 •

    iosApp : Xcode에서 정상으로 보이고, iOS 앱 관련 폴더 • shared : Kotlin 기반의 코드로 KMM 공유 모듈 ◦ commonMain : 두 main에 대한 정의 ▪ 공용 코드 또는 interface ◦ androidMain : 안드로이드 플랫폼 접근 ▪ 안드로이드 플랫폼 접근이 필요한 경우 상속 구현체 ◦ iosMain : iOS 플랫폼 접근 ▪ iOS 플랫폼 접근이 필요한 경우에 대한 상속 구현체 KMM 프로젝트가 만들어지면 오른쪽과 같이 Project에서 모든 코드를 살펴볼 수 있습니다. 크게 andoridApp 모듈, iOSApp 모듈, Shared를 확인할 수 있습니다. Shared 폴더 안에는 다시 플랫폼을 활용할 수 있는 androidMain, iosMain 폴더로 나뉘고, commonMain으로 나뉘게 됩니다. 안드로이드 개발자 입장에선 디펜던시 하나 더 추가되었다고 생각하시면 됩니다.
  42. commonMain - Platform.kt interface Platform { val name: String }

    expect fun getPlatform(): Platform 먼저 commonMain 코드를 살펴보면 interface로 정의한 Platform이 보입니다. 이 코드는 각 플랫폼의 현재 버전 정보를 가져와 노출합니다. 당연히 android는 android 버전이, iOS는 iOS 버전이 노출되어야 합니다. 그래서 기본 샘플에서는 각 플랫폼을 이용하는 코드를 살펴볼 수 있습니다.
  43. androidMain - Platform.kt class AndroidPlatform : Platform { override val

    name: String = "Android ${android.os.Build.VERSION. SDK_INT}" } actual fun getPlatform(): Platform = AndroidPlatform() androidMain에는 안드로이드 플랫폼에 접근할 수 있는데 여기서는 andorid.os에 접근할 수 있습니다. Android sdk에 접근하여 sdk 버전 정보를 가져옵니다. 그리고 getPlatform() 함수를 여기서 구현해 줍니다.
  44. iosMain - Platform.kt import platform.UIKit.UIDevice class IOSPlatform: Platform { override

    val name: String = UIDevice. currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } actual fun getPlatform(): Platform = IOSPlatform() iosMain에서는 iOS 시스템에 접근하고, 버전 정보를 불러옵니다. 여기서도 동일하게 getPlatform을 구현합니다.
  45. expect와 actual expect fun getPlatform(): Platform actual fun getPlatform(): Platform

    = AndroidPlatform() actual fun getPlatform(): Platform = IOSPlatform() 참고 MM에서 제공하는 expect, actual expect : 추상 함수를 구현 actual : 추상 함수에 대한 정의 앞에서 함수를 구현한다고 표현했는데, expect라는 키워드와 actual이라는 키워드가 있습니다. 추상 형태도 아닌데 정의만 하고, 구현을 한 다라? 이 2개의 키워드를 통해 정의만하고, 구현할 수 있게 KMM에서 제공하고 있습니다. expect를 함수를 표현하고, actual 키워드를 붙여 함수를 정의했음을 알려주면 됩니다.
  46. commonMain - Greeting.kt class Greeting { private val platform: Platform

    = getPlatform() fun greeting(): String { return "Hello, ${platform.name}!" } } Greeting 클래스에서는 앞에 정의한 interface와 각 플랫폼에 맞는 정보를 불러와 String을 리턴하게 됩니다.
  47. 각 플랫폼에서는 Android : Greeting(Greeting().greeting()) iOS : let greet =

    Greeting().greeting() 그리고 각 플랫폼에서는 클래스 접근하듯 값을 가져와 화면에 노출하게 됩니다. 이때 UI는 Android compose, iOS는 SwiftUI를 활용합니다.
  48. 결론? 결론은 이미 다 말했지만

  49. 결론 • 새로운 도전 • 모든 팀이 함께 공통화 작업이

    가능해야 함 ◦ 현실적으로 그런 팀을 운영할 회사가 몇 있을까? • 혼자서 도전한다면 매우 유용 ◦ 당분간은 대응이 힘들겠지만 UI까지 동작한다면? • UI까지 만들어진다고 해도 플랫폼에 대한 이해도 필요 ◦ Android/iOS 플랫폼 이해도 필요 • KMM을 지금 당장 쓴다면 데이터 레이어에만 활용할 듯 • 그리고 하자고 한 사람이 마무리해야 한다. KMM을 적용하는 것 역시 새로운 도전입니다. 모든 팀이 함께 공통화 작업을 통해 운영되어야 이상적이겠죠. 혼자서 도전한다면 매우 유용할 것 같습니다. 현재는 SwiftUI까지 작업해야겠지만 추후에는 하나만 하면 모든 게 끝날 거니깐요. 그렇다고 플랫폼까지 이해하지 않을 순 없지만요. 당장 KMM을 적용한다면 공통 코드에서 자주 수정되어야 하거나 실수가 빈번한 코드부터 이동시켜보는 것도 좋을 것 같습니다.
  50. End e-mail : taehwan@thdev.net Blog : https://thdev.tech Github : https://github.com/taehwandev