언리얼 UObject 동작 원리 정리 (CDO, Reflection, GC, Serialization)
언리얼 C++ 개념 학습 노트. 강의 2.1~2.7 개념만. UObject가 왜 이렇게 도는지 헷갈릴 때 다시 보기.
왜 Unreal C++인가
Native C++은 메모리 직접 관리라 최적화엔 좋지만 잘못 쓰면 누수/크래시. C# 같은 후발 언어는 GC, 리플렉션을 언어에 내장. 언리얼은 매크로 문법으로 Native C++에 이 기능들을 얹음. 이게 적용된 클래스가 UObject, 이 문법이 Unreal C++.
핵심 함정: UObject가 아니면 Content Browser에 인식 안 됨. 일반 C++ 클래스(부모 None)는 에디터가 못 봄. UCLASS() + .generated.h가 있어야 UObject.
CDO (Class Default Object)
엔진 초기화 시 클래스마다 CDO 생성. CDO는 생성자 로직대로 초기화된 템플릿 개체. 개체를 새로 만들 때 처음부터 만드는 게 아니라 CDO를 복제 → 메모리 효율.
가장 중요한 포인트: 생성자는 PIE 누르기 전에 이미 한 번 호출됨(CDO 생성 시점). PIE 누르면 또 호출(실제 개체). 그래서 생성자에 무거운 로직이나 월드 의존 로직 넣으면 안 됨. 초기화는 Init() 같은 이벤트 함수에서. CDO는 GetDefault()로 언제든 접근 가능.
이벤트 함수와 Super 호출
특정 이벤트 발생 시 자동 호출되는 함수가 이벤트 함수(생성자, Init, Shutdown 등). override 시 Super::함수() 먼저 호출해야 함. 엔진 엔지니어가 작성한 코드가 먼저 돌아야 엔진 루틴이 깨지지 않음.
방어 코드: check / ensure / IsValid
- check(조건): 거짓이면 크래시. checkf()로 메시지 추가
- ensure(조건): 거짓이면 알리지만 크래시는 안 냄(복구 로직 필요 지점 찾을 때). ensureMsgf()로 메시지
- IsValid(): UObject 포인터가 유효한지. nullptr만 검사하면 Pending Kill/GC 대상을 못 거름. 셋 다 체크해줌
판단 기준: "false일 수 있고 그땐 그냥 넘어가면 됨" → 예외처리(if). "false일 수가 없음, 즉시 알려야 함" → checkf(). checkf 잘 쓰면 if 줄어서 코드 깔끔.
Reflection (리플렉션)
런타임에 자기 자신을 조사하는 기능. GC, 리플리케이션, 시리얼라이즈의 근간. UObject만 가능.
용어: 멤버 변수 = 속성(Property, UPROPERTY()), 멤버 함수 = 함수(Function, UFUNCTION()). 이 매크로가 런타임 에디터에 메타데이터 전달.
- StaticClass(): 컴파일 타임 클래스 정보
- GetClass(): 런타임 클래스 정보
- 다형성 상황(부모 포인터가 자식 가리킴)에서 둘이 다를 수 있음
- 이름으로 속성/함수 찾아 호출 가능(FindPropertyByName, FindFunctionByName, ProcessEvent)
객체 생성은 new가 아니라 NewObject<>() 써야 함. 언리얼 메모리 체계에 등록돼야 하기 때문.
Garbage Collection (Mark-Sweep)
동작: 루트에서 시작 → 참조하는 개체 Mark → Mark된 개체가 참조하는 것 또 Mark 반복 → Mark 안 된 것(아무도 참조 안 함) 회수(Sweep).
GUObjectArray: 모든 UObject 정보를 담은 전역 자료구조. RootSet 플래그(참조 없어도 회수 안 됨), Garbage 플래그(회수 예정). GCCycle 주기마다 몰아서 회수.
로우 포인터 문제 해결 정리:
- 메모리 누수 → GC가 자동 해결
- 댕글링 포인터 → IsValid()로 검사
- 와일드 포인터 → UPROPERTY() 붙은 속성은 자동 nullptr 초기화
가장 중요한 함정: UObject 포인터 멤버에 UPROPERTY()를 안 붙이면 GC가 추적을 못 함. 참조로 안 잡혀서 살아있어야 할 개체가 회수되거나, 초기화가 안 됨. UObject 멤버엔 UPROPERTY() 습관.
Serialization (직렬화)
오브젝트 그래프(개체가 다른 개체를 속성으로 참조하는 관계)를 바이트 스트림으로 변환. 역은 Deserialization. 용도: 게임 상태 저장/복원, 블루프린트 복붙, 네트워크 위치 재현.
API: 아카이브 클래스 + << 연산자. 메모리(FMemoryReader/Writer), 파일(FArchiveFileReader/Writer), Json(별도 모듈).
USTRUCT: 언리얼 구조체 매크로. 리플렉션 제한적(UPROPERTY만 됨, UFUNCTION 안 됨). 직렬화 제공. 스택 메모리라 NewObject 불가. 데이터 저장/전송용으로 많이 씀.
UObject 직렬화는 Serialize(FArchive&) override해서 Super 호출 후 Ar << 멤버. Json은 텍스트라 읽기 쉽고 가볍지만 타입이 적고(문자/숫자/불리언/널/배열/오브젝트) 극한 효율은 불가. 웹 통신 사실상 표준.
'학습 > Unreal' 카테고리의 다른 글
| 언리얼 Actor와 컴포넌트 구조 정리 (컴포지션, UPROPERTY, 이벤트 함수, Movement) (0) | 2026.04.30 |
|---|---|
| 언리얼 실무 도구 정리 (Interface, Delegate, FString, 컨테이너) (0) | 2026.04.28 |
| [실습] Pawn 클래스 3D캐릭터 만들기 (0) | 2026.04.16 |
| PlayerController 알아보기 / Enhanced Input System을 활용한 입력 매핑 구현하기 (0) | 2026.04.15 |
| Character 클래스를 활용한 캐릭터 구현하기 (0) | 2026.04.15 |
