회사 프로젝트에 어드레서블(Addressable)을 적용하기 위해 공부하고 있다.
보통 "어드레서블을 적용하면 CDN으로부터 에셋 번들을 원격으로 다운받을 수 있다." 정도로만 알고 있었는데 공부하면 할수록 생각보다 복잡한 시스템이라고 느껴진다.
내가 구현해야 되는 기능은 다음과 같다.
쉽게 말해 빌트인 방식으로 배포하되 스토어 업데이트 없이 핫픽스도 가능해야 한다~ 라는 것이다.
사실 여기서부터 생각을 잘못 해버려서 한 이틀정도 헤맨 것 같다.
요구사항이 언뜻 보면 내장과 원격 다운로드를 동시에 지원해야 되는 것처럼 보인다.
하지만 아무리 찾아봐도 어드레서블은 그런 기능을 제공하지 않는다. (당연히 관련 자료도 찾을 수 없었다.)
이런저런 테스트를 해보며 결국 깨달은 점은 CDN에서 이를 컨트롤 할 수 있다는 것이었다.
그리고 그 해답의 핵심은 카탈로그(Catalog)였다.
어드레서블 시스템이 번들을 관리하기 위한 메타데이터라고 봐도 무방할 것 같다.
어드레서블로 관리되는 모든 번들에 대한 정보가 들어 있으며, 특히 '번들을 어디로부터 로드할 것인가'에 대한 정보가 들어있어 확실하게 이해할 필요가 있었다.
번들을 빌드하면 기본적으로 로컬에 카탈로그가 생성된다. (Library 폴더 하위에 생성된다.)
이는 에디터 환경에 주로 쓰이고 경우에 따라 인터넷 연결이 없는 경우에도 사용된다고 한다.
Addressable Asset Settings를 보면 'Build Remote Catalog'가 있는데 이를 체크하면 카탈로그의 사본을 생성할 수 있다.
이 카탈로그의 사본은 반드시 에셋 번들과 함께 배포되어야 한다. (이유는 차차 이해하게 된다.)
카탈로그를 이해하는데 반드시 선행되는게 바로 경로 설정이다.
Build path는 빌드 결과물이 저장되는 경로, Load path는 결과물을 불러올 경로를 뜻한다.
경로는 Profile에서 수정이 가능하며, 간단히 local과 remote로 구분지어 설명하겠다.
어드레서블 시스템에서 경로를 설정하는 경우는 두가지이다.
첫째는 Asset Group, 둘째는 Asset Settings다.
Asset Group에서 설정하는 경로는 번들 자체가 저장되고 불러질 경로를 뜻한다.
즉 remote로 설정됐다면 번들을 프로젝트 외부에 저장하고 필요할 때 다운받겠다는 의미이고, local은 그 반대이다.
Asset Settings에서 설정하는 경로는 카탈로그의 사본이 저장되고 불러질 경로를 뜻한다.
마찬가지로 remote로 설정됐다면 카탈로그를 프로젝트 외부에 저장하고 필요할 때 다운받겠다는 의미이고, local은 그 반대이다.
번들이 로드되는 과정을 표현한 다이어그램을 먼저 보자. (이 과정을 깨닫는데 이틀이 걸렸다.)
다이어그램의 내용을 구체적으로 풀어서 설명하면,
어드레서블이 빌드됐을 때 설정된 카탈로그의 로드 경로로부터 사본을 복사하여 캐싱한다.
이 경로가 remote라면 CDN에서 최신 카탈로그를 다운받을 것이다.
캐싱된 카탈로그는 번들을 어디에서 로드할 것인지에 대한 정보를 담고 있다.
그 경로가 remote라면 우선 캐싱된 번들이 있는지 확인하고, 다음으로 번들 업데이트 여부를 확인한다.
만약 번들에 수정사항이 있다면 다운로드한다.
반대로 경로가 local이면 내장된 번들을 로드한다.
윈도우 기준
카탈로그는 'C:/User/UserName/AppData/LocalLow/[Company]/[Project]'에 캐싱되어 사용된다.
번들은 외부에서 다운받는 경우 'C:/User/UserName/AppData/LocalLow/Unity'에 캐싱된다.
카탈로그를 CDN에서 로드하게 설정하면 CDN의 카탈로그를 수정하여 외부에서 번들을 컨트롤 할 수 있을 것이다.
내장된 에셋 번들은 StreamingAssets 폴더 하위에 저장되는데 외부에서 다운받은 에셋 번들은 캐시 디렉토리에 캐싱된다.
즉 번들 자체를 수정하는게 아니고 외부에서 다운받은 번들로 대체하는 것이기 때문에 해당 번들에 대해서는 용량을 약 두배로 사용하게 된다.
예를 들면,
오른손잡이 캐릭터가 1.0 버전에서 실수로 왼손잡이로 설정되어 배포됐다.
이를 수정하기 위해 바로 1.1 버전을 배포하자니 스토어 검수 기간이 문제다.
그래서 캐릭터 설정이 포함된 에셋 번들을 CDN에 업로드하여 원격으로 수정되도록 했다.
그러면 사용자의 디바이스 내 StreamingAssets 폴더 하위에는 왼손잡이 데이터가, 캐시 디렉토리에는 오른손잡이 데이터가 들어있는 것이다.
그리고 2주 뒤 1.1 버전에 다시 수정된 번들을 내장해서 배포한다.
이렇게 되면 캐시 디렉토리의 핫픽스 데이터는 더미가 된다.
두가지 해결방안이 떠오른다.
첫째, Catalog가 수정되는 시점에 자동으로 캐싱된 번들을 삭제하는 메커니즘을 도입한다.
어드레서블에서 제공하는 API 중에 CheckForCatalogUpdates 메서드가 있다.
이는 캐싱된 카탈로그와 로드 경로의 카탈로그를 비교해서 수정사항이 있는지 확인하는 메서드이다.
카탈로그가 수정된다면 새로운 번들을 다운받을 것이기 때문에 이전에 받은 캐시들은 지워도 된다.
캐싱된 번들은 ClearDependencyCacheAsync 메서드로 삭제할 수 있다.
CheckForCatalogUpdates 메서드를 사용하기 위해선 사전작업이 필요하다.
반드시 카탈로그를 수동으로 업데이트하게 해야 한다.
둘째, 사용자가 직접 캐시를 삭제할 수 있도록 인터페이스를 제공한다.
실제로 다른 게임에서 이미 제공하고 있는 기능이다.
몇 가지 여쭤보고 싶은게 있습니다. 그럼 처음 외부에서 다운받은 에셋 번들은 이후 StreamingAssets 폴더 하위에 저장되게 되고 새로 외부에서 다운받은 에셋 번들은 캐시 디렉토리에 캐싱되는 것이라고 이해하면 될까요? 아니면 Local은 StreamingAssets 폴더 하위, Remote는 캐시 디렉토리라고 이해하면 되는 걸까요??