언리얼엔진 GENERATED_BODY()
GENERATED_BODY()
GENERATED_BODY()
는 언리얼 엔진의 리플렉션 시스템을 사용하는 클래스(UCLASS
) 또는 구조체(USTRUCT
)의 헤더 파일 내부에 반드시 포함되어야 하는 중요한 매크로입니다. 이 매크로는 언리얼 엔진의 핵심 기능들을 활성화하는 데 필수적인 코드를 자동으로 생성해줍니다.
1. GENERATED_BODY()의 정의 및 목적
GENERATED_BODY()
는 실제로는 다른 여러 매크로들을 포함하는 복합적인 매크로입니다. 주요 목적은 다음과 같습니다.
- 리플렉션 메타데이터 생성: 언리얼 엔진의 리플렉션 시스템이 클래스 또는 구조체의 정보를 파악하고 활용할 수 있도록 필요한 메타데이터를 생성합니다. 이 메타데이터에는 클래스/구조체의 이름, 속성, 함수, 상속 관계 등에 대한 정보가 포함됩니다.
- UObject 기반 기능 활성화:
UCLASS
로 선언된 클래스의 경우,UObject
로부터 상속받는 다양한 기능들 (예: 가비지 컬렉션, 에디터 통합, 블루프린트 연동, 네트워크 동기화 등)을 사용할 수 있도록 필요한 코드를 생성합니다. - 구조체 지원:
USTRUCT
로 선언된 구조체의 경우에도 리플렉션 기능을 활성화하여 에디터에서 편집하거나 블루프린트에서 사용할 수 있도록 합니다.
2. 사용 위치
GENERATED_BODY()
매크로는 UCLASS()
또는 USTRUCT()
매크로로 선언된 클래스 또는 구조체의 헤더 파일 내부에 위치해야 합니다. 일반적으로 클래스/구조체 선언의 첫 번째 public 섹션에 위치합니다.
예시 (UCLASS):
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYPROJECT_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// ... 클래스 멤버 선언 ...
};
예시 (USTRUCT):
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "MyStruct.generated.h"
USTRUCT(BlueprintType)
struct FMyStruct
{
GENERATED_BODY()
public:
// ... 구조체 멤버 선언 ...
};
3. 생성되는 코드
GENERATED_BODY()
매크로는 컴파일 과정에서 언리얼 헤더 툴(Unreal Header Tool, UHT)에 의해 실제 C++ 코드로 확장됩니다. 생성되는 코드는 클래스 또는 구조체의 종류와 선언 방식에 따라 다소 차이가 있지만, 일반적으로 다음과 같은 내용들을 포함합니다.
- 클래스/구조체 정보 메타데이터: 이름, 부모 클래스/구조체, 플래그 등의 정보가 담긴 정적 변수 및 함수들이 생성됩니다.
- 속성 메타데이터:
UPROPERTY()
매크로로 선언된 멤버 변수들의 이름, 타입, 플래그 등의 정보가 담긴 메타데이터가 생성됩니다. - 함수 메타데이터:
UFUNCTION()
매크로로 선언된 멤버 함수들의 이름, 파라미터, 반환 값, 플래그 등의 정보가 담긴 메타데이터가 생성됩니다. - 가비지 컬렉션 지원 코드 (UCLASS):
UObject
기반 클래스의 경우, 가비지 컬렉션 시스템이 오브젝트를 추적하고 관리할 수 있도록 필요한 함수들이 생성됩니다. 여기에는GetClass()
와 같은 중요한 함수들이 포함됩니다. - 블루프린트 지원 코드: 블루프린트에서 해당 클래스/구조체를 사용하고 상호작용할 수 있도록 필요한 함수 및 메타데이터가 생성됩니다.
- 네트워크 동기화 지원 코드 (UCLASS,
Replicated
속성 사용 시): 네트워크를 통해 오브젝트의 상태를 동기화하는 데 필요한 코드가 생성됩니다. - 생성자 및 복사/이동 생성자 (UCLASS): 클래스의 인스턴스를 생성하고 복사/이동하는 데 필요한 기본 생성자들이 생성될 수 있습니다.
4. 필요성
GENERATED_BODY()
매크로는 언리얼 엔진의 리플렉션 시스템이 제대로 작동하기 위해 필수적입니다. 이 매크로가 없으면 다음과 같은 문제들이 발생할 수 있습니다.
- 에디터에서 속성 편집 불가:
UPROPERTY()
로 선언된 속성들이 언리얼 엔진 에디터의 디테일 패널에 나타나지 않아 편집할 수 없게 됩니다. - 블루프린트와의 연동 실패: 블루프린트에서 해당 클래스/구조체를 사용하거나 상속받을 수 없게 됩니다.
- 가비지 컬렉션 문제 (UCLASS):
UObject
기반 클래스의 인스턴스가 제대로 관리되지 않아 메모리 누수가 발생할 수 있습니다. - 네트워크 동기화 실패 (UCLASS):
Replicated
속성을 사용한 속성들이 네트워크를 통해 제대로 동기화되지 않습니다. GetClass()
함수 사용 불가 (UCLASS): 오브젝트의 클래스 정보를 얻는 데 필수적인GetClass()
함수를 사용할 수 없게 됩니다.
5. 리플렉션 활성화의 영향
GENERATED_BODY()
를 통해 활성화된 리플렉션 시스템은 언리얼 엔진의 다양한 핵심 기능들을 가능하게 합니다.
- 속성 편집 (Property Editing):
UPROPERTY()
매크로와 함께 사용되어 언리얼 엔진 에디터에서 클래스/구조체의 속성 값을 시각적으로 편집할 수 있도록 합니다. - 가비지 컬렉션 (Garbage Collection):
UObject
기반 클래스의 인스턴스를 자동으로 추적하고 더 이상 사용되지 않는 오브젝트를 메모리에서 해제하여 메모리 누수를 방지합니다. - 블루프린트 통합 (Blueprint Integration): C++로 작성된 클래스/구조체를 블루프린트에서 상속하거나 변수 타입, 함수 파라미터/반환 값으로 사용할 수 있도록 합니다.
- 언리얼 에디터와의 통합 (Unreal Editor Integration): 액터 배치, 컴포넌트 추가, 오브젝트 검색 등 다양한 에디터 기능을 활용할 수 있도록 합니다.
- 직렬화 (Serialization): 오브젝트의 상태를 저장하거나 네트워크를 통해 전송할 수 있도록 데이터를 직렬화하고 역직렬화하는 기능을 제공합니다.
- 네트워킹 (Networking):
Replicated
속성을 사용하여 게임 클라이언트 간에 오브젝트의 상태를 자동으로 동기화할 수 있도록 합니다. - 언리얼 마켓플레이스 에셋: 리플렉션 시스템 덕분에 언리얼 마켓플레이스에서 다양한 종류의 에셋들을 쉽게 통합하고 사용할 수 있습니다.
6. 내부 메커니즘 (간략 설명)
GENERATED_BODY()
매크로가 작동하는 핵심에는 언리얼 헤더 툴 (Unreal Header Tool, UHT)이라는 빌드 도구가 있습니다. UHT는 프로젝트의 헤더 파일을 파싱하여 UCLASS
, USTRUCT
, UPROPERTY
, UFUNCTION
등의 언리얼 엔진 특정 매크로들을 분석합니다. 분석된 정보를 바탕으로 UHT는 각 클래스/구조체에 대한 메타데이터 정보와 필요한 C++ 코드를 생성하여 .generated.h
파일에 저장합니다. GENERATED_BODY()
매크로는 바로 이 .generated.h
파일을 포함시키는 역할을 합니다.
7. 주의 사항
- 헤더 파일에만 포함:
GENERATED_BODY()
매크로는 반드시 클래스 또는 구조체의 헤더 파일 (.h) 내부에 포함되어야 합니다. 소스 파일 (.cpp)에 포함하면 컴파일 에러가 발생합니다. UCLASS()
또는USTRUCT()
선언 이후:GENERATED_BODY()
매크로는 반드시UCLASS()
또는USTRUCT()
매크로 선언 바로 다음에 위치해야 합니다.- 첫 번째
public
섹션에 위치 권장: 일반적으로 클래스/구조체 선언의 첫 번째public
접근 제한자 섹션에 위치시키는 것이 관례입니다. .generated.h
파일 포함: 헤더 파일에서GENERATED_BODY()
를 사용했다면, 해당 헤더 파일은 반드시#include "YourHeaderName.generated.h"
라인을 포함해야 합니다. 이 라인은GENERATED_BODY()
매크로에 의해 생성된 코드를 포함시키는 역할을 합니다.
결론적으로, GENERATED_BODY()
매크로는 언리얼 엔진의 강력한 리플렉션 시스템을 활용하기 위한 필수적인 요소입니다. 이 매크로를 통해 클래스와 구조체는 언리얼 엔진의 다양한 기능들과 seamlessly 통합되어 개발 생산성을 크게 향상시킬 수 있습니다.