
캐시
캐시란 자주 사용하는 데이터나 값을 미리 복사해 놓는 임시 저장소이다.
갑자기 iOS에서 이 개념이 왜 나올까 ??
부스트 캠프 과정 중 앱 개발을 할 때 항상 비용을 고려해야한다.
비용은 크게 2가지로 나눠진다
- 비용 Money
- 전원 Power
전원 Power는 말 그대로 우리 서비스를 이용할 때 배터리 소모량이 된다.
비용 Money은 우리 서비스를 이용하면서 유저가 지불해야하는 금액적인 비용이다.
금액적인 비용은 우리 서비스내의 제품을 구매할 때도 역시 필요하지만
앱이 네트워크가 필요하여 인터넷 비용도 있다.
우리가 컨트롤 할 수 있는 것은 바로 인터넷 비용이다.
우리는 유저의 인터넷비용을 최대한 기술적으로 절감시켜 유저 이탈 수를 막야한다.
대표적인 예로 바로 캐시 데이터를 통해 불필요한 네트워크 통신을 막아 비용을 절감시킬 수 있다.
우리는 오늘 이미지를 캐싱하여 불필요한 이미지를 불러오는 작업을 막아보자.
우리가 사용할 캐시는 크게 두가지 영역이다.
- Memoery Cache
- 애플리케이션 메모리 영역의 일부분을 캐싱
- 앱이 종료되면 사라지는 휘발성 캐시
- NSCache, URLCache 존재
- Disk Cache
- 데이터를 파일 형태로 디스크에 저장
- 반복적으로 발생하면 애플리케이션이 차지하는 용량이 커지는 단점
- 앱이 종료되어도 데이터가 사라지지 않는 비휘발성 캐시
- FileManager를 이용한다.
NSCache
A mutable collection you use to temporarily store transient key-value pairs that are subject to eviction when resources are low.
class NSCache<KeyType, ObjectType> : NSObject where KeyType : AnyObject, ObjectType : AnyObject
정의
- iOS 애플리케이션에서 Memoery Caching에 주로 사용되는 클래스이다.
- key - value 형태의 임시 저장 가변 컬렉션
특징
1. 캐시를 잠글 필요 없이 별도 스레드에서 캐시 항목을 추가/ 삭제/ 검색 할 수 있다.
2. NSMutableDictionary 객체와 달리 키 객체를 복사하지 않는다.
- key-value 형태의 데이터를 임시로 저장할 때 NSMutableDictionary 가변 컬렉션이 있다.
- 그렇다면 차이가 NSCache와 차이가 뭘까 ??
- NSCache는 키 객체를 복사하지 않고 NSMutableDictionary은 key 객체가 복사된다.
- 차이는 다음 코드를 살펴보자, 출처는 밑의 stack over flow를 살펴보자.
- NSMutableDictionary은 key 변수에 새로운 값이 할당되어도 이전 key에 대한 값이 남아있고
- NSCache는 key 변수에 새로운 값이 할당되면 이전 키값에 대한 값이 남아 있지 않는다.
et mutableDic = NSMutableDictionary()
var dicKey: NSMutableString = "key" // K₁
mutableDic.setObject("one", forKey: dicKey) // K₂
dicKey.setString("changedKey") // still K₁
mutableDic.setObject("two", forKey: dicKey) // K₃
print(mutableDic.object(forKey: "key") ?? "") // "one"
print(mutableDic.object(forKey: "changedKey") ?? "") // "two"
// BUT:
let cache = NSCache<NSString, NSString>()
var cacheKey: NSMutableString = "key" // K₁
cache.setObject("one", forKey: cacheKey) // still K₁
cacheKey.setString("changedKey") // still K₁
cache.setObject("two", forKey: cacheKey) // still K₁!
print(cache.object(forKey: "key") ?? "") // "" !!!
print(cache.object(forKey: "changedKey") ?? "") // "two"
3. 연결리스트와 Dictionary를 함께 사용한다.
- 캐싱은 중간에 있는 데이터 추가/ 삭제가 빈번하게 발생할 수 있어 배열을 사용하면 시간복잡도가 크게 증가한다.
- 이를 해결하기위해 연결리스트를 도입, 하지만 연결리스트는 key-value 타입이 아니기 때문에 탐색에 O(n) 이 발생
- 그렇기 때문에 동시에 Dictionary를 도입하여 탐색을 O(1)로 만든다.
4. 메모리를 과도하게 사용하지 않도록 자동 제거 정책이 있다.
- limitation을 넘어갈 경우 적은 용량(cost)의 데이터 부분 부터 삭제한다.
- 삭제될 수 있는 하위 구성요들은 NSDiscardableContent 프로토콜을 채택하여 캐시 제거 동작을 향상 시킬 수 있다.
- 기본적으로 캐시의 NSDiscardableContent 객체는 내용이 삭제될 경우 자동으로 제거되지만 이 자동 제거 정책은 변경할 수 있다.
- NSDiscardableContent 객체가 캐시에 저장되면 캐시는 삭제 명령 수행시 discardContentIfPossible()이 호출된다.
- NSDiscardableContent 객체의 삭제는 연결리스트를 통해서 삭제가 진행되는데 이 연결리스트는 cost로 정렬된 연결 리스트다. head부터 삭제가 진행되기 때문에 결과론적으로는 적은 cost의 데이터부터 삭제되게 된다.
- 의도는 명확히 알 수 없지만 용량이 큰 데이터의 경우 다시 계산되어야 할 때의 비용이 높기 때문에 적은 용량의 캐싱데이터부터 삭제하는 건 아닐까
Topics
Managing the Name
// 캐시의 이름
var name: String
Managing Cache Size
// 캐시가 가질 수 있는 최대한의 객체 수
var countLimit: Int
// 객체를 제거하기 전에 캐시가 보유할 수 있는 최대 비용
var totalCostLimit: Int
Managing Discardable Content
// 캐시가 내용이 삭제된 NSDiscardableContent를 자동으로 제거할지의 여부
var evictsObjectsWithDiscardedContent: Bool
// 클래스의 객체의 하위 구성 요소가 사용되지 않을 때 삭제되어도 된다면 이 프로토콜을 채택함으로써 응용 프로그램의 메모리 사용 공간을 줄일 수 있다.
protocol NSDiscardableContent
Managing the Delegate
// 캐시의 위임자
var delegate: NSCacheDelegate?
// NSCache의 위임자 객체는 이 프로토콜을 채택한다.
이 프로토콜을 채택하면 캐시에서 객체가 추출되거나 제거될 때의 작업들을 특수화할 수 있다.
protocol NSCacheDelegate
Getting a Cached value
// 주어진 Key과 연결된 값을 반환
func object(forKey: KeyType) -> ObjectType?
Adding and Removing Cached Values
// 캐시에 주어진 키와 그에 대응되는 값을 저장
func setObject(ObjectType, forKey: KeyType)
// 비용을 명시하여 값을 저장.
func setObject(ObjectType, forKey: KeyType, cost: Int)
// 캐시에 주어진 키에 대응되는 값을 제거
func removeObject(forKey: KeyType)
// 캐시 비움
removeAllObjects()
URLCache
An object that maps URL requests to cached response objects.
class URLCache : NSObject
정의
URL 요청으로 캐시된 response를 매핑해주는 캐시 객체
특징
1. 메모리와 디스크 상 복합 캐시를 제공할 수 있으며 두 부분의 크기를 제어할 수 잇다.
2. Thread Safe
- 동시에 여러 실행 컨텍스트에서 안전하게 호출될 수 있지만 동일한 요청에 대한 응답을 읽고 쓸 때 race condition이 발생할 수 있다
- 그럴경우 URLCache의 서브클래스는 스레드로부터 안전한 방식으로 재정의된 메서드를 구현해야한다.
Topics
Getting and setting shared cache
// 공유 URL 캐시 인스턴스
class var shared: URLCache
Creating a new cache object
// 지정된 메모리 및 디스크 용량과 디렉토리를 사용하여 URL 캐시 객체를 생성합니다.
init(memoryCapacity: Int, diskCapacity: Int, directory: URL?)
Getting and storing cached objects
// 지정된 URL 요청에 대해 캐시에 저장된 URL 응답을 반환
func cachedResponse(for: URLRequest) -> CachedURLResponse?
// 스레드 안전한 방식, 데이터 작업에 대한 캐시된 URL 응답을 가져와 제공된 완료 핸들러에 전달한다.
func getCachedResponse(for: URLSessionDataTask, completionHandler: (CachedURLResponse?) -> Void)
// 지정된 요청에 대해 캐시된 URL 응답을 저장
func storeCachedResponse(CachedURLResponse, for: URLRequest)
// 스레드 안전한 방식, 지정된 데이터 작업에 대해 캐시된 URL 응답을 저장합니다.
func storeCachedResponse(CachedURLResponse, for: URLSessionDataTask)
Removing cached objects
// 지정된 URL 요청에 대한 캐시된 URL 응답을 제거
func removeCachedResponse(for: URLRequest):
// 스레드 안전한 방식, 지정된 데이터 작업에 대한 캐시된 URL 응답을 제거
func removeCachedResponse(for: URLSessionDataTask)
// 지정된 날짜 이후에 캐시된 모든 응답을 제거
func removeCachedResponses(since: Date):
// 캐시에 저장된 모든 URL 응답을 제거
func removeAllCachedResponses():
Getting and setting on-disk cache properties
// 디스크 캐시의 현재 크기(바이트)입니다.
var currentDiskUsage: Int:
// 디스크 캐시의 용량(바이트)입니다.
var diskCapacity: Int:
Getting and setting in-memoery cache properties
// 메모리 캐시의 현재 크기(바이트)
var currentMemoryUsage: Int
// 메모리 캐시의 용량
var memoryCapacity: Int
Cache storage policies
// CachedURLResponse 객체에서 사용되는 캐싱 전략을 지정하는 상수
enum URLCache.StoragePolicy
allowed:
캐시된 응답을 디스크와 메모리에 모두 저장할 수 있는 정책입니다.
기본적으로 이 정책이 사용되며, 캐시된 응답을 디스크에 저장해 나중에 사용하도록 허용합니다.
memoryOnly:
캐시된 응답을 메모리에만 저장할 수 있는 정책입니다.
디스크에 저장되지 않으며, 앱이 종료되면 캐시된 응답이 제거됩니다. 즉, 응답이 일시적으로만 사용되도록 하고 싶을 때 적합합니다.
notAllowed:
캐시된 응답을 저장하지 않는 정책입니다.
이 정책을 사용하면 캐시에서 응답을 전혀 저장하지 않으며, 항상 새롭게 요청해야 합니다.
코드
실제 코드는 여기를 참고 바란다.
GitHub - yongbeomkwak/Cache: iOS Cache 관련 레포
iOS Cache 관련 레포 . Contribute to yongbeomkwak/Cache development by creating an account on GitHub.
github.com
참고
URLCache | Apple Developer Documentation
An object that maps URL requests to cached response objects.
developer.apple.com
NSCache | Apple Developer Documentation
A mutable collection you use to temporarily store transient key-value pairs that are subject to eviction when resources are low.
developer.apple.com
NSCache
Content Similar Posts Comments
caution-dev.github.io
NSCache vs URLCache
안녕하세요. 그린입니다🟢 이번 포스팅에서는 오랜만에 간단한 주제인 NSCache와 URLCache의 차이를 알아보려고 합니다🙌 그럼 본론으로 바로 들어가시죠! 우선 둘다 Cache라는 개념에서는 동일할
green1229.tistory.com
이미지 캐시 처리와 NSCache
이미지 캐시 처리를 해봅시다! 최근 iOS 프로젝트를 하다가 이미지 캐싱 작업을 하기 위해 NSCache를사용했습니다! 자세히 모르는 상태에서 이미지 캐싱 부분을 구현하긴 했는데... 그래도 알고 넘
beenii.tistory.com
Does the different way of handling key between NSMutableDictionary and NSCache (copy vs. retain) result in different consequence
I studied the differences between NSMutableDictionary and NSCache. One of them was that NSMutableDictionary copy its keys and NSCache just retain it as a strong reference. In addition, I found that...
stackoverflow.com
'iOS > UIKit' 카테고리의 다른 글
Auto Layout이란 (0) | 2024.12.15 |
---|---|
특정 시기에 아이콘 자동 변경하기 (0) | 2024.10.26 |
키보드 반응하기 (1) | 2024.10.13 |
UIHostingController (0) | 2024.10.12 |
UIEditMenuInteraction (3) | 2024.10.12 |