문제를 줄이자

Judy·2021년 9월 2일
0

문제

전체적인 앱 기능을 만들고 나서는 크고 작은 문제들이 보였다. 여러 개의 기능을 만드는 것 보다 이 문제들 하나 해결하는게 더 어렵다..

1) 로딩시간

  1. 원본 로딩
    기본 화면에서 장소의 이미지를 보여줘야 하는데 시간이 꽤 걸리고 한 번에 뜨지
    않았다. FireStore에서 모든 사진이 다운로드되면 한 번에 뜨도록 로딩 화면을 만들었다. 사진 하나를 다운 받을 때마다 Notification을 post해서 전체 장소 목록의 개수와 같으면 로딩이 끝나도록 했다.
  1. 이미지 다운샘플링
    로딩 화면을 통해 사진들을 한 번에 뜨게 할 순 있지만 모든 사진이 다운 될 때까지 기다리니 오래걸렸다. 앱에 들어오자마자 대기하면 사용자가 답답함을 느낄 수 있기 때문에 최대한 로딩 시간을 줄이고자 했다. 이미지의 사이즈를 줄여보니 다운 속도도 줄어들어 이미지를 resizing한 후 로드했다.

  2. 썸네일
    이미지 크기르 줄여 로딩 속도를 줄이긴 했지만 여전히 기다리는 시간이 길었다. 이미지 사이즈를 대폭 낮추면 더 빠르게 할 수 있지만 이미지 화질 또한 낮아져 크게 줄일 수가 없었다. 그래서 기본 목록 화면에서는 이미지가 크게 보이지 않기 때문에 사이즈를 최대한 줄인 이미지를 썸네일처럼 사용하고 원본 이미지는 따로 저장하여 초기에 로딩 시간을 줄이고 이미지의 화질저하 문제도 해결했다.

  3. 이어서 원본 이미지 저장
    썸네일로 로딩 시간은 빠르지만 장소를 보려면 원본 사진이 필요했다. 썸네일 사진은 테이블 셀을 생성할 때 다운받고 모든 이미지가 다운되어 로딩이 끝나면 원본 이미지들도 다운 받게 했지만 로딩이 끝나도 원본 이미지가 모두 다운될 때까지 작동을 안했다...

  4. 누를 때 원본 이미지 로드
    사실 원본 이미지가 필요한 것은 그 장소를 상세히 보려고 클릭 했을 때이다. 따라서 한 번에 모두 다운받을 필요가 없으니 장소를 클릭하면 일단 썸네일로 쓰인 이미지를 보여주고 원본 이미지를 다운 받으면 이미지를 교체하도록 했다.

    5-1. 이미지는 한 번만 받게
    썸네일도 처음 화면을 로딩할 때 한 번만 받고, 원본 이미지도 처음 클릭 했을 때만 받아와야 했다. PlaceDate에 이미지를 담는 orgImage 변수와 현재 썸네일만 받았는지 확인하는 thumbnail 변수를 추가했다.
    썸네일만 -> orgImage: 썸네일 / thumbnail: true
    원본 이미지 -> orgImage: 원본 이미지 / thumbnail: false
    thumbnail을 확인해 false면 원본 이미지를 받지 않는다.

    5-2. 받은 이미지를 넘겨주기
    받은 원본 이미지를 PlaceData 변수에 넣은 후 화면을 나가도 유지되도록 데이터를 넘겨줘야 했다. 프로토콜을 이용해 이미지를 담은 PlaceData를 받아 저장했다. 또한 기본 화면이 아닌 다른 화면에서 장소 상세히 보기로 넘어가 원본 이미지를 받았을 때도 업데이트가 되어야 하므로 원본 이미지를 새로 받으면 각각 tab 화면들끼리 데이터를 넘기도록 했다.

이미지 사이즈 줄이기

extension UIImage {
    func resize(newWidth: CGFloat) -> UIImage {
        let scale = newWidth / self.size.width
        let newHeight = self.size.height * scale
        let size = CGSize(width: newWidth, height: newHeight)
        let render = UIGraphicsImageRenderer(size: size)
        let renderImage = render.image {
            context in self.draw(in: CGRect(origin: .zero, size: size)) }        
        return renderImage
    }
    
    func downSample2(size: CGSize, scale: CGFloat = UIScreen.main.scale) -> UIImage {
        let imageSourceOption = [kCGImageSourceShouldCache: false] as CFDictionary
        let data = self.pngData()! as CFData
        let imageSource = CGImageSourceCreateWithData(data, imageSourceOption)!
        let maxPixel = max(size.width, size.height) * scale
        let downSampleOptions = [ kCGImageSourceCreateThumbnailFromImageAlways: true, kCGImageSourceShouldCacheImmediately: true,
                                  kCGImageSourceCreateThumbnailWithTransform: true, kCGImageSourceThumbnailMaxPixelSize: maxPixel ] as CFDictionary
        let downSampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downSampleOptions)!
        let newImage = UIImage(cgImage: downSampledImage)
        print("origin: \(self), resize: \(newImage)")
        return newImage
    }
}

2) 이미지 전역변수

이미지를 [String : UIImage] 딕셔너리에 넣고 전역변수로 관리해 어떤 페이지에서도 참조 가능하게 했다. PlaceData에서 장소 이름을 비교해 이미지를 참조했는데 그 방식이 번거롭고 전역변수를 갖고 있는게 좋지 않다고 생각하여 다른 방식을 고민했는데 썸네일을 사용하면서 장소 데이터에 이미지를 넣게 되어 이미지만 모은 변수가 필요 없게 되었다.

profile
iOS Developer

0개의 댓글