Unreal Engine

[UE] 언리얼 엔진의 GC

programmer-faust 2025. 8. 28. 22:17
  • 순서
    1. 가비지 컬렉션 GC란?
    2. GC의 동작 원리
    3. GC가 보는 참조와 보지 못하는 참조
    4. 객체 생명주기 관련 포인트
    5. GC로 인해 자주 겪는 문제
    6. C++의 GC와 UE의 GC 차이
  • 가비지 컬렉션 GC란?
    1. UObject 기반 객체들의 메모리를 자동으로 정리하는 도달성 기반의 마크-앤-스윕 시스템이다.
    2. UObject들 간의 레퍼런스를 따라 도달 가능한 객체는 살리고, 도달 불가능한 객체는 수거함.
    3. 도달성이란?
      • 특정 객체가 아직 사용중이라고 간주할 수 있는지를 뜻함.
      • 도달 가능한 객체: 현재 실행 중인 코드에서 경로를 따라 접근할 수 있는 객체 > 살려둠
      • 도달 불가능한 객체: 어느 곳에서도 참조하지 않는 객체 > 필요없는 메모리로 판단 > 수거대상
  • GC의 동작 원리
    1. 루트(Root) 수집
      • 엔진이 시작.유지하는 지속적 객체들, AddToRoot()로 보호된 객체들, GC 컬렉터가 직접 참조하고 있는 것들이 루트로 간주됨
    2. 마크(Mark) 단계
      • 루트에서 출발하여 UPROPERTY()로 선언된 포인터나 FGCObject::AddReferencedObjects등으로 보고된 참조들을 따라가며 도달 가능한 모든 객체를 표시함
    3. 스윕(Sweep) 단계
      • 도달 불가능한 객체들은 파괴 절차에 들어감. 이때 MarkPendingKill() 처리를 거치고, BeginDestroy() > FinishDestroy() 같은 파괴 콜백이 실행되며 실제 메모리 해제는 엔진 내부 절차를 거쳐 이뤄짐
    4. 정리 완료
      • 파괴가 끝난 객체들은 UObject 레지스트리에서 제거되고 메모리에서 해제됨
  • GC가 보는 참조와 보지 못는 참조
    1. 자동 추적
      • UPROPERTY()로 선언된 UObject*, TArray<UObject*>등은 리플렉션 시스템이 스캔해서 GC가 인식함.
    2. 자동 추적되지 않는 경우
      • 일반 C++ 멤버 포인터(UObject*이지만 UPROPERTY() 없음), STL컨테이너는 기본적으로 GC가 보지 못함 > 객체가 수거되어 댕글링 포인터/크래시 발생 가능
    3. 대체 수단(GC에 참조를 알려주는 방법)
      • AddToRoot() / RemoveFromRoot() 객체를 루트로 올려 GC에서 보호함.(장기간 유지할 때 사용)
      • FGCObject를 상속해서 AddReferencedObjects(FReferenceCollector&) 구현 - Non-UObject 매니저가 UObject 포인터를 소유할 때 사용
      • TWeakObjectPtr<T> - 약한 참조(객체가 파괴되면 자동으로 null). GC가 객체를 살리지는 않음
      • TSoftObjectPtr<T> / FSoftObjectPath - 경로 기반의 약한(지연)참조로, 로드/유지와는 별개
  • 객체 생명주기 관련 포인트
    1. IsPendingKill() / IsPendinKillPendin() 등으로 파괴 예정 상태를 검사할 수 있음.
    2. BeginDestroy() / FinishDestroy()는 엔진이 파괴 과정에서 호출하는 콜백 - 디버깅할 때 오버라이드해서 로그 찍기 좋음
    3. AddToRoot()를 남용하면 메모리 누수가 생기므로 루트로 올렸으면 RemoveFromRoot() 해주는 것이 중요함.
  • GC로인해 자주 겪는 문제
    1. 플레이 도중 NullPtr/크래시
      • 원인: 객체를 UPROPERTY로 선언하지 않아 GC가 수거함 => 댕글링 포인터 사용
      • 대책: 해당 포인터를 UPROPERTY()로 만들거나 FGCObject로 보호
    2. 메모리 누수(특정 객체가 해제되지 않음)
      • 원인: AddToRoot()로 올리고 RemoveFromRoot()를 안하거나 루트로 연결된 오브젝트 그래프가 있음.
      • 대책: 루트 사용 점검, 참조 그래프 확인
    3. GC 시간이 길어 프레임 드롭
      • 대책: UObject 수 줄이기, GC 타임 슬라이스/점진적 GC 사용 고려(엔진 설정에서 조정)
  • C++의 GC와 UE의 GC 차이
구분 C++ UE
GC 지원 여부 없음 있음
메모리 해제 방식 delete, RAII, 스마트포인트 GC가 참조 그래프 검사 후 자동 해제
추적 기준 참조 횟수(스마트 포인터) / 범위 도달성 기반
관리 대상 모든 객체(개발자 책임) UObject 파생 클래스만
장점 세밀한 제어, 성능 최적화 용이 자동 관리, 에디터/블루프린트 통합
단점 해제 누락/댕글링 포인터 위험 UObject 아닌 건 수동 관리 필요, GC 부하

'Unreal Engine' 카테고리의 다른 글

[UE] 언리얼 빌드 툴/헤더 툴  (0) 2025.08.29
[UE]스마트 포인터  (0) 2025.08.29
[UE] 언리얼의 클래스들  (0) 2025.08.28
[UE]언리얼 오브젝트  (0) 2025.08.28
[UnrealEngine] Enhanced Input System  (0) 2025.08.01