---
# System prepended metadata

title: Cache
tags: [토요스터디]

---

## NSCache
- 하기 이미지 링크를 활용하여 NSCache 구현
    - 이미지 1: https://wallpaperaccess.com/download/europe-4k-1369012
    - 이미지 2: https://wallpaperaccess.com/download/europe-4k-1318341
- UI 구성
1. 각 이미지를 URLSession을 통해 받아와서 ImageView 표시
```swift
 @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
        }
    }
```
2. NACache를 이용하여 ImageView에 캐시 데이터 활용
   2-1. 캐시 데이터가 없는 경우 : 새로 이미지를 요청하여 받고 표시/ "새로운 이미지를 받아왔습니다." 출력
   2-2. 캐시 데이터가 있을 경우 : 캐시된 데이터를 활용하여 이미지를 표시/ "캐시된 데이터가 있습니다." 출력
```swift
 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()
    }
}
```
3. 이미지 초기화 하기
```swift
@IBAction func tappedClearImage(_ sender: UIButton) {
    // 메모리 할당 해제 방법 2가지 
    firstImage.image = nil
    secondImage.image = UIImage()
    print("이미지 초기화")
}
```
4. 저장된 캐시를 비우기

```swift
@IBAction func tappedClearCache(_ sender: UIButton) {
    imageCache.removeAllObjects() // NS Cache
    imageCacheURL.removeAllCachedResponses() // URL Cache
    print("캐시 비우기")
}
```


## URLCache

```swift

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. 메모리 캐싱과 디스크 캐싱의 차이점 및 각각의 장단점
    ||메모리 캐싱|디스크 캐싱|
    |-|-|-|
    |특징|인메모리 저장만 가능<br>|인메모리, 온디스크 저장 가능|
    |장점|인메모리만 사용하기 때문에 로드 속도가 빠름|온디스크의 경우 앱이 종료되어도 시스템이 정리하지 않는 이상 데이터가 남아있음|
    |단점|앱 종료시 데이터가 모두 사라짐|온디스크의 경우 로드 속도가 인메모리에 비해 느림|

3. 캐시를 구현할 때 고려해야하는 캐시 운용 정책
    - Request
        1. useProtocolCachePolicy
        2. reloadIgnoringLocalCacheData
        3. reloadIgnoringLocalAndRemoteCacheData
        4. returnCacheDataElseLoad
        5. returnCacheDataDontLoad
        6. reloadRevalidatingCacheData
    - Response
        1. allowed
        2. allowedInMemoryOnly
        3. notAllowed


## 🔗참고링크
- [📚 Blog: NSCache](https://jryoun1.github.io/swift/Cache/)
- [📚 Blog: URLCache](https://levelup.gitconnected.com/image-caching-with-urlcache-4eca5afb543a)
- [🍎 Apple Developer: URLCache](https://developer.apple.com/documentation/foundation/urlcache)
- [🍎 Apple Developer: default](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1411560-default)