게임을 개발하는 데 있어 리소스 관리 중요성은 몇 번을 말해도 부족하지 않다. 게임 리소스를 어떻게 관리하느냐에 따라 메모리 관리부터 게임 용량, 로딩 시간 등 다방면에 영향을 끼치기 때문이다. 그렇다면 리소스 관리는 어떻게 하는 게 좋을까?
이 의문을 해결하기 위해 유니티테크놀러지코리아의 오지현 에반젤리스트가 NDC에 강연자로 나섰다. 본 세션에서는 유니티 에반젤리스트로서 유니티 리소스와 에셋번들을 어떻게 사용하는 게 제일 좋을지 오지현 에반젤리스트가 12년간 쌓아온 노하우를 공유하는 자리가 됐다.
유니티 리소스를 관리하는데 필수라 여겨지는 에셋번들이란 과연 뭘까? 그리고 어떻게 사용하면 좋을까? 일선에서 유니티 엔진을 다뤄온 오지현 에반젤리스트의 강연을 통해 그 궁금증을 해결해보자.
■ 에셋번들 왜 사용해야 할까?
에셋번들은 어플리케이션의 초기 인스톨 용량을 줄이거나 런타임 메모리를 줄이는 용도로 사용된다. 그렇기에 모바일에선 에셋번들을 필수적으로 사용한다. 모바일은 PC에 비해 하드웨어 용량과 메모리가 적기 때문이다. 특히, 에셋번들을 잘못 사용하면 모바일에선 메모리 문제가 발생하기 십상이다.
에셋번들 말고는 리소스 폴더를 이용해 리소스를 관리하는 방식이 있다. 이 방법은 리소스 폴더에 에셋들을 전부 넣고 필요할 때 하나씩 빼서 쓸 수 있어 간편하다. 하지만 리소스 폴더를 이용하는 방법은 프로토타이핑 시점에나 적합하다. 우선 리소스 폴더에 모든 에셋을 모아놓다 보니 에셋 관리 난이도가 증가할 뿐더러 메모리 관리 역시 복잡해지고 많은 에셋으로 인해 어플리케이션 시작 시간과 빌드 시간이 증가하기 때문이다.
이 중에서 오지현 에반젤리스트는 특히 메모리 관리 때문에라도 리소스 폴더 사용은 권장하지 않는다 밝혔다.
"리소스 폴더를 사용할 경우 현재 씬에 쓰이지 않는 오브젝트라도 메타 데이터를 전부 메모리에 띄우기 때문에 에셋이 많을수록 기본적인 메모리 사용량이 계속 증가하게 된다. 이는 아무것도 없는 빈 씬에서도 마찬가지로, 이 때문에 특히 모바일에선 리소스 폴더를 사용하는 건 권장하지 않는다."
이때 등장하는 게 바로 에셋번들이다. 에셋번들은 서버에 에셋을 전부 올려두고 이후 앱이 실행되면 에셋번들을 통해 오브젝트를 로드하는 방식으로 인스펙터로 원하는 리소스를 분류할 수 있다. 하지만 에셋번들을 사용하면서도 알아야 할 게 있다. 바로, 에셋번들 묶음 분류 방식이다.
■ 에셋번들 분류법, 너무 작거나 혹은 너무 많거나
우선 에셋번들 분류법이 왜 필요한지 알아야 할 필요가 있다. 우선 리소스는 하나로만 움직이는 경우가 거의 없다. 오브젝트의 경우 마테리얼이 있고 그 마테리얼에 텍스쳐가 붙는다. 만약 마테리얼만 로드하면 텍스쳐가 없어서 깨지게 되는 경우가 생기기에 에셋번들 어떻게 쓰는 게 가장 효과적일지 알아야 한다.
이쯤에서 '그렇다면 모든 리소스를 에셋번들로 올려놓고 한 번에 로드하면 되지 않느냐?'는 궁금증이 들 수 있는데, 이 경우 통째로 메모리에 에셋번들이 올라가게 돼 메모리 문제가 발생할 수 있어 위험하다.
그래서 메모리가 낭비되는 문제를 해소하기 위해 저마다 다양한 에셋번들 분류법을 사용한다. 물론 에셋번들의 수를 몇 개로 묶는지는 회사마다, 프로젝트마다 다르기에 정석이란 건 없다. 그렇기에 오지현 에반젤리스트는 대표적인 분류법 3가지만을 소개했다.
첫 번째로 논리적인 개체 별 분류법이 있다. 이 방식은 기능적인 부분 개념으로 에셋들은 분류한다. 이를테면 UI의 텍스쳐와 레이아웃 등 게임하면서 수시로 쓰이는 리소스가 대표적이다. 어디서, 어떻게 에셋이 필요한지 명확히 알 때 가장 추천하는 분류법이다.
두 번째는 타입 별 분류법으로 비슷한 리소스끼리 번들에 묶는 방식이다. 오디오트랙이라거나 언어 파일이 대표적인데 쉐이더는 예외로 친다. 쉐이더는 플랫폼별 호환성이 다르기에 이 분류법에는 어울리지 않는 리소스다. 또한, 엔진 업데이트에 영향을 받지 않는 리소스의 경우에도 이 같은 분류법을 이용하는 게 좋다.
세 번째는 동시에 사용되는 콘텐츠 별로 그룹화하는 방식이다. 이 방식은 한 판, 한 씬마다 고유한 아트, 캐릭터, 사운드가 나오는 레벨 기반 게임에 적합한 방식으로 씬을 통째로 번들로 묶는 식이다.
■ 에셋번들, 어떻게 써야 좋을까?
이처럼 모바일 앱 개발에 필수적인 에셋번들. 그렇다면 도대체 에셋번들은 어떻게 쓰는 게 좋을까? 보통 에셋번들은 WWW.LoadFromCacheOrDownload와 다운로드핸들러 코드를 통해 사용한다.
WWW.LoadFromCacheOrDownload는 다운로드 후 캐싱하고 그대로 저장하는 방식이다. 이 경우에는 압축된 번들을 풀어서 캐싱하기에 사용하기 편리하지만, 그에 따른 단점도 있다. 다운로드 받는 중 파일을 통째로 메모리에 올려놔 메모리 문제가 발생할 수 있다.
그래서 WWW.LoadFromCacheOrDownload를 사용할 때는 에셋번들을 각각 최대 10메가로 나눠서 사용하길 권장한다. 그렇지 않을 경우 모바일에선 이른바 메모리가 터지는 경우가 발생할 수 있다. 이런 문제를 해결하기 위해 최근 유니티에서는 UnityWebRequest 사용을 권장하고 있다. UnityWebRequest의 경우 메모리 문제를 해결할 수 있다.
다운로드핸들러는 에셋번들을 캐싱하고 해당 에셋번들과 기기에 있는 파일 정보를 대조해 버전이 구버전이면 업데이트를 진행하고 같을 경우 생략하는 방식으로, 유니티에서는 다운로드핸들러를 사용하길 권장하고 있다.
그렇다면 사용한 후 에셋번들은 어떻게 해야 할까. 흔히 화장은 하는 것보다 지우는 게 중요하다고 한다. 에셋번들 역시 마찬가지다. 로드하는 것보다 그 후 해제하는 게 더 중요하다. 앞서 에셋번들을 통째로 올렸다가 로드할 때 잘못하면 메모리가 폭발하는 문제가 발생한다고 했는데, 에셋번들을 해제하지 않을 경우에도 메모리에 계속 쌓여 메모리 이슈가 발생할 수 있다. 이를 방지하기 위해선 에셋번들을 해제해야 한다.
예를 들어 특정 씬의 에셋들을 로드하고 제거한다고 할 때 씬 A에서 씬 B로 넘어갈 경우, 필요가 없어진 씬 A 번들을 해제해야 한다. 하지만 여기서도 문제가 있다. 타이밍이다. 완벽하게 B로 넘어가면서 필요가 없어진 A를 해제하면 좋겠지만, 보통은 B가 로드된 후에 A를 삭제한다. 근데 이럴 경우 메모리에 A와 B가 모두 적재돼 메모리 이슈가 발생할 수 있다.
이런 문제를 해결하기 위해 보통 씬 A와 B 사이에 용량이 적은 씬 C를 임의로 넣는 방법을 사용한다. 이렇게 해서 메모리 문제를 살짝 비켜 나갈 수 있다. 보통 이런 씬 C는 게임의 결과창이나 로딩 화면 등의 용도로 활용된다.
■ 에셋번들 압축법, 통째로 압축하던가 일부를 압축하던가
에셋번들은 빠른 전송과 초기 인스톨 용량을 줄이기 위해 다양한 압축방식을 제공하고 있다. 크게 2가지로 NONE으로 할 경우 LZMA 방식으로 압축한다. 이 방식은 에셋을 통째로 압축하는데 LZ4 대비 압축 효율이 높아 에셋번들에 큰 오브젝트가 들어가는 상황에 적합하다. 압축 효율이 높은 만큼, 중국이라거나 동남아처럼 무선 네트워크 환경이 좋지 않은 곳에서 사용하기에 적합한 방식이다.
또 다른 방식은 청크베이스 압축 방식이다. 특정 단위로 쪼개서 압축하는 이 방식은 LZ4로 압축돼 압축 효율은 NONE 방식보다 낮지만, 빠르게 압축을 해제할 수 있는 게 장점이다. 그래서 대부분 청크베이스 압축 방식을 사용한다.
■ 에셋번들, 앞으로는 더 쉬워집니다
현재 유니티테크놀러지코리아에서는 새롭게 에셋번들 팀을 꾸려서 기존에 에셋번들을 새롭게 개발하고 있다. 필수랄 수 있는 에셋번들을 좀 더 사용하기 쉽게 한다는 게 그들의 목표다. 물론 이에 대해 오지현 에반젤리스트는 "여러 부분에서 개선됐지만, 아직 개발 중이기에 앞으로 소개할 툴들을 쓰기 전에 꼭 백업하길 추천한다"고 덧붙였다.
우선 에센번들 그래프 툴이 개발 중이다. 이 툴은 비쥬얼 기반의 툴로 아티스트나 기획자도 에셋번들을 좀 더 쉽게 쓸 수 있도록 고안됐으며, 그 외 워크플로우 관리에도 탁월할 것으로 예상된다.
이어서 에셋번들 브라우저 툴에 대한 설명이 이어졌다. 그 동안 에셋번들을 사용하면서 에셋번들에 어떤 리소스가 포함됐는지 보기 어렵다는 의견들이 많았다. 불가능한 건 아니었지만 확인하기 번거로운 부분이 있었는데 유니티 5.6부터는 에셋번들 브라우저 툴로 에셋번들을 좀 더 쉽게 확인할 수 있다.
에셋번들에 포함된 에셋들이 메모리를 얼마나 사용하는지 좀 더 편하게 볼 수 있는 메모리 프로파일러 확장판도 추가됐다. 확장판에서는 오브젝트의 레퍼런싱 관계를 좀 더 쉽게 파악할 수 있다.
끝으로 오지현 에반젤리스트는 에셋 핫리로드라는 기능을 추가할 예정이라 밝혔다. 현재 개발 중인 이 기능은 에셋번들을 통해 에디터로 수정한 내용을 바로 모바일 기기에 적용하는 기능이다. 원래라면 에디터로 앱을 수정할 경우 새로 빌드를 해서 기기에 설치해야 하는데 에셋 핫리로드 기능이 추가되면 앱을 내리고 새로 업데이트 버전을 올릴 필요가 없어서 빠른 작업이 가능해진다.
이 같은 다양한 기능들은 현재까지 약 70% 정도 개발이 진행됐다. 이미 많은 부분이 개선됐고 API도 사용하기 편해진 에셋번들에 대해 오지현 에반젤리스트는 "앞으로는 에셋번들을 더 편하게 쓸 수 있도록 계속 개선하는 게 목표"라 말하며 강연을 끝마쳤다.