Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Compose Multiplatform Image Picker

easyhooon
January 10, 2024

Compose Multiplatform Image Picker

찰스님 주최하신 KMP 스터디에서 발표했던 내용을 공유합니다

easyhooon

January 10, 2024
Tweet

Other Decks in Programming

Transcript

  1. Kotlin Multiplatform 이 아닌 Compose Multiplatform 을 선택한 이유 •

    빠르게 프로젝트를 마무리 해야함 • Swift 라는 언어와 SwiftUI에 대한 숙련도가 아직 부족하여, 익숙한 Kotlin 기반의 Compose 로 공통의 UI 를 작성 해보는 것을 둘 다 선호 • Image Picker 라는 단순한 앱이기에, UI 를 Compose, SwiftUI 로 각각 작성 할 필요가 없다고 판단 • 이미지 로드를 위한 Coil 라이브러리가 3버전 부터 Compose Multiplatform 을 지원
  2. 프로젝트 구조 • commonMain 의 rememberImagePickerLauncher expect 함수를 androidMain, iosMain

    에서 actual 함수 로 구현 • Screen 과 Component 는 commonMain 에서 공통으로 관리
  3. 이슈 공유 1. Android 에서는 PhotoPicker 를 통해 별도의 권한

    없이 갤러리에 접근할 수 있는데, iOS 에서는??? 2. Coil3 을 통해 네트워크 이미지를 로드할 때, 기존의 Coil2 와 다른 점 3. moko-resources 라이브러리를 통해 국제화를 적용할 때, Android 측 Config Change 관련 이슈 4. Decompose 라이브러리의 Navigation 을 통해 데이터를 전달해야 하는데, 각 플랫폼에서 받아온 사진의 Data Type이 다른 문제
  4. 이슈 1) iOS 에서는 갤러리에 어떻게 접근? • iOS 에서는

    iOS 14 부터 PHPicker 를 사용 • 해당 기능을 구현하는 것이 이번 프로젝트의 핵심 • Peekaboo 라는 Compose Multiplatform 을 지원하는 imagePicker 라이브러리의 내부 코드를 참고해서 구현 https://github.com/TEAM-PREAT/peekaboo
  5. 이슈 1) iOS 에서는 갤러리에 어떻게 접근? • iosMain 는

    iosApp 모듈이 아닌 composeApp 모듈에 포함되어 있기 때문에 Swift 가 아닌, Swift 와 호환 가능한 Kotlin-Native 기반으로 코드를 작성 • PHPickerViewController 를 호출하기 위해 PHPickerViewControllerDelegateProtocol 인터페이스를 구현하는 delegate 객체를 정의 • 결과적으로 선택된 이미지가 NSData 타입으로 내려오는데 이를 Kotlin-Native 에서 사용할 수 있는 ByteArray 타입으로 변환 참고) Compose-multiplatform 이미지 피커 라이브러리 배포하기 composeApp/iosMain/imagePickerLauncher.kt
  6. 이슈 2) Coil3 를 이용한 Network Image Load (Coil3 에서

    제공하는 LocalPlatformContext 를 통해 context 에 접근 가능) 기존과 같이 coil 라이브러리를 주입하 고, 이미지를 로드 해보았지만 image 가 화면에 출력되지 않는 문제 가 발생…
  7. 이슈 2) Coil3 를 이용한 Network Image Load https://coil-kt.github.io/coil/upgrading_to_coil3/#network-images 기존에

    Coil2.x 버전에서는 Network Image 를 로드할 때, Coil 내부에서 OkHttp 를 사용 Coil3 버전에서는 Multiplatform 을 지원하기 위해 OkHttp 가 아닌 Ktor 를 사용하는 것으로 변경 현재 alpha 버전인 Coil3 에서는 ImageLoader 가 기본적으로 network url 형태의 이미지를 로드하는 것을 지원하지 않음 별도로 coil-network 와 ktor 를 import 하여 NetworkFetcher.Factor()를 직접 설정
  8. 이슈 3) moko-resources Android i18n Config Change Multiplaform 환경에서 resources(string,

    font, image) 등을 공유하여 사용하기 위해, 국제화를 지 원하기 위해 moko-resources 라이브러리를 사용 iOS 환경, Xcode 에서 resources 들을 복제하기 위한 환경 설정이 추가적으로 필요(공식 문서 참고) moko-resources 0.23.0 버전 기준) Android 기기에서 시스템 언어를 변경한 뒤, 앱에 다 시 진입했을 때, 변경된 언어가 반영이 되지 않는 문 제 (다시 앱을 실행해야 반영) https://github.com/icerockdev/moko-resources
  9. 이슈 4) Decompose Navigation argument type Decompose 는 Androidx 의

    Navigation 과 AAC ViewModel 과 비슷한 State holder 를 Multiplatform 에서 제공하는 라이브러리 문제는 Navigation 을 통해 상세 화면으로 전달해야 할 데이터의 타입이 Android 에서는 android.net.Uri, iOS 에서는 ByteArray 타입으로 같지 않다는 것 (심지어 android.net.Uri 타입은 android 플랫폼 종속성이 있어, commonMain 에서 접근 불가)
  10. 이슈 4) Decompose Navigation argument type • 전달해야 할 타입을

    Kotlinx-Serialization 을 통해 직렬화 할 수 있는 ByteArray 로 통일하여 해결 • Uri 를 ByteArray 로 변환하기 위해, Coil3 를 이용 • 하지만 Coil3 는 Coil2 버전과 차이점이 존재해 오른쪽의 기존의 사용했던 함수를 사용할 수 없음 • 공식 문서도 확인해보았으나, alpha 버전이 나온 지 얼마 되지 않아, 레퍼런스가 없어 해결하는데 어려움이 존재
  11. 이슈 4) Decompose Navigation argument type 영광스럽게도 skydoves 님의 도움을

    받아, coil3 에서 사용할 수 있는 함수로 migration 할 수 있었음
  12. 후기 • 시니어) 권대원 • CMP를 접하기 전에는 컴포즈로 Android,

    iOS UI를 그린다는것이 상상이 가지 않았 지만, 별개로 존재하는 iOS의 lifecycle 같은 부분들을 주의한다면 KMM 과 크게 다르 지 않다고 느꼈다. • 이번 KMM 스터디를 진행하면서 조금은 익숙해진 덕분에 공통 로직을 생성하여 각 플랫폼 별로 비즈니스 로직을 구현할 수 있었다. 특히 iOS 모듈에서는 kotlin-native 로 구현을 하면서 kotlin-native 에 큰 의존성을 갖고 있다보니, 제한사항을 마주할 수 있다는 생각이 들었다. • 그리고 지훈님이 decompose, moko-resources 등 여러 라이브러리 사용과 아이디어 를 주셔서 많이 배울 수 있었다.
  13. 후기 • 주니어) 이지훈 • 토이 프로젝트를 하면서 Compose Multiplatform

    과 조금이나마 친해질 수 있어서 좋았다. 프로젝트 초기에 환경 설정 단계(coil) 에서 어려움이 있었는데, 대원님께서 해결을 해주셔서, 빠르게 다음 단계로 넘어갈 수 있었다. • 다음에도 이런 좋은 기회가 있다면, Multiplatform 을 지원하는, 써보지 않았던 다른 라이브러리들도 사용 해보면서, 좀 더 규모 있는 앱을 만들어보고 싶다.
  14. 참고 • 이슈 해결의 대한 더욱 자세한 내용은 하단의 블로그

    글 링크를 참고 • [Compose Multiplatform] Coil 을 이용한 Network Image Load • [Compose Multiplatform] moko-resources 를 이용하여 font 적용하기 • [Compose Multiplatform]moko-resources 라이브러리를 통해 국제화(i18n) 적용하기 • [Compose Multiplatform] Decompose 라이브러리를 통해 Navigation 구현하기 (깃허브 레포에도 링크 걸어놨어요!)