NSCache
는 주로 Memory Caching
에 사용되는 클래스로, 메모리에서 해제될 때 자동으로 캐시된 내용이 제거됩니다. 메모리 부족 시 NSCache
는 자동적으로 객체를 제거하여 메모리를 효율적으로 관리하며, 간단하게 사용할 수 있는 인터페이스를 제공합니다.
Key-Value
쌍 저장Thread-Safe
고화질, 고용량의 이미지를 계속해서 다운로드하게 되면 사용자의 네트워크 리소스를 계속 소모하는 것은 물론, 다운로드가 완료되기까지 걸리는 시간도 낭비됩니다.
따라서 애플리케이션에서 다운로드한 이미지를 캐싱하여 저장해두면, 한 번 다운로드했던 이미지는 나중에 별도의 리소스를 소모할 필요 없이 빠르게 보여줄 수 있는 장점이 있습니다.
TableView, CollectionView에서 사용자가 뷰를 스크롤 시 같은 이미지를 요청하는 경우가 생기고, 이때 Cache를 통해서 이미지에 해당하는 URL은 API를 한 번만 호출하도록 하기 위함입니다.
Memory Caching
앱의 메모리 영역의 일부분을 Caching에 사용하는 것
Disk Caching
데이터를 파일 형태로 디스크에 저장하는 것
Disk Cache는 보통 FileManager 객체를 사용하여 데이터를 파일 형태로 디스크에 저장하거나 UserDefaults
, CoreData
를 사용합니다.
import UIKit
import Alamofire
final class ImageCacheManager {
static let shared = ImageCacheManager()
private init() { }
private let cache = NSCache<NSURL, UIImage>()
func loadImage(url: String) async -> UIImage? {
guard let url = URL(string: url) else { return nil }
// Cache에 저장된 이미지가 있는 경우
if let image = cachedImage(url: url) {
return image
}
// Cache에 저장된 이미지가 없는 경우
let dataTask = AF.request(url, method: .get)
.serializingData()
switch await dataTask.result {
case .success(let data):
let image = UIImage(data: data)
cachingImage(url: url, image: image)
return image
case .failure(let error):
print(error.localizedDescription)
return nil
}
}
private func cachingImage(url: URL, image: UIImage?) {
guard let image = image else { return }
cache.setObject(image, forKey: url as NSURL)
}
private func cachedImage(url: URL) -> UIImage? {
cache.object(forKey: url as NSURL)
}
}
final class ThumbnailCell: UICollectionViewCell {
// 생략
func configure(data: Thumbnails.Item) {
let url = data.snippet.thumbnails.high.url
let channelID = data.snippet.channelId
Task {
let image = await ImageCacheManager.shared.loadImage(url: url)
imageView.image = image
}
titleLabel.text = data.snippet.title
subTitleLabel.text = data.snippet.description
}
}
이미지를 요청하면 먼저 Cache에 저장된 이미지가 있는지 확인한 후 이미지가 있다면 해당 이미지를 return 하고, Cache에 저장된 이미지가 없다면 서버로부터 데이터를 가져오고 나서 Cache에 이미지를 저장하는 방식으로 구현했습니다.