[Unity] Addressable Asset을 왜?

안녕하세요, 더핑크퐁컴퍼니 Unity 개발자 쿠마(Kuma) 입니다. 이글은 Unity의 Addressable Asset 도입하는 과정 중, 도입 이유에 관한 글 입니다.

[Addressable Asset Unity 공식 소개 페이지]

들어가기에 앞서

이 글은 다음과 같은 사전 지식이 있으면 훨씬 이해하기 편하며, 어느 정도 지식이 있다는 가정 하에 진행 되어 일부 간략한 설명이나 생략되는 내용들이 있을 수 있습니다.

  • Unity의 Asset 개념
  • Unity의 예약 폴더인 Resources 폴더와 Resources.Load() 기능
  • Unity의 Asset Bundle

개요

Addressable Asset을 간단하게 정리 하자면, Unity에서 사용되는 Asset 관리 시스템이라고 할 수 있습니다.

즉, Asset Bundle + 번들 관리 시스템(번들 버전 관리, 의존성 관리)으로 생각하시면 됩니다.

Addressable Asset을 도입하기 전에는 어떤 방식으로 Asset을 관리하였으며, 무슨 이유로 사용하게 되었는지에 대해서 이야기해보려 합니다.

Addressable Asset 이전의 Asset 관리 시스템

Unity의 Asset은 프로젝트 내에서 사용되는 모든 항목을 의미합니다. 여기에는 모델링, 텍스쳐, 오디오 파일 등 지원되는 리소스 파일은 물론 애니메이션(컨트롤러, 클립 등), GameObject 등 Unity 내에서 제작된 항목들이 포함됩니다.

프로젝트 내에서 사용되는 항목이기에 관리하는 시스템이 있는 것은 물론, 프로젝트 외부에 제공하는 것도 가능 합니다. 대표적으로 Asset Store와 Unity Package 등이 있겠습니다. 물론 Asset Bundle도 이러한 Asset의 제공 방식 중 한 가지입니다.

그렇다면 이러한 Asset은 어떤 식으로 관리가 될까요? Drag & Drop 으로 Hierarchy에 끌어다 쓰거나 참조를 걸어 사용하는 기본 방식을 제외한다면 다음과 같은 방법들이 있습니다.

  • Resources 폴더의 이용
  • Asset Bundle

두 방식 모두 Asset을 특정 경로에 생성(혹은 Built-in) 시켜 놓고 Load API를 통해 사용한다는 과정은 동일합니다. 주요 내용이 아니므로, 간략하게만 보고 넘어 가도록 하겠습니다.

1. Asset이 위치한 path 준비
- Resources 폴더 방식: 예약 폴더 (/Resources)에 Asset을 생성한다.
- Asset Bundle: 번들 내부에 Asset path를 준비해놓는다.

2. Asset의 path를 이용하여 Resources.Load() API로 로드한다.

3. 로드한 Asset을 사용(인스턴스 생성, 참조 등)

Resources 폴더 이용

Asset을 관리하는 방법 중 Hierarchy 참조 방식을 제외 한다면 Resources 폴더를 이용하는 방식이 가장 보편적이고 많이 알려진 방법일 것입니다.

특징
- Hierarchy와 인스펙터에 참조되어 있지 않더라도 Runtime 로드가 가능
- 별도의 사전 부가 과정이 없다 (예: CDN, Asset bundle export 등)

제한 사항
- 앱 패키징 시 Built-in되어 앱 설치파일(.apk, .ipa등) 용량 증가
- 앱 실행 시 인덱싱 과정이 있어, 실행 시간 증가
- Built-in되기 때문에 교체 시 앱 업데이트 필요

사용법은 간단하지만 남용하게 되면 앱 품질에 영향을 줄 수 있으므로 주의가 필요합니다. 물론, 무조건 쓰지 말라는 것은 아닙니다.

스마트스터디 인터랙티브 앱에서는 다음과 같은 기준을 충족한다면 Resources 폴더 방식을 채택하여 사용하고 있습니다.

  1. 앱을 실행하고 이용하는데 필수적인 리소스인가?
  2. 교체가 빈번하지 않거나, 원격으로 업데이트 할 필요가 없는가?

위 기준에 준하지 않는다면 사용을 지양하지만, 간단한 사용 방법과 편의성 때문에 종종 사용하고 있습니다.

Asset Bundle 방식

Resources 폴더 방식의 제한 사항들을 보완하기 위해 채택하는 방법입니다. Asset Bundle에 Asset을 포함시켜 배포(혹은 Built-in)하여 로드하는 방식인데, 그렇다면 Asset Bundle은 무엇일까요?

이름 그대로 Asset의 Bundle(묶음)입니다.

[Asset Bundle 구조]

Resources 폴더의 하위에 있는 특정 폴더를 압축한 것과 유사하다고 할 수 있습니다. 그렇기 때문에 Resources 폴더에서 로드하는 것처럼 번들에서 로드하면 Asset을 사용할 수 있게 됩니다.

번들로 만들어(Export 과정 필요) 외부로 배포할 수 있기 때문에 Resources 폴더 방식을 이용할 수 있지만, 제한 사항에서는 비교적 자유로워집니다.

하지만, 이러한 번들이 좋기만 한 것은 아니었습니다.

  • 번들 의존성 관리
  • 번들 버전 관리의 까다로움
  • 번들에 들어가 있는 Asset Path 변경 공수

위의 단점들에 대한 이해를 돕기 위하여 몇 가지 사례를 들어 설명해 보겠습니다.

  1. 번들 의존성 관리
[중복된 Asset 을 가지고 있는 서로 다른 번들]

위 그림처럼 중복된 리소스를 참조하는 Asset이 있고, 서로 다른 번들에 있다면 각 번들에 리소스를 모두 포함시켜야 합니다. 즉, 리소스의 중복이 생기게 되는 것이죠. 그렇지 않을 경우 개발자가 의존성 관리를 별도로 해주어야 합니다.

예) Image A를 먼저 로드한 후, 참조하고있는 번들을 사용

2. 번들 버전 관리

- 라이브된 A앱은 0.1 버전의 번들을 사용 중
- B앱부터는 0.2 버전의 번들을 사용해야 함
- B앱과 0.2 버전의 번들을 릴리즈 함
- A앱 사용 중, 업데이트를 받지 않은 사람들이 0.2 버전의 번들 사용 불가

위와 같은 상황이 발생할 경우, A앱에서 0.1 이상 번들을 사용하지 못하게 하거나 0.2에서 하위 호환성을 제공하는 등의 복잡한 관리 상황이 발생할 수 있습니다.

3. 번들에 들어있는 Asset Path 변경의 번거로움

[번들에서 Asset 을 로드할 때 Path를 이용]

번들 내부 Asset의 Path는 문자열 형태로 들어가있습니다. 이를 외부 코드에서 로드하여 사용하는데, 만약 번들 내부의 Asset path가 변경될 경우 외부 코드에서도 변경된 Path를 사용하도록 작업을 해주어야 합니다.

그래서 Addressable Asset을 도입한 이유는?

Asset Bundle만 사용하다가 Addressable asset을 도입하게 된 이유는 아래의 주요한 단점들 때문이었습니다.

위에서 말했듯, Addressable Asset = Asset Bundle + 관리 시스템이라고 정리할 수 있습니다. 그렇다면 Asset Bundle의 단점을 그대로 가지고 가는 게 아닌가? 하는 의문이 있을 수 있습니다. 관리 시스템이 붙으면서 생긴 구조가 이를 해결해주었습니다.

  1. 번들 의존성 관리: Group과 Label (Key)

Group은 Bundle 단위입니다. Group 단위로 Bundle 이 생성됩니다.
Group 내 Asset에는 각각의 ID(Key) 와 같은 부류라는 GameObject 의 Tag와 같은 개념인 Label을 기입할 수 있습니다. 이로 인하여 다음과 같이 구조가 변경되었습니다.

[번들에서 Asset을 사용하기 위한 간단한 구현 흐름]
[Addressable asset의 번들 구조]

그림에서 비교되듯이, 구현 흐름이 간단해졌습니다. Addressable asset은 번들의 Download & Load 단계에서, 사용할 Asset들의 의존성(설계상 Label이나 Key로 제대로 기입되었다는 게 전제가 됩니다.)을 API에서 일괄 관리 해줍니다. Label(Key) 관리만 해준다면 기존 Asset Bundle의 의존성에 의한 중복이나 수동 관리는 해결할 수 있었습니다.

2. 번들 버전 관리의 까다로움 : Catalog

Catalog란, Asset의 Address(Group, Label 정보 포함)와 Asset의 매핑 정보가 기재된 파일입니다. 이러한 Catalog 덕분에 1번의 단점 해결은 물론 번들 자체의 버전도 관리가 됩니다. Catalog는 Addressable의 번들과 함께 생성되는 녀석인데 Catalog의 버전이 붙어서 생성됩니다.
(자세한 내용은 다음 글에…)

[Catalog에 기재된 번들을 읽는 구조]

앱을 배포할 때 앱이 사용할 Catalog의 버전이 함께 기재되기 때문에, 저장소에 사용할 Catalog와 번들만 존재한다면 새롭게 배포하는 Catalog와 번들 때문에 문제가 생길 여지는 사라지게 됩니다.

[Catalog 하위 호환성을 보장하는 방식]

3. 번들에 들어 있는 Asset Path 변경 공수 : Address (참조)

기존 번들의 Asset들은 Path가 통짜로 들어가서 외부 코드에서 사용하고 있을 때 Path 값을 똑같이 맞춰줘야 했습니다. 즉, 한쪽이 변경된다면 다른 쪽도 바꿔줘야 해서 번거로웠습니다. 번들의 Asset 이름만 변경되더라도 Path가 변경되기 때문에 생각보다 빈번하게 일어날 수 있는 일입니다.

Addressable Asset의 이름에서 볼 수 있듯이 Address (참조) 방식을 사용합니다. 그렇다면 무엇을 참조하는 것이냐? 바로 Asset의 path입니다.

[Asset 참조]

위 그림의 설명에서 볼 수 있듯이, Path 를 참조하는 값만 처음에 맞춰서 작업해 놓는다면 번들 내부의 Path 가 바뀌더라도 기존 번들 방식에서처럼 코드를 바꾸는 번거로움은 사라집니다.

마치며

이렇게 Asset Bundle의 단점을 보완하면서 공수도 줄일 수 있기 때문에 Addressable Asset을 사용하는 이점이 있습니다. 또한 Unity에서도 Asset Bundle에 대한 업데이트 대신 Addressable Asset을 대체 기술로 내세우기 때문에 도입하게 되었습니다.

다음에는 이러한 특징들을 실제로 어떻게 사용하는지와 Remote Bundle 방식 도입에 관하여 글을 써볼 예정입니다.

긴 글 읽어주셔서 감사합니다.

--

--