본문 바로가기

AActor와 UObject의 차이점

UObject와 AActor의 수명·월드 배치·컴포넌트·복제 차이를 비교하고 생성 API를 올바르게 선택합니다.

지난 절에서 리플렉션 시스템과 핵심 매크로를 익혔다면, 이제 객체 시스템의 뼈대로 내려가야 합니다.

이번 절은 언리얼 C++에서 가장 자주 만나는 기본 클래스, UObject와 AActor를 비교합니다.

두 클래스의 경계를 명확히 이해해야 설계 실수를 줄일 수 있습니다.


UObject: 언리얼 객체 시스템의 기반

먼저 UObject를 정리하겠습니다.

UObject는 언리얼의 리플렉션 객체 시스템을 이루는 기본 클래스입니다. 일반 C++ 클래스나 값 타입 구조체까지 모두 UObject를 상속하는 것은 아닙니다.

언리얼 엔진에서 객체라고 불리는 거의 모든 것(액터, 컴포넌트, 에셋, 게임 모드 등)은 직간접적으로 UObject를 상속받습니다.

UObject가 담당하는 핵심적인 역할들은 다음과 같습니다.

  • 리플렉션 시스템 통합: UObject는 앞서 배운 UCLASS, UPROPERTY, UFUNCTION 매크로를 통해 언리얼 엔진의 리플렉션 시스템에 통합됩니다. 에디터 노출과 블루프린트 접근, 직렬화에 참여할 수 있지만 실제 허용 범위는 각 타입과 지정자에 따라 다릅니다.
  • 가비지 컬렉션(Garbage Collection) 관리: UObject의 수명 주기는 언리얼의 가비지 컬렉터가 관리합니다. GC가 추적하는 강한 참조 그래프에서 루트로부터 도달할 수 없는 객체는 회수 대상이 됩니다. 임의의 C++ 포인터를 보관하는 것만으로 생존이 보장되지는 않습니다.
  • 직렬화(Serialization): UObject는 자신과 자신의 속성들을 저장하고 불러올 수 있는 직렬화 기능을 제공합니다. 이는 게임 상태를 저장하거나, 네트워크를 통해 객체 데이터를 전송할 때 매우 유용합니다.
  • 에디터 통합: 에셋으로 만든 UObject 계열은 콘텐츠 브라우저에서 다룰 수 있습니다. 일반 런타임 객체가 모두 독립 에셋으로 표시되는 것은 아닙니다. 리플렉션에 등록한 속성의 Details 편집도 타입과 지정자가 허용한 범위를 따릅니다.
  • 이름 관리 및 참조: UObject의 이름은 같은 Outer 안에서 구분되며, 다른 UObject들을 강력하게 참조할 수 있는 메커니즘을 제공합니다.

간단히 말해, UObject는 언리얼 엔진의 스마트한 객체 시스템에 편입되어 엔진의 다양한 관리 기능(메모리, 직렬화, 반사 등)의 혜택을 받을 수 있도록 해주는 최소 단위의 클래스입니다.

월드에 배치하지 않더라도 개별 객체의 정체성과 엔진의 수명 관리가 필요하면 UObject 계열을 선택할 수 있습니다. 단순 값 데이터에는 USTRUCT나 일반 C++ 구조체가 더 적합할 수 있습니다.


AActor: 월드에 존재할 수 있는 모든 것

그렇다면 AActor는 무엇일까요?

AActor는 언리얼 엔진의 월드(Level)에 배치하거나 스폰하는 액터의 기본 클래스입니다. 월드의 표현에 참여하는 컴포넌트나 메시 에셋까지 모두 액터 인스턴스인 것은 아닙니다.

즉, 여러분이 게임 화면에서 보거나 상호작용할 수 있는 거의 모든 것들(캐릭터, 카메라, 라이트, 스폰 지점, 트리, 건물 등)은 AActor를 상속받습니다.

AActor는 UObject를 상속받습니다.

이는 AActor가 UObject의 모든 기능을 그대로 물려받는다는 의미입니다.

즉, AActor도 가비지 컬렉션의 대상이 되고, 직렬화되며, 에디터에 노출됩니다.

하지만 AActor는 UObject에는 없는 추가적인 중요한 기능들을 제공합니다.

  • 변환(Transform) 정보: 액터의 위치(Location), 회전(Rotation), 크기(Scale)는 루트 USceneComponent의 트랜스폼을 통해 표현됩니다. AActor 자체가 이 값을 저장하는 것은 아닙니다.
  • 컴포넌트(Components) 컨테이너: AActor는 여러 UActorComponent를 부착해 기능을 확장하는 컨테이너입니다. StaticMeshComponent(시각 요소), CapsuleComponent(충돌), MovementComponent(이동)처럼 역할을 분리해 조합하면 복잡한 액터도 구조적으로 관리할 수 있습니다.
  • 수명 주기 관리: AActor는 BeginPlay(), Tick(), EndPlay() 등 게임 월드 내에서의 특정 이벤트 발생 시 호출되는 중요한 수명 주기 함수들을 가집니다. 여러분은 이 함수들을 오버라이드(Override)하여 액터의 동작을 정의하게 됩니다.
  • 네트워크 복제(Networking Replication): 멀티플레이어 게임을 만들 때, AActor는 네트워크를 통해 자신의 상태를 클라이언트들에게 복제하는 기능을 제공합니다.
  • 콜리전(Collision) 및 물리 시뮬레이션: UPrimitiveComponent 계열의 컴포넌트와 충돌·물리 설정을 통해 충돌 감지와 물리 시뮬레이션에 참여합니다.

생성과 수명 선택

객체 종류에 맞는 생성과 수명 관리

NewObject 효과→도달 가능한 관리 객체의 ActiveEffect 보관→참조 비움에서 강한 경로와 회수 대상 가능성이 바뀐다. 즉시 해제·Actor Destroy 생존 연장으로 표시하지 않는다.

UNREAL C++ · CH2-2

객체 종류에 맞는 생성과 수명 관리

일반 UObject, 기본·동적 컴포넌트, 월드 액터의 생성 경로를 구분하고 생존·등록·부착을 별도로 확인합니다.

보관 중: 루트에서 관리 객체를 거쳐 효과에 도달합니다.

일반 UObject 효과의 강한 참조 retainedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.
GC 루트도달 가능한 경로
연결 관계GC 루트 · 도달 가능한 경로 → 관리 객체 · UPROPERTY · ActiveEffect
관리 객체UPROPERTYActiveEffect
참조참조관리 객체 · UPROPERTY · ActiveEffect → 일반 UObject 효과 · 생성된 객체
일반 UObject 효과생성된 객체
일반 UObject 효과의 강한 참조 retainedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.
GC 루트도달 가능한 경로
연결 관계GC 루트 · 도달 가능한 경로 → 관리 객체 · UPROPERTY · ActiveEffect
관리 객체UPROPERTYActiveEffect
강한 참조강한 참조관리 객체 · UPROPERTY · ActiveEffect → 일반 UObject 효과 · 생성된 객체
일반 UObject 효과생성된 객체

참조를 비운 뒤: 다른 강한 참조가 없다면 일반 효과는 회수 대상이 될 수 있습니다.

일반 UObject 효과의 강한 참조 releasedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.GC 루트도달 가능한 경로관리 객체UPROPERTYActiveEffect일반 UObject 효과생성된 객체ActiveEffect = nullptr다른 강한 참조 없음회수 대상 가능 ≠ 즉시 해제
일반 UObject 효과의 강한 참조 releasedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.GC 루트도달 가능한 경로관리 객체UPROPERTYActiveEffect일반 UObject 효과생성된 객체ActiveEffect = nullptr다른 강한 참조 없음회수 대상 가능 ≠ 즉시 해제
생성하려는 대상과 수명 관리
생성 상황생성·등록 경로수명에서 확인할 점
일반 객체NewObject<T>(Outer)GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트생성자에서 CreateDefaultSubobject<T>()액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트NewObject<T>(Owner) 후 RegisterComponent()등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터월드의 SpawnActor<T>()Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음
일반 객체
생성·등록 경로: NewObject<T>(Outer)
수명에서 확인할 점: GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트
생성·등록 경로: 생성자에서 CreateDefaultSubobject<T>()
수명에서 확인할 점: 액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트
생성·등록 경로: NewObject<T>(Owner) 후 RegisterComponent()
수명에서 확인할 점: 등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터
생성·등록 경로: 월드의 SpawnActor<T>()
수명에서 확인할 점: Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음

Outer나 포인터 변수만으로 생존이 보장되지는 않습니다. GC가 추적할 강한 참조와 소유 객체의 도달 가능성을 확인합니다. Tick·복제·충돌도 별도 설정입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명GC 루트→도달 가능한 관리 객체의 강한 참조, 관리 객체의 UPROPERTY ActiveEffect→일반 UObject 효과로 이어진다. 보관을 비운 상태는 다른 강한 참조가 없다는 가정에서 뒤 간선만 없으며 회수 대상 가능≠즉시 해제다. 액터 Destroy의 생존 연장을 뜻하지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
효과 생성

NewObject로 효과 UObject를 만든다.

  • 객체: 효과 UObject
  • 조건: 유효한 소유/참조 경로
  • 일반 C++ new와 UObject 관리의 관계를 구분한다.
강한 보관

도달 가능한 관리 객체의 ActiveEffect가 효과를 보관한다.

  • 필드: ActiveEffect
  • 상태: 강한 도달 경로 유지
  • 필드가 있는 소유자도 루트에서 도달 가능해야 한다.
참조 비움

필드를 비워 다른 강한 경로 유무가 중요해진다.

  • ActiveEffect: 비움
  • GC: 회수 대상 가능
  • 즉시 해제 시점이나 Actor Destroy 수명 연장을 보장하지 않는다.

객체 종류에 맞는 생성과 수명 관리

NewObject 효과→도달 가능한 관리 객체의 ActiveEffect 보관→참조 비움에서 강한 경로와 회수 대상 가능성이 바뀐다. 즉시 해제·Actor Destroy 생존 연장으로 표시하지 않는다.

UNREAL C++ · CH2-2

객체 종류에 맞는 생성과 수명 관리

일반 UObject, 기본·동적 컴포넌트, 월드 액터의 생성 경로를 구분하고 생존·등록·부착을 별도로 확인합니다.

보관 중: 루트에서 관리 객체를 거쳐 효과에 도달합니다.

일반 UObject 효과의 강한 참조 retainedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.
GC 루트도달 가능한 경로
연결 관계GC 루트 · 도달 가능한 경로 → 관리 객체 · UPROPERTY · ActiveEffect
관리 객체UPROPERTYActiveEffect
참조참조관리 객체 · UPROPERTY · ActiveEffect → 일반 UObject 효과 · 생성된 객체
일반 UObject 효과생성된 객체
일반 UObject 효과의 강한 참조 retainedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.
GC 루트도달 가능한 경로
연결 관계GC 루트 · 도달 가능한 경로 → 관리 객체 · UPROPERTY · ActiveEffect
관리 객체UPROPERTYActiveEffect
강한 참조강한 참조관리 객체 · UPROPERTY · ActiveEffect → 일반 UObject 효과 · 생성된 객체
일반 UObject 효과생성된 객체

참조를 비운 뒤: 다른 강한 참조가 없다면 일반 효과는 회수 대상이 될 수 있습니다.

일반 UObject 효과의 강한 참조 releasedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.GC 루트도달 가능한 경로관리 객체UPROPERTYActiveEffect일반 UObject 효과생성된 객체ActiveEffect = nullptr다른 강한 참조 없음회수 대상 가능 ≠ 즉시 해제
일반 UObject 효과의 강한 참조 releasedGC루트→도달가능관리객체의강한참조,관리객체의UPROPERTYActiveEffect→일반UObject효과.보관을비운상태는다른강한참조없음가정에서뒤간선만없으며회수대상가능≠즉시해제이다.액터Destroy의생존연장을뜻하지않는다.GC 루트도달 가능한 경로관리 객체UPROPERTYActiveEffect일반 UObject 효과생성된 객체ActiveEffect = nullptr다른 강한 참조 없음회수 대상 가능 ≠ 즉시 해제
생성하려는 대상과 수명 관리
생성 상황생성·등록 경로수명에서 확인할 점
일반 객체NewObject<T>(Outer)GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트생성자에서 CreateDefaultSubobject<T>()액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트NewObject<T>(Owner) 후 RegisterComponent()등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터월드의 SpawnActor<T>()Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음
일반 객체
생성·등록 경로: NewObject<T>(Outer)
수명에서 확인할 점: GC가 추적하는 강한 참조를 유지할 위치
기본 컴포넌트
생성·등록 경로: 생성자에서 CreateDefaultSubobject<T>()
수명에서 확인할 점: 액터의 기본 구성; 씬 컴포넌트 부착 관계는 별도 설정
동적 컴포넌트
생성·등록 경로: NewObject<T>(Owner) 후 RegisterComponent()
수명에서 확인할 점: 등록과 공간 부착은 별개; 소유 액터와 정리 시점 확인
런타임 액터
생성·등록 경로: 월드의 SpawnActor<T>()
수명에서 확인할 점: Destroy 후 IsValid 등으로 유효성 확인; 직접 delete하지 않음

Outer나 포인터 변수만으로 생존이 보장되지는 않습니다. GC가 추적할 강한 참조와 소유 객체의 도달 가능성을 확인합니다. Tick·복제·충돌도 별도 설정입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명GC 루트→도달 가능한 관리 객체의 강한 참조, 관리 객체의 UPROPERTY ActiveEffect→일반 UObject 효과로 이어진다. 보관을 비운 상태는 다른 강한 참조가 없다는 가정에서 뒤 간선만 없으며 회수 대상 가능≠즉시 해제다. 액터 Destroy의 생존 연장을 뜻하지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
효과 생성

NewObject로 효과 UObject를 만든다.

  • 객체: 효과 UObject
  • 조건: 유효한 소유/참조 경로
  • 일반 C++ new와 UObject 관리의 관계를 구분한다.
강한 보관

도달 가능한 관리 객체의 ActiveEffect가 효과를 보관한다.

  • 필드: ActiveEffect
  • 상태: 강한 도달 경로 유지
  • 필드가 있는 소유자도 루트에서 도달 가능해야 한다.
참조 비움

필드를 비워 다른 강한 경로 유무가 중요해진다.

  • ActiveEffect: 비움
  • GC: 회수 대상 가능
  • 즉시 해제 시점이나 Actor Destroy 수명 연장을 보장하지 않는다.

지속할 UObject 참조를 멤버에 둘 때는 도달 가능한 객체 안의 UPROPERTY() TObjectPtr<T>처럼 GC가 추적하는 강한 참조를 사용합니다. TObjectPtr만 붙이거나 Outer만 지정하는 것은 같은 보장이 아닙니다.

예시: 객체를 만들고 보관하는 것은 다른 단계

앞 절의 ActiveEffect를 가진 관리 객체가 GC 루트에서 도달 가능하다고 합시다. NewObject로 만든 일반 UObject 효과를 그 멤버에 보관하면 관리 객체에서 효과로 이어지는 추적 가능한 강한 참조가 생깁니다. 다른 강한 참조가 전혀 없는 상태에서 ActiveEffect를 비우면 효과는 GC 회수 대상이 될 수 있습니다. 대입 직후 즉시 메모리가 회수된다는 뜻은 아닙니다. 같은 객체를 원시 포인터 지역 변수에 보관했거나 Outer를 정해 두었다는 이유만으로 그 강한 참조를 대신했다고 판단하지 않습니다.

이 예시는 일반 UObject의 GC 참조를 다룹니다. 액터의 Destroy나 월드 종료로 더 이상 게임플레이에 사용할 수 없게 된 대상을 강한 참조로 계속 살려 사용할 수 있다는 뜻은 아닙니다.

생성 경로 선택하기

월드에 날아가는 발사체 액터 한 개와, 월드 위치 없이 객체 정체성만 필요한 효과 데이터 객체 한 개를 런타임에 만들려 합니다. 각각 월드의 SpawnActor와 일반 객체의 NewObject 중 어느 경로를 고를까요? 효과 데이터의 Outer만 관리자로 정하고 추적 가능한 보관 참조를 두지 않아도 장기 생존이 보장되는지도 설명해 보세요.

생성과 생존의 풀이

발사체는 액터의 월드 생성 경로인 SpawnActor, 일반 UObject 효과 데이터는 NewObject를 선택합니다. 효과의 Outer 지정은 도달 가능한 소유 객체의 강한 UPROPERTY 참조 보관과 같지 않습니다. 계속 사용할 일반 효과는 그 참조 경로를 유지하고, 액터는 Destroy·월드 수명 경계에서 유효성을 다시 확인합니다.

Object Pointers는 UPROPERTY로 표시한 TObjectPtr의 GC 영향과 원시·약한 참조의 차이를 설명합니다. 일반 객체의 생성은 NewObject 항목을 확인합니다.

자주 발생하는 오해

  • UObject도 월드 위치를 가진다: 아닙니다. 월드 트랜스폼이 필요하면 AActor 또는 USceneComponent 기반으로 설계해야 합니다.
  • AActor는 delete로 정리한다: 아닙니다. 언리얼 수명 주기(Destroy, GC)에 맞춰 정리해야 하며 수동 delete는 사용하지 않습니다.
  • 복제는 아무 클래스에서나 자동 동작한다: 네트워크 복제는 기본적으로 AActor(및 관련 컴포넌트) 경로에서 설계하는 것이 표준입니다.

게임 인스턴스나 월드 수명에 붙는 관리자는 해당 Subsystem 계열도 검토합니다. Subsystem은 액터 배치를 대신하는 타입이 아니라 엔진이 정해진 수명에 맞춰 생성·정리하는 UObject 계열입니다.

언제 무엇을 사용할까?

  • AActor를 상속받을 때
    • 게임 월드에 시각적으로 배치되어야 하는 오브젝트 (예: 캐릭터, 건물, 무기, 차량, 조명).
    • 3D 공간에서 위치, 회전, 스케일 정보를 가져야 하는 오브젝트.
    • 다른 컴포넌트를 부착하여 복합적인 기능을 수행해야 하는 오브젝트.
    • 특정 게임 이벤트(예: 충돌, 트리거)에 반응해야 하는 오브젝트.
  • UObject를 상속받을 때
    • 게임 월드에 직접 배치될 필요는 없지만, 엔진의 가비지 컬렉션이나 직렬화의 혜택을 받고 싶은 데이터 컨테이너.
    • 특정 시스템의 관리자 클래스 (예: 인벤토리 관리자, 퀘스트 관리자).
    • 특정 UI 위젯의 데이터 모델.
    • 값 구조체로 충분하지 않고 객체 참조가 필요한 블루프린트 데이터.
    • UActorComponent를 상속받지 않는 순수 논리적 컴포넌트.

다음 절에서는 AActor를 상속하는 C++ 클래스를 생성하고 블루프린트로 확장합니다.