현재 원더보드에 올라와 있는 게시물을 선택하면 이미지를 불러오는 로딩 속도가 상당히 느려서 이용성이 저하되는 문제가 있었다.
이용자 피드백에서도 해당 내용이 거론되었고 내부적으로도 이 부분은 우선적으로 수정해야하는 의견이 많아 얼른 수정해야 한다.
이 점을 개선하기 위해 Kingfisher를 활용해서 이미지 캐싱을 손보고 로딩 속도를 개선하고자 한다.
이미지 로딩 로직 수정
먼저 이전의 저장되어있는 이미지를 불러오는 구현을 살펴보면
func updateSelectedImages(with mediaItems: [Media]) {
selectedImages.removeAll()
let group = DispatchGroup()
for media in mediaItems {
guard URL(string: media.url) != nil else { continue }
group.enter()
loadImage(from: media.url) { [weak self] image in
guard let self = self else {
group.leave()
return
}
if let image = image {
let location: CLLocationCoordinate2D? = (media.latitude != nil && media.longitude != nil) ? CLLocationCoordinate2D(latitude: media.latitude!, longitude: media.longitude!) : nil
if !self.selectedImages.contains(where: { $0.0 == image && $0.1 == media.isRepresentative && $0.2?.latitude == location?.latitude && $0.2?.longitude == location?.longitude }) {
self.selectedImages.append((image, media.isRepresentative, location))
}
}
group.leave()
}
}
group.notify(queue: .main) {
if let galleryCell = self.detailViewCollectionView.cellForItem(at: IndexPath(item: 0, section: 0)) as? GalleryCollectionViewCell {
galleryCell.selectedImages = self.selectedImages
}
}
}
func loadImage(from urlString: String, completion: @escaping (UIImage?) -> Void) {
guard let url = URL(string: urlString) else {
completion(nil)
return
}
AF.request(url).response { response in
if let data = response.data, let image = UIImage(data: data) {
completion(image)
} else {
completion(nil)
}
}
}
이미지가 로드 되는 과정을 보면 알라모파이어를 통해 이미지를 가져오게 되는데 원본 그대로 가져오게 되어 리뉴얼로 크게 이미지를 구현하는 것으로 바뀐 지금에는 그 데이터가 너무 커 firebase에서도 용량을 많이 차지하는 경향이 있었다.
이 부분을 개선하기 위해 킹피셔를 활용해 이미지 캐싱을 하고 빠르게 이미지 로드 하는 로직으로 변경하였다.
func updateSelectedImages(with mediaItems: [Media]) {
selectedImages.removeAll()
let group = DispatchGroup()
for media in mediaItems {
guard let url = URL(string: media.url) else { continue }
group.enter()
KingfisherManager.shared.retrieveImage(with: url, options: nil) { [weak self] result in
guard let self = self else {
group.leave()
return
}
switch result {
case .success(let value):
let image = value.image
let location: CLLocationCoordinate2D? = (media.latitude != nil && media.longitude != nil) ? CLLocationCoordinate2D(latitude: media.latitude!, longitude: media.longitude!) : nil
if !self.selectedImages.contains(where: { $0.0 == image && $0.1 == media.isRepresentative && $0.2?.latitude == location?.latitude && $0.2?.longitude == location?.longitude }) {
self.selectedImages.append((image, media.isRepresentative, location))
}
case .failure(let error):
print("Failed to load image: \\(error)")
}
group.leave()
}
}
group.notify(queue: .main) { [weak self] in
guard let self = self else { return }
if let galleryCell = self.detailViewCollectionView.cellForItem(at: IndexPath(item: 0, section: 0)) as? GalleryCollectionViewCell {
galleryCell.selectedImages = self.selectedImages
}
}
}
retrieveImage
KingfisherManager.shared.retrieveImage(with: url, options: nil)
킹피셔의 싱글톤을 활용해서 이미지 로딩 작업을 관리하도록 한다.
retrieveImage(with:options:completionHandler:)
메서드는 지정된 URL에서 비동기적으로 가져온다.
switch result {
case .success(let value):
let image = value.image
...
case .failure(let error):
print("Failed to load image: \\(error)")
}
result는 Result<RetrieveImageResult, KingfisherError> 타입인데 이미지 가져오는 걸 성공하면 value.image로 이미지에 접근 할 수 있다.
킹피셔의 자동 캐싱을 활용해서 로드도니 이미지를 메모리와 디스크에 자동으로 캐시하고 이 코드는 캐시옵션을 설정하지 않았지만 기본적으로 캐싱을 수행한다.
모든 이미지 로딩 작업이 백그라운드에서 비동기적으로 수행되기 떄문에 더욱 빠르게 로딩이 가능해진다.
이를 통해서 이미지가 너무 늦게 뜨는 것을 수정하고 조금 더 앱 이용성을 챙길 수 있었다.
'◽️ Programming > T I L' 카테고리의 다른 글
[.There 프로젝트 일지] - UI 구성하기 (3) | 2024.07.22 |
---|---|
PHPicker 권한 안내 구현하기 (0) | 2024.07.10 |
[Project 일지] 여행 기록 앱 만들기 (12) - 2.0 버전 업데이트 진행(UI 수정 및 디테일 보완, 오류 수정) (0) | 2024.07.01 |
[Project 일지] 여행 기록 앱 만들기 (11) - Mate 업데이트 구현 (0) | 2024.06.29 |
[Project 일지] 여행 기록 앱 만들기 (10) - 앱 승인 이후 Update (0) | 2024.06.27 |