티스토리 뷰

iOS

[Swift] NSCache, 이미지캐시 개념

Peppo 2022. 6. 17. 08:34
728x90

오늘은 이미지 캐시에 대해 공부해 보려고 합니다. 

 

보통 이미지의 경우 크기가 작지 않기 때문에 불러오는데 시간이 걸리게 됩니다. 

컬렉션뷰, 테이블뷰 에서 스크롤을 하게되면 데이터를 다시 불러오게되어 사진의 경우

아래처럼 뒤늦게 바뀌는걸 볼 수 있습니다. 

기존에 있던 날씨 이미지 → 새로 받아오는 이미지로 뒤늦게 바뀌는게 보이시나요? 

 

문제를 해결하기 위해선 캐시처리에 대해 알아야 하는데요.

과제때는 급하게 처리하느라 코드 복붙이었는데 개념부터 차근차근 알아봅시다 🙌

 


캐시 - Cache

 

기기 안의 임시저장소를 뜻합니다.

 

임시 저장소를 통해 이미지를 저장해 뒀다가 보여질때가 되면 저장했던 이미지를 그대로 가져와 뿌려줍니다. 

 

 

Cache의 종류

Memory cache (휘발성)

  • 기기를 끄면 저장된 데이터가 사라집니다. 
  • Swift에서 NSCache 로 구현 가능 합니다.
  • 처리속도는 빠르지만 저장공간이 작습니다.

 

Disk cache (비휘발성)

  • 기기를 꺼도 데이터가 남아있습니다.
  • UserDefault를 이용한 데이터 저장 → 단, 앱 삭제시 데이터도 삭제 
  • 파일경로에 이미지 저장 → 앱 삭제시에도 캐시가 남아 있음.
  • 예) 카카오톡에서 친구들에게 받은 사진, 동영상들은 다운받아야 볼수 있는데, 이때 다운받은 파일들이 캐시에 포함 됩니다. 

 

저장공간 처리속도
메모리캐시 < 디스크캐시 메모리캐시 > 디스크캐시

 

여기서 오늘은 NSCache에 대해 알아보려고 합니다.

 


NSCache

 

리소스가 부족할때 제거될 key-value쌍을 임시저장 하는데 사용하는 가변 컬렉션.

 

대충 임시저장 하지만 메모리를 많이 차지하면 자동으로 제거 된다는 뜻.

 

 

NSCache 적용

 

1. ImageCacheManager 싱글톤 클래스 만들기 

import UIKit

final class ImageCacheManager {
    static let shared = NSCache<NSString, UIImage>()
    private init() { }
}

 

NSCache 는 key-value 로 이루어져 있다고 했습니다. 

Key값:  NSString

Value값: UIImage

위처럼 키, 밸류값을 구분합니다.

 

캐싱의 순서는 아래와 같습니다. 

 

1. 이미지를 가져오기전 캐싱된 데이터에 해당 이미지가 있는지 확인 

2. 캐싱된 이미지 유/무 에 따라 아래 표 대로 진행

 

캐싱된 이미지가 있을경우 캐싱된 이미지가 없을경우
해당 이미지 사용 서버에서 이미지 받아온 후 → ImageCacheManager 캐시에 저장
extension UIImageView {
    func load(urlString: String) {
        // 1. 저장된 캐시키가 있으면 이미지 바로 보여주기
        let cachedKey = NSString(string: urlString)
        if let cachedImage = ImageCacheManager.shared.object(forKey: cachedKey) {
            DispatchQueue.main.async {
                self.image = cachedImage
                return
            }
        }
        
        guard let iconUrl = URL(string: urlString) else { return }
        // 2. 없으면 아래 네트워킹 호출해서 이미지url을 받아오기
        URLSession.shared.dataTask(with: iconUrl) { data, _, error in
            guard error == nil else {
                DispatchQueue.main.async { [weak self] in
                    self?.image = UIImage()
                }
                return
            }
            
            DispatchQueue.main.async { [weak self] in
                if let data = data,
                   let image = UIImage(data: data) {
                    // 3. 받아온 이미지url(value), image(key) 저장
                    ImageCacheManager.shared.setObject(image, forKey: cachedKey)
                    self?.image = image
                }
            }
        }.resume()
    }
}

 

이렇게 캐싱 처리를 해놓으면 !?

 

 

 

한번 불러왔던 이미지 데이터를 저장하고 있다가 필요할 때 캐싱된 데이터를 불러와 바로 보여줄 수 있게 됩니다! 

 


참고

 

https://developer.apple.com/documentation/foundation/nscache

https://dev-in-gym.tistory.com/111

https://ios-development.tistory.com/658

https://nsios.tistory.com/58

https://jryoun1.github.io/swift/Cache/

728x90