2026-05-18 TIL (59일차)
2026-05-18 TIL (59일차)
[TIL] 언리얼 엔진: 하드 레퍼런스와 소프트 레퍼런스의 완벽 이해 및 활용
언리얼 엔진으로 개발을 하다 보면 가장 빈번하게 겪는 최적화 이슈 중 하나가 메모리 낭비와 초기 로딩 속도 저하다. 이 문제의 90%는 에셋을 참조하는 방식, 즉 레퍼런스(Reference) 구조에서 발생한다. 오늘은 메모리 관리의 핵심인 하드 레퍼런스와 소프트 레퍼런스의 차이를 정리해 본다.
1. 하드 레퍼런스 (Hard Reference) 란?
하드 레퍼런스는 객체가 다른 객체를 메모리 상에서 직접적(포인터)으로 꽉 쥐고 있는 상태를 말한다.
동작 방식
- “연쇄 로딩(Cascading Load)”: A라는 객체가 메모리에 로드될 때, A가 하드 레퍼런스로 참조하고 있는 B도 무조건 함께 메모리에 로드된다.
- 만약 B가 C를, C가 D를 하드 레퍼런스로 가지고 있다면? A 하나만 불렀을 뿐인데 A, B, C, D가 줄줄이 소시지처럼 모두 메모리에 올라가 버린다.
C++ 코드 예시
1
2
3
4
5
6
// 하드 레퍼런스 (강한 참조)
UPROPERTY(EditAnywhere)
UTexture2D* ItemIcon;
UPROPERTY(EditAnywhere)
TSubclassOf<AActor> BossMonsterClass;
언제 사용할까?
- 해당 객체가 존재할 때 ‘반드시’ 존재해야만 하는 필수적인 에셋
- 예: 캐릭터의 메인 스켈레탈 메시(Skeletal Mesh), 기본 장착 무기, 즉각적으로 반응해야 하는 기본 이펙트.
- 장점: 이미 메모리에 올라와 있으므로, 접근 속도가 매우 빠르고 null 체크 후 즉시 사용할 수 있다.
- 단점: 불필요한 상황에서도 메모리를 차지한다. (예: 인벤토리 UI를 열지도 않았는데, UI 위젯이 모든 아이템 아이콘을 하드 참조하고 있다면 게임 시작부터 아이콘 수백 개가 메모리를 갉아먹는다.)
(에디터에서 특정 에셋 우클릭 -> Reference Viewer (레퍼런스 뷰어)를 열어보면 하드 참조로 인해 엮인 메모리 연쇄 로드 트리를 확인할 수 있다.)
2. 소프트 레퍼런스 (Soft Reference) 란?
소프트 레퍼런스는 객체의 실제 메모리가 아니라, “그 객체가 어디 있는지 주소(경로, String)만” 들고 있는 상태다.
동작 방식
- A가 B를 소프트 레퍼런스로 가지고 있다면, A가 메모리에 로드되어도 B는 로드되지 않는다. A는 그저 B의 경로만 알고 있을 뿐이다.
- B가 실제로 필요한 순간에만 개발자가 코드를 통해 명시적으로 로드(동기/비동기)하여 메모리에 올린다.
C++ 코드 예시
1
2
3
4
5
6
// 소프트 레퍼런스 (약한 참조)
UPROPERTY(EditAnywhere)
TSoftObjectPtr<UTexture2D> ItemIcon; // 실제 에셋(오브젝트)
UPROPERTY(EditAnywhere)
TSoftClassPtr<AActor> BossMonsterClass; // 클래스 타입
언제 사용할까?
- “언젠가 쓰일 수도 있지만, 지금 당장 무조건 필요한 것은 아닌” 무거운 에셋
- 예: 인벤토리의 아이템 아이콘들, 특정 페이즈에만 스폰되는 거대 보스 몬스터, 방대한 오픈월드의 특정 구역 에셋, UI/사운드 파일들.
- 장점: 초기 로딩 속도를 엄청나게 줄여주고, 사용하지 않는 메모리를 극적으로 절약할 수 있다.
- 단점: 실제로 에셋을 띄우기 위해 로딩하는 시간(Delay)이 발생한다. 따라서 렉(Hitch)을 방지하기 위해 주로
FStreamableManager를 이용한 비동기 로딩(Async Loading) 작업이 수반되어야 한다.
하드 레퍼런스 vs 소프트 레퍼런스 요약
| 구분 | 하드 레퍼런스 (Hard Reference) | 소프트 레퍼런스 (Soft Reference) |
|---|---|---|
| 저장 형태 | 메모리 포인터 직접 참조 | 에셋 경로(주소) 문자열 |
| 로딩 시점 | 부모 객체가 로드될 때 즉시 동반 로드 | 개발자가 원할 때 명시적 로드 (동기/비동기) |
| 메모리 점유 | 항상 점유함 (무거움) | 필요할 때만 점유함 (가벼움) |
| 접근 속도 | 즉시 사용 가능 (가장 빠름) | 로딩 후 사용 가능 (로딩 딜레이 존재) |
| C++ 타입 | UObject*, TSubclassOf<T> | TSoftObjectPtr<T>, TSoftClassPtr<T> |
| 적합한 용도 | 캐릭터 본체, 필수 컴포넌트, 주무기 | 수백 개의 인벤토리 아이콘, 특수 몬스터, 맵 에셋 |
This post is licensed under CC BY 4.0 by the author.