SwiftUI 프로젝트에서 이미지 캐시를 구현해보았다.
최근까지 SwiftUI로 채팅 서비스를 구현하는 프로젝트를 진행했다. 텍스트 형태의 채팅 메시지뿐만 아니라 이미지를 최대 5장까지 업로드해서 이미지 뷰어로 보여줄 수 있어야 했다. 채팅 전송 시점에 서버에 저장한 이미지 주소를 소캣 채널을 통해 전달 받아 보여줘야 했다. 채팅 방의 업로드된 이미지 조회만 아니라 앱 전반적으로도 유저의 프로필을 보여주거나, 특정 뷰에서 서버의 이미지가 필요한 경우가 많았다. 앱에서 이미지를 보여줄 때마다 서버에 요청을 보내 이미지 데이터를 조회하는 것은 너무나도 고역이었다. 아니 앱에게 너무 몹쓸 짓을 하는 것 같았다. 이미지 캐싱을 왜 적용해야 했을까? 이미지 캐싱을 적용해야겠다고 마음 먹은건, 채팅 방을 개발하면서 메모리 사용 내역을 보고 난 이후였다. 이미지가 업로드 된 채팅 방에서 스크롤을 한 번 했는데, 스크롤을 할 때마다 네트워크 요청이 들어가서 메모리 사용량이 급격하게 100MB씩 치솟는 걸 보았다. 스크롤을 계속 할 수록 메모리 사용 그래프는 우상향을 그렸다. 정말 나쁜 앱이라고 생각했다. 불러 올 이미지가 많았다면 아마 앱이 터졌을 수도 있다. Kingfisher와 같은 URL 기반으로 이미지 캐싱을 적용해주는 라이브러리 도입을 제일 먼저 고려했다. UIKit 프로젝트를 할 때부터 애용했던 라이브러리라 사용법도 익숙했고 당연히 이미지 캐싱이 잘 될거라고 생각했는데, 'Kingfisher는 어떻게 이미지 캐싱을 적용하는 걸까?'는 질문은 크게 던져보지 않았던 것 같다. 그래서 이번 프로젝트에서는 이미지 캐싱을 담당하는 모듈을 구분하여 직접 만들어보기로 했다. 이미지 캐싱 방식을 서칭해보았다. 이미지 캐싱은 붙은 단어 그대로 '이미지'를 '캐싱'하는 것이고, 캐싱은 자주 쓸 것 같은 데이터를 어떤 공간에 임시적으로 저장해두고 활용하는 것을 의미한다. 그래서, 이미지 캐싱은 자주 쓸 것 같은 이미지 데이터를 특정 공간에 임시적으로 저장해두고 필요할 때마다 조회해서 사용하고, 필요 없으면 지우는 작업을 의미했다. 내가 이해한 바를 정리해 보면, 이미지 캐싱을 위해서는 이미지 데이터 저장을 위한 어떤 공간이 필요하고 임시적으로 저장하는 것이기 때문에 저장 만료 시간에 대한 반영과 계산이 필요하고 (캐싱 전략) 이미지 데이터를 저장하고 이미지 데이터를 불러오고 이미지 데이터를 삭제하는 작업이 반영되어야 한다. 저장 공간 결정