언리얼 엔진 리플렉션 시스템의 기본 개념

2025. 5. 14. 23:19원티드_언리얼RPG 2기/언리얼

 

 

리플렉션(Reflection) 시스템은 언리얼 엔진의 핵심 기술 중 하나로, 간단히 말해 프로그램이 실행 중에 자기 자신의 구조와 데이터를 조사하고 조작할 수 있게 해주는 메커니즘입니다. C++에는 기본적으로 리플렉션 기능이 없기 때문에, 언리얼 엔진은 자체적인 리플렉션 시스템(프로퍼티 시스템)을 구현했습니다.

핵심 개념

  1. 런타임 타입 정보
    • 프로그램이 실행 중에 클래스, 구조체, 함수, 변수 등의 타입 정보에 접근할 수 있습니다.
    • 이를 통해 코드가 자신의 구조를 "인식"하고 그에 따라 작동할 수 있습니다.
  2. 메타데이터 시스템
    • 클래스나 프로퍼티에 추가 정보(메타데이터)를 붙일 수 있습니다.
    • 이 메타데이터는 에디터에서의 표시 방법, 네트워크 동작, 직렬화 방법 등을 지정합니다.
  3. 자동 생성 코드
    • 개발자가 특수 매크로(UCLASS(), UPROPERTY() 등)로 코드에 주석을 달면, 언리얼 헤더 툴(UHT)이 자동으로 필요한 리플렉션 코드를 생성합니다.

리플렉션 시스템의 주요 구성 요소

 

전체적인 구조 요약:

  1. 모든 것은 UObject에서 시작 (런타임 객체):
    • UObject
      • UActor (게임 월드에 배치될 수 있는 오브젝트)
      • UActorComponent (액터에 붙어서 기능을 확장하는 컴포넌트)
      • 그 외 여러분이 UCLASS()로 만드는 모든 것들...
      • UField (리플렉션 메타데이터 객체들의 루트도 결국 UObject)
  2. 리플렉션 메타데이터 계층 (UField 아래):
    • UObject
      • UField (모든 리플렉션 타입의 기본)
        • UStruct (멤버를 포함하는 구조의 기본)
          • UClass (C++ 클래스에 대한 정보)
          • UScriptStruct (C++ 구조체에 대한 정보)
          • UFunction (C++ 함수에 대한 정보)
        • UEnum (C++ 열거형에 대한 정보)
        • FProperty (멤버 변수, 함수 파라미터에 대한 정보 - UProperty의 실제 구현은 FProperty 계열이며, UObject를 직접 상속하지 않는 FField를 상속합니다. 하지만 개념적으로 UField 계열의 정보를 다룬다고 이해하시면 편합니다. 좀 더 정확히는, UProperty는 UField를 상속받지만, 내부적으로 FProperty의 데이터를 참조하여 작동)
          • FNumericProperty (UIntProperty, UFloatProperty 등)
          • FObjectProperty (UObject* 타입 변수)
          • FStructProperty (구조체 타입 변수)
          • ... 등등
  1. 타입 계층구조
     
    UField
    ├── UStruct
    │   ├── UClass (C++ 클래스)
    │   ├── UScriptStruct (C++ 구조체)
    │   └── UFunction (C++ 함수)
    ├── UEnum (C++ 열거형)
    └── UProperty (C++ 멤버 변수 또는 함수 매개변수)
        └── (다양한 타입별 하위 클래스)
  2. 주요 매크로
    • UCLASS(): 클래스를 리플렉션 시스템에 등록
    • USTRUCT(): 구조체를 리플렉션 시스템에 등록
    • UPROPERTY(): 변수를 리플렉션 시스템에 등록
    • UFUNCTION(): 함수를 리플렉션 시스템에 등록
    • UENUM(): 열거형을 리플렉션 시스템에 등록
    • GENERATED_BODY(): 언리얼 헤더 툴이 생성한 코드를 삽입

리플렉션 시스템의 주요 활용 사례

  1. 에디터 통합
    • 디테일 패널에서 프로퍼티 표시 및 편집
    • 블루프린트 편집기에서 노드로 함수 표시
  2. 직렬화
    • 객체를 파일로 저장하고 불러오기
      • 직렬화란? 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것
    • 레벨, 액터, 컴포넌트 등의 저장 및 로드
  3. 네트워크 리플리케이션
    • 멀티플레이어 게임에서 객체 상태 동기화
  4. 가비지 컬렉션
    • 사용되지 않는 객체 자동 정리
  5. 블루프린트-C++ 상호작용
    • C++ 코드를 블루프린트에서 사용 가능하게 함
    • 블루프린트에서 정의된 함수를 C++에서 호출

예시 코드

 
 
// MyActor.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h" // 항상 마지막에 include
							   // UHT(언리얼 헤더툴이 자동생성해줌)

UCLASS()
class MYGAME_API AMyActor : public AActor
{
    GENERATED_BODY()
    
public:    
    AMyActor();

    // 블루프린트에서 호출 가능한 함수
    UFUNCTION(BlueprintCallable, Category="MyFunctions")
    void DoSomething();
    
    // 에디터에서 편집 가능한 변수
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MyProperties")
    float MyFloat;
    
    // 네트워크에서 복제되는 변수
    UPROPERTY(Replicated)
    int32 MyReplicatedInt;
    
private:
    // 직렬화되지만 에디터에서는 숨겨진 변수
    UPROPERTY()
    FString MyPrivateString;
};

 

언리얼 엔진의 리플렉션 시스템은 게임 코드를 더 모듈화하고, 엔진과 에디터 간의 통합을 강화하며, 네트워킹과 직렬화와 같은 복잡한 작업을 단순화하는 데 중요한 역할을 합니다. 이 시스템을 이해하면 언리얼 엔진으로 게임을 개발할 때 큰 도움이 될 것입니다.