-
Notifications
You must be signed in to change notification settings - Fork 1
Naver_Maps와_Coil에서의_Marker_이미지_로딩_이슈_해결
yujin45 edited this page Nov 18, 2024
·
1 revision
- Naver Maps API를 사용해 Room DB에 저장된 여러 개의 이미지를 지도에 마커로 표시하려 했으나, Coil을 사용한 이미지 로딩이 제대로 작동하지 않는 문제가 발생했다. Coil 로딩 상태에서
DeferredCoroutine{Cancelled}
메시지가 반복적으로 출력되며, 로딩이 취소되는 현상이 나타났다. 그 결과, Marker에 설정된 OverlayImage가 이미지 로딩 전 상태의 View를 사용하면서 원하는 이미지가 정상적으로 표시되지 않았다.
-
문제 상황 인지: 처음에는 Coil로 로딩된 이미지를 MapView에 Marker로 추가하기 위해 Coil을 사용해 ImageView에 로드한 후, 이 ImageView를
OverlayImage.fromView()
를 통해 Marker에 적용했다. 그러나 Coil이 이미지 로딩을 시작하지 않고,DeferredCoroutine{Cancelled}
메시지만 출력되었다. -
로그 확인: Coil의
ImageRequest.Builder
에 리스너를 추가하고 로그를 통해 onStart와 onSuccess 등의 상태가 호출되지 않는 것을 확인했다. 이를 통해 Coil 요청이 정상적으로 작동하지 않고 취소되는 것을 파악했다.
- Coil load의 listener에서 onStart자체가 실행되지 않음
- ▲ Log 출력 결과 job이 Cancelled 되는 것을 확인
- ▲ MapView의 Lifecycle은 정상 작동하는 것 확인
-
Composable을 사용해 이미지 로드 테스트:
-
시도: Coil로 이미지를 로드한 후
ComposeView
에 마커를 설정하는 방식을 고려해,Composable
에서 이미지를 표시해보고자 했다. -
결과:
MapView
를 사용하지 않고 Composable만 사용할 때는 Coil이 정상적으로 이미지를 로드했다. 그러나 MapView와 함께 사용하는 경우에는 로딩 문제가 여전히 발생했다. - 분석: 문제는 MapView와 함께 사용될 때 발생하는 것으로 보였으며, View 생명주기와 관련이 있을 것으로 추정되었다.
-
시도: Coil로 이미지를 로드한 후
-
MapView 대신 Fragment를 사용하여 마커 표시 시도:
-
시도: MapView 대신 Fragment를 사용해 ImageView를 포함한 커스텀 마커 뷰를 Marker의 OverlayImage로 설정했다.
-
결과: 커스텀 마커 뷰를 사용하여도 이미지가 정상적으로 로드되지 않고 Coil의 로딩이 취소되는 문제가 발생했다. 로그를 통해 Coil의
ImageRequest
가 시작되지 않는 것을 확인했다. -
추가 분석: 이로 인해 Attach 상태에서 Coil 로딩이 문제를 일으킬 수 있다는 점을 의심하게 되었다. Coil 로딩을 위해 View가 Attach 상태에 있어야 함을 확인한 후, Attach 상태에서만 로딩을 시도해야 함을 알게 되었다. ⭐
// Coil 관련 override fun assertActive() { if (!target.view.isAttachedToWindow) { target.view.requestManager.setRequest(this) throw CancellationException("'ViewTarget.view' must be attached to a window.") } }
-
-
LifecycleObserver와
DisposableEffect
활용 테스트:-
시도: MapView의 생명주기를 Compose의
DisposableEffect
와LifecycleObserver
로 직접 관리하면서 ImageView를 추가하고, Marker가 올바르게 표시되는지 테스트했다. - 결과: MapView 자체의 생명주기는 정상적으로 관리되었지만, 여전히 ImageView에서 Coil 로딩이 취소되었다.
- 분석: MapView는 정상적으로 동작했으나, Coil이 ImageView를 Attach된 상태에서 처리하지 못하고 취소되는 문제가 계속되었다. 이를 통해 Attach 상태가 Coil의 요청 활성화에 필수적임을 재차 확인했다.
-
시도: MapView의 생명주기를 Compose의
-
ViewTreeObserver를 통한 Attach 상태 확인 후 Marker에 추가:
- 시도: ViewTreeObserver를 사용해 ImageView가 Window에 완전히 Attach된 후 Coil 로딩을 시작하고, Coil 로딩이 완료된 후 Marker에 추가되도록 작업 순서를 조정했다.
- 결과: View가 Attach된 이후 Coil 로딩을 시작하면서 Coil의 이미지 로딩이 정상적으로 완료되었고, 이를 Marker의 OverlayImage로 추가할 수 있었다. 최종적으로 이미지가 정상적으로 Marker에 표시되었다.
- 분석: ImageView가 Window에 완전히 Attach된 이후에 Coil이 활성화되어 로딩을 성공적으로 수행하는 것을 확인했다. 따라서, View의 Attach 상태가 이미지 로딩의 성패를 좌우하는 주요 원인임을 확인할 수 있었다.
-
OverlayImage.fromView()의 비동기 처리 한계 파악:
-
문제 분석:
OverlayImage.fromView()
는 호출 시점에 View의 현재 상태를 비트맵으로 변환하기 때문에, 이미지가 완전히 로딩되기 전의 View 상태가 비트맵으로 변환될 경우, 예상과 달리 빈 View가 Marker에 표시되는 현상이 발생했다. - 해결책: Coil 로딩이 완료된 후, 완전한 이미지 상태의 View를 Marker에 적용하는 방식으로 수정했다.
-
문제 분석:
-
ImageView의 Attach 상태: Coil의 ImageLoader는 View가 Attach된 상태에서만 활성화되어 로딩을 시작할 수 있다. Attach되지 않은 View에서는 Coil 로딩이 취소되어
DeferredCoroutine{Cancelled}
메시지가 출력되었다. -
OverlayImage.fromView()의 비동기 처리 한계:
OverlayImage.fromView()
는 호출 시점의 View 상태를 바로 비트맵으로 변환하기 때문에, View의 이미지가 완전히 로딩되기 전에 호출될 경우, 빈 View가 비트맵으로 변환되어 Marker에 표시된다.
-
ImageView
가 Attach된 후에 로딩 요청하기: ViewTreeObserver를 통해ImageView
가 Window에 Attach된 후 Coil 로딩을 수행하고, 로딩이 완료된 시점에서 Marker에 추가되도록 작업 순서를 조정했다. -
Coil을 사용하여 마커 이미지 로딩: Coil 로딩 과정에서 발생한 취소 문제를 해결하기 위해
ImageView
가 Attach된 상태를 확인한 후에만 이미지를 로딩하게 설정했다.
imageView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (imageView.isAttachedToWindow) {
val marker = Marker().apply {
position = LatLng(photoDetail.latitude, photoDetail.longitude)
icon = OverlayImage.fromView(imageView)
map = naverMap
}
imageView.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
})
-
정상적인 이미지 로딩:
ImageView
가 Attach된 후에 Coil이 이미지를 정상적으로 로딩했고, 이를 Marker의OverlayImage
로 설정할 수 있었다. -
Marker에 올바른 이미지 표시: Marker에 완전히 로드된
ImageView
상태를 비트맵으로 변환하여OverlayImage
로 적용할 수 있었다.
- Coil의 ImageLoader는 View가 Window에 Attach된 상태여야 활성화되어 로딩을 시작한다.
OverlayImage.fromView()
는 호출 시점의 View를 비트맵으로 변환해 Marker에 사용하므로, 이미지가 완전히 로드된 상태의 View를 Overlay로 설정해야 한다. 이를 위해 View가 Attach된 이후 Coil 로딩을 시작하도록 작업 순서를 조정함으로써, 정상적인 이미지 표시가 가능하게 되었다.
위 문제 해결과 관련된 PR 링크는 다음과 같다: https://github.com/boostcampwm-2024/and04-Nature-Album/pull/115
데일리 스크럼
1주차
2주차
3주차
4주차
5주차
회의록
1주차
2주차
3주차
4주차
5주차