Skip to content

[week13] Cache

Daehoon Lee edited this page Aug 5, 2023 · 1 revision

NSCache

  1. 각 이미지를 URLSession을 통해 받아와서 ImageView 표시
 @IBAction func ImageViewLoad(_ sender: UIButton) {
        switch sender {
        case firstImageView:
            getImage(firstImageView, "https://wallpaperaccess.com/download/europe-4k-1369012")
        case secondImageView:
            getImage(secondImageView, "https://wallpaperaccess.com/download/europe-4k-1369012")
        default:
            break
        }
    }
  1. NACache를 이용하여 ImageView에 캐시 데이터 활용 2-1. 캐시 데이터가 없는 경우 : 새로 이미지를 요청하여 받고 표시/ "새로운 이미지를 받아왔습니다." 출력 2-2. 캐시 데이터가 있을 경우 : 캐시된 데이터를 활용하여 이미지를 표시/ "캐시된 데이터가 있습니다." 출력
 private func getImage(_ myImage: UIImageView, _ url: String) {
    let cacheKey = NSString(string: url)

    guard let imageUrl = URL(string: url) else { return }

    if let cachedImage = ImageCacheManager.shared.object(forKey: cacheKey) {
        myImage.image = cachedImage
        print("캐시된 이미지")
        return
    } else {
        print("새로운 이미지")
        let task = URLSession.shared.dataTask(with: imageUrl) { data, response, error in
            if let error {
                print(error.localizedDescription)
                return
            }

            guard let httpResponse = response as? HTTPURLResponse,
                  (200...299).contains(httpResponse.statusCode) else {
                print("http 오류")
                return
            }

            guard let data,
                  let image = UIImage(data: data) else {
                print("이미지 오류")
                return
            }

            ImageCacheManager.shared.setObject(image, forKey: cacheKey)

            DispatchQueue.main.async {
                myImage.image = image
            }
        }
        task.resume()
    }
}
  1. 이미지 초기화 하기
@IBAction func tappedClearImage(_ sender: UIButton) {
    // 메모리 할당 해제 방법 2가지 
    firstImage.image = nil
    secondImage.image = UIImage()
    print("이미지 초기화")
}
  1. 저장된 캐시를 비우기
@IBAction func tappedClearCache(_ sender: UIButton) {
    imageCache.removeAllObjects() // NS Cache
    imageCacheURL.removeAllCachedResponses() // URL Cache
    print("캐시 비우기")
}

URLCache

final class ViewController: UIViewController {
    let cache = URLCache.shared
    ...
}

extension ViewController {
    func fetchImage(from urlString: String, apply imageView: UIImageView) {
        guard let url = URL(string: urlString) else { return }
        let request = URLRequest(url: url)
        
        if let data = self.cache.cachedResponse(for: request)?.data,
           let image = UIImage(data: data) {
            print("캐시된 데이터가 있습니다.")
            ...
        } else {
            print("새로운 이미지를 받아왔습니다.")
            URLSession.shared.dataTask(with: url) { data, response, error in
             ...
                // cache 저장
                let cachedData = CachedURLResponse(response: httpResponse, data: data)
                self.cache.storeCachedResponse(cachedData, for: request) 
            ...
            }.resume()
        }
    }
}

NSCache vs. URLCache

  1. NSCache와 URLCache의 차이점 NSCache

    • NSCache는 일반적인 객체들의 메모리 기반 캐시를 구현하기 위해 사용
    • 주로 메모리 내에서 데이터를 임시로 저장하고, 메모리 부족 상황에서 자동으로 데이터를 제거하여 앱의 성능을 최적화
    • 특정 메모리 제한에 도달하면 자동으로 데이터를 삭제하므로, 메모리 관리에 편의성을 제공
    • 일반적으로 이미지나 다운로드한 데이터와 같이 빠르게 접근해야 하는 데이터를 저장하는 데 사용

    URLCache

    • URLCache는 네트워크 요청의 응답 데이터를 디스크 또는 메모리 기반 캐시로 저장하는 데 사용
    • 네트워크 요청의 결과를 저장하고, 이후 동일한 요청이 발생했을 때 캐시된 데이터를 반환하여 네트워크 사용량과 응답 시간을 줄일 수 있음
    • 주로 네트워크 요청의 성능 최적화를 위해 사용
    • 캐시 정책 및 제한을 더욱 세밀하게 제어할 수 있도록 설정할 수 있음
  2. 메모리 캐싱과 디스크 캐싱의 차이점 및 각각의 장단점

    메모리 캐싱 디스크 캐싱
    특징 인메모리 저장만 가능
    인메모리, 온디스크 저장 가능
    장점 인메모리만 사용하기 때문에 로드 속도가 빠름 온디스크의 경우 앱이 종료되어도 시스템이 정리하지 않는 이상 데이터가 남아있음
    단점 앱 종료시 데이터가 모두 사라짐 온디스크의 경우 로드 속도가 인메모리에 비해 느림
  3. 캐시를 구현할 때 고려해야하는 캐시 운용 정책

    • Request
      1. useProtocolCachePolicy
      2. reloadIgnoringLocalCacheData
      3. reloadIgnoringLocalAndRemoteCacheData
      4. returnCacheDataElseLoad
      5. returnCacheDataDontLoad
      6. reloadRevalidatingCacheData
    • Response
      1. allowed
      2. allowedInMemoryOnly
      3. notAllowed

🔗참고링크