[UE] GetTransientPackage()

이 글에서는 "Transient Package가 왜 존재하는지", "Outer로서 어떤 의미를 가지는지", "GC 및 수명과 어떤 관계가 있는지", "실무에서 언제 쓰고 언제 피해야 하는지" 정리한다.
목차
GetTransientPackage()
Transient UObject의 소속, 수명
Unreal Engine에서 UObject를 다루다 보면 한 번쯤은 다음과 같은 코드를 마주치게 된다.
UObject* Obj = NewObject<UObject>(GetTransientPackage());
겉보기에는 단순히 “임시 객체를 만드는 방법”처럼 보이지만,
GetTransientPackage()는 UObject 저장 모델, 경로 시스템, GC 설계와 연결된 개념이다.
Transient Package란 무엇인가?
GetTransientPackage()는 엔진이 전역으로 유지하는 단 하나의 UPackage를 반환한다.
이 패키지는 디스크에 저장되지 않는(Runtime-only) UObject들의 최상위 컨테이너 역할을 한다.
Transient Package는 “저장되지 않는 UObject들을 위한 합법적인 소속(Outer)”이다.
/** Transient package. */
static UPackage* GObjTransientPkg = nullptr;
UPackage* GetTransientPackage()
{
return GObjTransientPkg;
}
Unreal의 핵심 전제: UObject는 반드시 “어디엔가” 속해야 한다
(Outer, Name) → Full Path Name
예를 들면:
- /Game/Items/Sword.Sword
- /Engine/Transient.MyTempObject
즉,
- UObject는 반드시 Outer 트리에 매달려야 하고
- 이 Outer 트리의 최상단은 항상 UPackage다
문제는 여기서 발생한다.
런타임 전용 객체는 어디에 속해야 할까?
- 에셋 패키지(/Game/...) → ❌ 저장/쿠킹 대상이 됨
- 맵 패키지(/Game/Maps/...) → ❌ 에디터/PIE 오염 가능
- 월드/레벨 → ❌ 수명 결합 위험
이때 등장하는 해결책이 바로 Transient Package다.
Transient Package의 역할 정리
Transient Package는 다음 목적을 동시에 만족한다.
1) UObject 경로 시스템을 유지한다
- UObject는 여전히 유효한 PathName을 가진다
- 리플렉션, 디버깅, 로깅, FindObject 계열 API와 정상적으로 호환된다
2) 저장/쿠킹 파이프라인에서 분리된다
- 디스크에 저장되지 않는다
- 에셋 레지스트리, 패키지 로딩, 쿠킹 대상이 아니다
3) 엔진 전반에서 “공용 임시 루트”로 사용된다
- 엔진이 단 하나만 생성
- 모든 임시 UObject가 동일한 기준을 공유
Transient ≠ GC 안전
UObject* Temp = NewObject<UObject>(GetTransientPackage());
위 코드에서 Temp는 GC로부터 보호되지 않는다.
중요한 사실
- Outer는 수명을 보장하지 않는다
- Unreal GC는 Reachability(도달 가능성) 기반이다
- Transient Package는 Root Object가 아니다
즉, 다음 중 하나라도 없으면 객체는 GC 대상이다.
- 다른 살아있는 UObject가 UPROPERTY()로 참조
- FGCObject를 통한 참조 등록
- AddToRoot() (주의해서 사용)
- GameInstance / Subsystem / Manager 객체가 멤버로 보유
Transient Package는 “저장 안 됨”을 보장할 뿐, “살아 있음”을 보장하지 않는다.
언제 GetTransientPackage()를 써야 하는가
1. 런타임 전용 데이터 객체
- UI ViewModel (MVVM)
- 임시 계산 결과
- 테스트/디버그용 UObject
- 세션 간 유지될 필요 없는 상태 객체
단, 반드시 다른 UObject가 UPROPERTY로 보유해야 한다.
2. 특정 월드에 종속되면 안 되는 객체
- 월드 전환 시 유지돼야 하거나
- 반대로, 월드 수명과 무관해야 하는 객체
이 경우 Transient가 적절한 선택이 될 수 있다.
언제 쓰면 안 되는가
1. 월드/레벨 수명과 함께 가야 하는 객체
다음과 같은 경우라면 Transient는 잘못된 선택이다.
- 특정 월드에서만 의미 있음
- 레벨 언로드 시 반드시 정리돼야 함
- PIE 재시작 시 초기화돼야 함
이런 경우는 보통:
- UWorld
- ULevel
- UGameInstance
- USubsystem
- AActor
를 Outer로 두는 것이 맞다.
2. “저장 안 되게 하려고” Transient만 쓰는 경우
저장/직렬화 제어는 Outer 하나로 끝나지 않는다. 실무에서는 보통 다음이 함께 필요하다.
- RF_Transient 플래그
- SaveGame 로직에서의 명시적 제외
- 에디터 트랜잭션(Undo/Redo) 제어
| 본질 | 플래그 (속성) | 소속(Outer) 패키지 |
| 해결하는 문제 | 직렬화/저장 | 패키지 경로/소속 |
| GC 영향 | ❌ 없음 | ❌ 없음 |
| Outer 대체 가능 | ❌ | ⭕ |
| 저장 방지 범위 | 객체 단위 | 패키지 단위 |
| 주 용도 | “이 객체는 저장하지 마라” | “이 객체는 어디에도 속하지 않는다” |
RF_Transient = “저장 금지 표시”
Transient Package = “저장 대상이 아닌 소속”
내부 구현 관점에서 본 GetTransientPackage()
GetTransientPackage()는 단순한 getter처럼 보이지만, 실제 의미는 다음과 같다.
- 엔진 초기화 시 정확히 한 번 생성
- 전역으로 공유되는 유일한 Transient Package
- 모든 임시 UObject가 일관된 기준으로 소속됨
이 일관성이 깨지면:
- 경로 충돌
- GC 추적 문제
- 에디터/리디렉션/디버깅 이상 동작
같은 문제가 발생할 수 있다.
그래서 엔진은 직접 패키지를 만들게 하지 않고,
반드시 GetTransientPackage()를 통해 접근하도록 설계되어 있다.
GetTransientPackage()를 사용하기 전 체크리스트
- 이 객체는 저장되면 안 되는가?
- 이 객체의 수명은 무엇과 동기화돼야 하는가?
- GC에서 살아남을 참조 경로가 있는가?
- 에디터(PIE, Undo/Redo)에서 부작용은 없는가?
이 질문에 명확히 답할 수 없다면,
Transient Package는 아직 이 객체의 올바른 Outer가 아닐 가능성이 크다.
마무리
GetTransientPackage()는 단순한 “임시 객체용 함수”가 아니다.
- 저장 모델을 이해하지 못하면 오용하기 쉽고
- GC 모델을 이해하지 못하면 크래시로 이어지며
- 수명 설계를 잘못하면 구조가 무너진다
'⭐ Unreal Engine > UE 개념정리' 카테고리의 다른 글
| [UE] GetDefault, GetMutableDefault (0) | 2025.10.15 |
|---|---|
| [UE] Actor와 Component, RegisterComponentWithWorld 사운드 문제 (2) | 2025.08.31 |
| [] ㅍㅈ Livecode Tech Interview (0) | 2024.02.21 |
| [Codility] ㅍㅈ 코딩테스트 (0) | 2024.02.07 |
| [UE] GameMode / GameState / Player State / Player Controller / Pawn (1) | 2023.12.31 |
댓글
이 글 공유하기
다른 글
-
[UE] GetDefault, GetMutableDefault
[UE] GetDefault, GetMutableDefault
2025.10.15 -
[UE] Actor와 Component, RegisterComponentWithWorld 사운드 문제
[UE] Actor와 Component, RegisterComponentWithWorld 사운드 문제
2025.08.31 -
[] ㅍㅈ Livecode Tech Interview
[] ㅍㅈ Livecode Tech Interview
2024.02.21 -
[Codility] ㅍㅈ 코딩테스트
[Codility] ㅍㅈ 코딩테스트
2024.02.07