빠른 흐름
csharp
AsyncOperationHandle<GameObject> handle = enemyRef.LoadAssetAsync<GameObject>();기본 흐름
- Addressables를 실제로 쓸 때 가장 중요한 것은 "로드"보다 "언제 해제할 것인가"입니다. 이 시스템은 참조 카운트와 핸들을 통해 수명주기를 관리하므로, 로드만 하고 release를 잊으면 메모리 흐름이 바로 흐려집니다.
LoadAssetAsync<T>는 에셋 자체를 로드하고,InstantiateAsync는 인스턴스 생성까지 포함합니다. 여러 번 생성할 프리팹이면 asset을 한 번 로드해 두고 직접 instantiate하는 방식이 맞을 때도 있고, 수명주기를 단순화하려면InstantiateAsync가 더 낫기도 합니다.AsyncOperationHandle은 단순히 "결과를 담는 변수"가 아니라 로드 작업과 수명주기를 대표하는 핸들입니다. 완료 여부, 진행률, 결과, release 시점이 여기에 묶입니다.- 씬과 프리팹, UI 리소스, 캐릭터 스킨처럼 자산 종류에 따라 해제 정책이 달라집니다. 한 번만 잠깐 쓰는 자산은 사용 직후 해제하고, 세션 내내 쓰는 공용 자산은 더 오래 유지할 수 있습니다.
- 그래서 Addressables 도입 시에는 API 자체보다 "누가 로드하고, 누가 release하고, 같은 자산을 여러 시스템이 공유할 때 정책을 어떻게 맞출 것인가"를 먼저 정하는 편이 좋습니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 에셋 하나 비동기 로드 | LoadAssetAsync<T> + 핸들 저장 |
| 로드와 인스턴스 생성을 함께 | InstantiateAsync |
| 로드한 에셋/핸들 해제 | Addressables.Release(...) |
InstantiateAsync로 만든 인스턴스 해제 | Addressables.ReleaseInstance(...) |
| 씬 전환 시 자산 정리 | 씬별 release 정책 명시화 |
| 비교 | 더 잘 맞는 쪽 | 이유 |
|---|---|---|
| 에셋 공유 로드 vs 즉시 인스턴스 생성 | LoadAssetAsync / InstantiateAsync | 재사용할 원본 자산인지, 바로 배치할 인스턴스인지 다름 |
| 단기 사용 자산 vs 세션 공용 자산 | 즉시 release / 장기 보유 후 명시적 해제 | 소유권과 해제 지점이 다름 |
| 핸들 기반 관리 vs 주소 문자열 남용 | 핸들 저장 | 해제와 중복 로드 추적이 쉬움 |
주의할 점
Addressables에서 가장 흔한 실수는 로드만 하고 Release를 잊는 것입니다. 핸들을 들고 있으면 소유권 추적이 쉬워지지만, 에셋 자체나 인스턴스를 기준으로 해제하는 API도 있으므로 "어떤 형태로 해제할지"를 로드 시점에 같이 정해 두는 편이 안전합니다.
csharp
// ❌ 로드만 하고 해제 지점을 정하지 않음 — 참조 카운트 누수 위험
Addressables.LoadAssetAsync<GameObject>("Enemy");
// ✅ 핸들 저장 → 사용 완료 시 Release
private AsyncOperationHandle<GameObject> _handle;
async void LoadEnemy()
{
_handle = Addressables.LoadAssetAsync<GameObject>("Enemy");
await _handle.Task;
// ... 사용
}
void OnDestroy()
{
Addressables.Release(_handle); // 사용이 끝난 로드 핸들 해제
}
// ❌ InstantiateAsync로 만든 인스턴스를 Destroy만 함
// → Addressables 인스턴스 수명주기와 참조 카운트가 어긋날 수 있음
// 필요하면 ReleaseInstance(handle 또는 instance)까지 같이 설계참고 링크
3 sources