링크드인에 반다라트 앱 부활 관련 글을 작성한지 3개월이라는 시간이 흘렀다.
Android 앱이었던 반다라트를 Compose Muliplatform 으로 Migration 하여 앱스토어에 성공적으로 출시하기까지 과정과 앞으로 해야할 일들에 대해 간략하게 적어보고자 한다.
결론부터 말하자면 예정했던 기간보다 오래걸렸다. 그 이유는 생각보다 시행착오가 많았기 때문이다.
우선 Circuit 을 먼저 적용한 뒤에 Multiplatform 전환을 하려고 했기 때문에, Circuit 학습 및 적용에 대략 2개월정도가 소모되었다.
그런데 이게 왠일, Circuit 이 Koin 을 지원하지 않는 듯 했다.
https://github.com/InsertKoinIO/koin/issues/1869
https://github.com/slackhq/circuit/issues/1392
KMP 환경에서는 Hilt 를 사용할 수 없기 때문에, 대부분의 레퍼런스들이 Koin 을 사용하는데, Koin 을 사용할 수 없다는 것은 치명적인 단점이라고 판단하였다.
kotlin-inject, kotlin-inject-anvil 등의 대안이 있긴하지만, 관련 레퍼런스가 별로 존재하지 않았다.
우선 Android 앱에 Hilt 를 걷어낸 뒤에, Multiplatform 전환을 하려고 했는데, kotlin-inject 와 kotlin-inject-anvil 은 Kotlin Multiplatform 을 위해 설계된 DI 라이브러리들이기 때문에, Android 관련 의존성인 ApplicationContext 를 어떻게 각 component 에 주입 할 수 있는지에 대한 정보를 찾기가 어려웠다. 그립읍니다 Hilt...
그렇게 계속 구르던 중에, Koin 공식문서를 확인하게 되었고, 기존에 Android 에서도 사용했던 DI 라이브러리이기 때문에, Android, KMP, CMP 등 각 프레임워크에 맞춰 문서화가 정말 잘 되어있다는 것을 확인할 수 있었다.
https://insert-koin.io/docs/reference/koin-annotations/start/
뿐만 아니라, 기존의 Koin 은 런타임에 의존성 주입을 했기 때문에, 앱의 성능이나 안정성이 떨어질 수 있었지만, 이제는 컴파일 타임에 의존성을 주입하는 방식을 지원한다는 것도 알게 되었다.
또한 기존의 Koin 의 사용법과 다른 Annotation 방식의 의존성 주입도 지원하기에, Hilt 랑 비슷한 방식으로 의존성 주입이 가능해졌다.
리플렉션을 사용하는 방식도 deprecated 되었다고 한다.
https://insert-koin.io/docs/reference/koin-android/dsl-update/
심지어 이제는 Android 개발만 한다 했을때도, Hilt 보다 Koin 을 사용하는 쪽이 보일러플레이트 코드를 더 줄일 수 있다고 생각한다.
따라서, 기존의 ViewModel + Compose Navigation 을 사용했던 브랜치 버전에 Koin 을 적용하여, 이를 Multiplatform 으로 전환하기로 결정하였다.
ViewModel 과 Compose Navigation 둘다 Multiplatform 을 지원하고, Hilt 를 Koin 으로 전환하는 것은 큰 공수가 들지 않은 편이다.
아... 그건 아니다...
사실 KMP 의 형태로 Migration 하기 위해 Circuit 을 먼저 적용했었다.
내가 생각했던 이상적인 Compose Multiplatform 은 Composable Architecture 을 표방하는 Circuit 을 적용한 형태였기 때문이다.
다만, 아직 Circuit 을 사용할 때 사이드 이펙트(UI 이벤트)를 처리하는 방식에 대한 의문점이 하나 있다.
이에 대한 대안으로 생각했던, 이벤트를 상태로 처리하는 방식은 개인적으로 선호하는 방식이 아니기 때문에, 더 나은 해결책을 계속 찾아보고 있다...답변 주시면 감사하겠습니다...
https://github.com/slackhq/circuit/discussions/1876
몰랐다... 난 왜 이슈랑 공식 문서만 보고 바로 포기했던 것인가...
이후 현재 develop 브랜치의 Circuit 을 적용한 형태의 Android 앱도 Multiplatform 전환을 해봐야겠다.
Koin Annotation 방식으로 migration 만 하고, 나머지는 대응은 이미 해본 경험이 있으니, 오래 걸리지 않을 듯 하다.
자세한 내용은 본문의 블로그 글을 참고하면 좋을 듯 하다.
링크드인 글
[Android] 의존성 주입 - Starting with Koin Annotations(feat. Compose, KMP, Circuit)
과정이 어찌되었든 앱스토어에 출시한게 어디냐!
시행착오들을 통해 조금 더 고민하고, 성장했으면 된거지! 음음,,
DI 라이브러리 관련 문제 해결 이후, KMP(정확히는 CMP) 로 앱을 전환하는 과정에서 겪었던 문제들도 상당히 많은데, 이를 이번 글에서 모두 소개하기엔 너무 길어질 것 같아, KMP 시리즈를 통해 주요 트러블 슈팅 과정들을 공유할 예정이다.
CMP 는 아무래도 KMP 보다 인지도가 낮고, CMP 라고 줄여 말했을 때, Android 개발자라도 아직 잘 모르는 분들이 많았다.
따라서 KMP 시리즈로... 깃허브 레포 네이밍도 Bandalart-Android 에서 Bandalart-KMP 로 변경했다.
그밖에도 Android 앱 배포는 많이 해봤지만, iOS 앱 배포는 처음이었기에, 배포과정에서 어려움이 많았는데, 회사 및 주변 iOS 개발자분들, 오픈 카톡방에 KMP 개발자분들께 도움을 받아 겨우 출시에 성공 할 수 있었다.
글 마지막에 도움을 받은 분들과 많이 참고한 레퍼런스들을 적어두었다. 샤라웃
수 많은 문제들을 해결했지만, 아직 해결하지 못한 문제도 남아있다. 비효율적으로 작성된 코드들도 다수 존재하고...
대표적으로는 In-App Update 가 있는데, iOS 에서는 In-App Update 를 지원하지 않기 때문에, 플랫폼 별로 분기처리를 해주어야한다.
다만 문제는 In-App Update 관련 로직은 기존에 화면 단에서 수행을 해줬기 때문에, 이는 Compose Multiplatform 특성상 commonMain 에 존재한다. 이를 androidMain 으로 끄집어낼 방법을 강구해야봐야겠다.
Android 앱은 현재 12MB 정도인데, iOS 앱은 무려 74MB 이다...! 별 기능도 없는데
그 이유를 추측해보자면, Android 앱의 경우 난독화 및 리소스 Shrink 까지 적용 하여, 어느정도 최적화를 해둔게 있지만, iOS 쪽에서는 최대한 빠른 배포가 우선이었기 때문에 위와 같은 작업을 전혀 해주지 않았다.
다른 앱들을 조사해본 결과 평균적으로 iOS 앱의 용량이 더 큰 편이긴 했다.
iOS 앱도 마찬가지로 난독화 혹은 리소스 Shrink 등, 앱의 용량을 어느정도 낮출 수 있는 방법이 무조건 있을 것이기 때문에, 아카이빙된 파일을 분석 해본 후, 다음 업데이트에서 이를 반영해보도록 해야겠다.
사실 가장 궁금했던 부분이, Compose 로 iOS 앱의 UI 를 구성했을 때, 많이 느리거나 프레임 드랍등의 버벅이는 현상이 있는지 여부였다.
어쨌든 기존의 iOS 의 방식인 SwiftUI 나 UIKit 으로 UI 를 구성하지 않았기 때문에, Compose 코드가 iOS 의 UI 로 변환되면서 네이티브의 퍼포먼스를 보여주긴 힘들지 않을까 추측했다.
정상 동작하는지 확인은 회사 테스트 폰으로 몰래 몰래 해봤지만, 더 다양한 테스트를 위해 테스트용 아이폰 하나를 장만해야겠다. 추천 환영
다행히도, 지인분들께서 테스트 해주신 결과, 최신 아이폰에서 성능 이슈는 발생하지 않았다고 한다! 컴포즈 최고
다만 iOS 환경에서 신기한 버그들이 발생하는데, 왜 이런 버그들이 발생하는지 파악하여 해결해봐야겠다,,
https://github.com/Kotlin-User-Groups-Seoul
https://github.com/DroidKaigi/conference-app-2024
https://github.com/yjyoon-dev/kmp-multi-module-template
https://github.com/wespot-bff/WeSpot-Staff
https://github.com/wisemuji/compose-would-you-rather-game
https://github.com/Nexters/dobedobe-android
레퍼런스)
https://doitddo.tistory.com/177
https://dev.to/kingori/2025nyeone-andeuroideu-aebeul-mandeulgi-50df
오 흥미롭게 봤습니다! React Native에서 크로스 플랫폼으로 개발할 때와 어떤 점에서 달랐는지도 남겨주시면 좋을 것 같습니디ㅏ.