본문 바로가기
iOS/iOS

이미지 캐시 처리와 NSCache

by 헤콩 2021. 6. 23.
반응형

이미지 캐시 처리를 해봅시다!

최근 iOS 프로젝트를 하다가 이미지 캐싱 작업을 하기 위해 NSCache를사용했습니다! 자세히 모르는 상태에서 이미지 캐싱 부분을 구현하긴 했는데... 그래도 알고 넘어가면 더 좋을 것 같아서 NSCache에 대해 간단히 알아보았습니다!

 

 

일단 제가 Image Cache in Swift - 이미지 캐싱 사용해보기 와, NSCache란? 라는 게시글을 참고해서 구현한 부분은 아래와 같습니다.

 

1. 이미지 캐시 작업을 위한 싱글톤 클래스 ImageCacheManager를 생성합니다.

 

2. 이미지를 가져오기 전에, 캐싱된 내용에 해당 이미지가 존재하는지 먼저 검사합니다.

  • 만약 캐시된 이미지에 해당 이미지가 존재한다면? 그 이미지를 사용하고 여기서 작업을 마칩니다.
  • 만약 캐시된 이미지에 해당 이미지가 없다면? 아래 과정 (2번부터) 을 진행합니다.

3. URLSessiondataTask를 통해 비동기처리로 이미지를 가져와서 사용합니다.

4. 그리고 ImageCacheManager (캐시) 에 가져온 이미지를 저장합니다.

 

 

 

 

이미지 캐시 처리를 하면 어떤 점이 좋을까?

고화질, 고용량의 이미지를 계속해서 다운로드하게 되면 사용자의 네트워크 리소스를 계속 소모하는 것은 물론, 다운로드가 완료되기까지 걸리는 시간도 낭비됩니다. 따라서 어플리케이션에서 다운받은 이미지를 캐싱하여 저장해두면, 한 번 다운받았던 이미지는 나중에 별도의 리소스를 소모할 필요 없이 빠르게 보여줄 수 있게 됩니다.

 

 

iOS 에서 이미지 캐시 처리를 하는 데에는 2가지 방법이 있습니다.


1. Memory Caching

  • 어플리케이션의 메모리 영역의 일부분을 Caching에 사용하는 것
  • (단점) 어플리케이션이 종료되어 메모리에서 해제되면 이 영역에 있던 리소스들은 OS에 반환되면서 Memory Caching 되어 있던 리소스들은 사라짐

2. Disk Caching

  • 데이터를 파일 형태로 디스크에 저장하는 것
  • (단점) Disk Caching이 반복적으로 발생하면 어플리케이션이 차지하는 용량이 커진다.
  • (장점) 어플리케이션을 껐다 켜도 데이터가 사라지지 않는다.
  • (예시) 카카오톡에서 이미지나 동영상을 디바이스에 저장하지 않더라도 눈으로 보기 위해서는 파일을 다운로드 받아야 하는데, 이때 다운로드 받은 파일들이 Disk Caching되어 앱을 종료했다가 실행해도 볼 수 있다.

 

이중에서도 NSCache는 Memory Caching에 주로 사용되는 클래스입니다.

 

 

 

그래서 NSCache가 뭐냐?!

class NSCache<KeyType, ObjectType>: NSObject where KeyType: AnyObject, ObjectType: AnyObject

 

NSCache는 주로 Memory Caching에 사용되는 클래스로, 메모리에서 해제될 때 자동으로 캐시된 내용이 제거됩니다. 만약 메모리 자원이 부족하게 되면 삭제 대상이 되기도 하죠.  NSCache는 Thread-Safe 하기도 합니다. 따라서 여러 스레드에서 접근할 때에도 Cache에 lock을 걸어줄 필요가 없습니다.

그리고 Key-Value 형태의 데이터를 임시로 저장하는 데에 사용할 수 있는 가변 컬렉션입니다. 
그런데 저는 Key-Value 형태로 사용되는 거면 도대체 NSDictionary와 뭐가 다른건지 궁금했습니다. 그래서 알아봤더니…

NSCahce는 NS (Mutable) Dictionary와 다르게, 그 안에 들어있는 Key 객체를 복사하지 않습니다. NSDictionary의 경우, Key에서 사용되는 모든 객체는 NSCopying 프로토콜을 지원하기 때문에 Key로 사용되는 모든 객체가 복사되어 사용되는데요! 그 이유는 NSDictionary의 동작 방식에 있습니다.

  • 만약 NSMutableDictionary를 사용할 때, NSMutableString 타입의 Key를 사용해서 value를 저장한다고 가정합니다. 그리고 만약 NSMutableString이 NSCopying을 따르지 않고, Key를 retain시킨 채 사용한다고 한다면, 나중에 NSMutableString 타입의 Key가 수정되었을 때 그에 해당하는 value를 찾을 수 없게 될 것입니다. 따라서 NS (Mutable) Dictionary는 NSCopying을 따르게 됩니다.


네... 그래서 NSDictionary는 Key 객체를 왜 복사해야하는지 이해했는데...... 도대체 NSCache가 Key 객체를 복사하지 않아도 되는 이유는 왜 아무도 안알려주는거죠???????? 아무리 자료를 찾아봐도 NSCache의 Key는 Strong Reference 이다. 또는, NSCache는 NSCopying 프로토콜을 따를 필요가 없다. 또는, NSCache의 Key는 NSDictionary와 다르게 복사되어 사용되지 않는다!!!!!! 라고!!! 밖에!! 안써있어!!!! 으악!!😂😂😂 도대체 왜일까요??? 왜??? 누가 좀 알려주세요ㅠㅠㅠㅠㅠ엉엉ㅠㅠㅠ

 

일단 NSDictionary와 다르게 NSCache Linked List와 Dictionary 자료구조를 함께 사용합니다. 캐싱 과정에서 중간에 있는 값을 추가하거나 삭제하는 과정이 빈번하게 발생하기 때문에 링크드 리스트를 사용하면 데이터를 앞으로 당기거나 뒤로 미는 작업이 매우 용이해지죠. 그리고 Key로 데이터를 접근 할 때는 Dictionary를 활용해서 접근하면 O(1)로 빠르게 탐색할 수 있다고 해요.

 

 

 

NSCache의 주요 프로퍼티

  • var name: String 캐시의 이름
  • var countLimit: Int 캐시가 가질 수 있는 최대한의 객체 수
  • var totalCostLimit: Int 객체를 제거하기 전에 캐시가 보유할 수 있는 최대 비용
  • func object(forKey: KeyType) -> ObjectType? 주어진 Key와 연결된 값을 반환합니다.
  • func setObject(ObjectType, forKey: KeyType) 캐시에 주어진 Key와 그에 대응되는 값을 넣습니다.
  • func removeObject(forKey: KeyType) 캐시에 주어진 Key에 대응되는 값을 제거합니다.
  • func removeAllObjects( ) 캐시를 비웁니다.

 

 

 


네.. 이렇게 NSCache에 대해서 알아보았는데요….
결국 제가 궁금해 하던 것 (왜 NSCache는 Key 복사가 필요 없는가?) 에 대한 명확한 답을 아직 얻지 못해서 시원하지 못한 상태로 이렇게 게시글을 마무리 하게 되네요..ㅠㅠㅠㅠ 시간될 때 더 찾아보고 글을 보충해보겠습니당... 혹시 아시는 분은 댓글로 알려주신다면 정말정말 감사하겠습니다!!

 

 

 

 

반응형

댓글