NSCache를 사용하여 데이터를 기기 캐시 메모리 안에 임시 저장하여 자원을 효율적으로 관리할 수 있다.
보통 NSCache를 사용할 때, Singleton으로 CacheManager 클래스를 만들어 하나의 객체에서 NSCache의 과업을 수행한다.
나는 개인 프로젝트로 OpenAPI로부터 이미지 데이터를 받아와서 메모리 / 디스크 캐시에 저장하고 다시 파일을 로드하는 과정을 시도했다.
나는 이미지 캐시에 대한 Singleton 객체를 만들게 되면 여러 스레드에서 한 개의 객체에 NSCache 작업을 수행하게 되어 크래시가 발생할 것을 우려하여 각 이미지 View Struct 안에 MVVM형식(데이터 바인딩)을 취하는 방식으로 이미지 캐시 구현을 시도했다.
결과는 데이터가 저장되고, 호출되는 과정에서 문제가 발생했다. 메모리에 캐시데이터를 제대로 로드할 수 없었다.
원인은 공식문서에 있었다.
NSCache를 구현하려고 하는 View는 LazyVGrid의 셀에 해당되는 View이다.
다음은 LazyVGrid에 대해 애플 개발자 공식문서 중 일부를 발췌한 것이다.
Unlike a lazy grid, which creates child views only when SwiftUI needs to display them, a regular grid creates all of its child views right away. - Apple Developer Document: LazyVGrid
LazyVGrid는 필요할 때만 자식뷰를 생성하고 필요하지 않으면 생성하지 않는다. 즉, LazyVGrid에 보여지지 않는 자식 뷰들은 메모리에 올라가지 않았다는 뜻이다.
NSCache가 사용되는 구조체 View가 LazyVGrid에 사용되는 View이고, NSCache는 시스템 메모리를 너무 과하게 소비하지 않기 위해서 자동 삭제 정책(auto-eviction policies)을 유지한다. NSCache는 데이터 자동 삭제시 NSDiscardableContent 프로토콜을 따르는데, 이에 대한 설명을 공식문서에서 발췌해보자면 다음과 같다.
By default, NSDiscardableContent objects in a cache are automatically removed if their content is discarded, although this automatic removal policy can be changed. - Apple Developer Document: NSCache
NSDiscardableContent의 프로토콜 내용을 일부 변경해서 사용할 수 있지만, 기본적으로 NSCache가 사용되는 컨텐츠가 소멸된다면 캐시 데이터도 소멸된다는 뜻이다.
나는 LazyVGrid에 사용될 하위 뷰에서 NSCache를 구성했고, 이를 통해 전체적인 시스템이 안정화 되길 원했지만 기능 자체가 의미없게 되어버린 결과를 가져왔다.
결국 CacheManager 클래스를 구현했다. 하지만 Singleton 객체를 사용해서 앱의 캐시 메모리 관리를 할 경우 문제가 없을지 궁금해서 Cache Set / Load 과정을 테스트 코드로 작성하여 실험해본 결과, 다행히도 크래시는 발생되지 않았다.
'실수' 카테고리의 다른 글
NSCache 파일 key - value 설정 실수 (0) | 2023.06.19 |
---|---|
의도치않은 ObservedObject 객체 초기화 실수 (0) | 2022.11.07 |
Button 컴포넌트 사용에 대한 실수(완성도 높이기) (0) | 2022.10.31 |