오늘은 게임의 메모리를 아끼고 빌드 용량을 최적화하기 위해 사용하는 자원 관리 시스템 Addressable에 대해 정리해보겠습니다.
어드레서블은 에셋의 위치에 관계없이 에셋에 부여된 고유 주소를 갖고 비동기적으로 로드 및 해제할 수 있게 해주는 시스템입니다.
기존의 [SerializeField] 방식은 연결된 모든 프리팹과 SO 데이터가 씬 로드 시 메모리에 한 번에 강제로 적재되는 방식으로 당장 쓰지 않는 데이터도 용량을 차지하는 문제가 있었습니다.
이를 해결하기 위해 에셋의 주소를 부여하여 특정 필요한 순간에 메모리를 불러오는 방식을 위해 어드레서블을 사용하고 있습니다.
어드레서블은 다음의 흐름으로 구현을 진행합니다.

1 ~ 4단계
Package 설치
Settings 생성: 어드레서블 기본 설정 파일들을 자동 생성
Asset Addressable: 특정 에셋의 Addressable 체크박스를 선택하거나 Inspector필드에 드래그 등으로 Addressable 할당이 가능합니다.
Grop: 필요에 따라 동일한 성격에 맞게 Group화 하여 분류할 수 있습니다.
5 단계
게임 실행 파일과 별개로 에셋들을 어드레서블 데이터로 빌드하는 단계입니다.
이 단계를 거치면 유니티가 에셋들을 카탈로그와 에셋 번들 파일로 빌드를 수행합니다.
6 ~ 7 단계
게임이 실제로 켜진 후 코드가 동작하는 런타임 영역입니다.
플레이 도중 스크립트 코드를 통해 지정했던 주소 이름을 사용해 비동기로 에셋을 불러옵니다.
이후 사용이 끝난 에셋을 메모리에서 해제해야 합니다.
<style>
using System.Collections
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AddressLoader : MonoBehaviour
{
// 에셋의 주소 이름을 텍스트로 받기
[SerializeField] private string address;
private AsyncOperationHandle<GameObject> handle;
private IEnumerator Start()
{
// 인스펙터에 적어둔 주소를 가진 프리팹을 메모리에 로드
// handle: 얼마나 로드되었는지, 성공 혹은 실패했는지 결과물이 무엇인지 등의 정보를 포함
handle = Addressables.LoadAssetAsync<GameObject>(address);
yield return handle;
if (handle.Status == AsyncOperationStatus.Succeeded)
Instantiate(handle.Result, transform.position, Quaternion.identity);
}
private void OnDestroy()
{
// handle은 아래와 같이 메모리 해제시에도 사용
if (handle.IsValid())
{
Addressables.Release(handle);
}
}
}
</style>