언리얼 엔진에서 GENERATED_BODY란 무엇인가 ?
언리얼 엔진에서 C++를 활용하여 개발을 진행하다 보면 반드시 접하게 되는 매크로 중 하나가 바로 GENERATED_BODY이다. 새로운 클래스 하나를 만들 때마다, 매번 보이는 이 GENERATED_BODY는 도대체 뭘까 ? 왜 있는걸까 ? 이건 바로 언리얼 엔진에서 GENERATED_BODY는 클래스 선언 시 필수적으로 포함되는 매크로로, 엔진의 리플렉션 시스템과 직렬화, 그리고 블루프린트 통합 등을 지원하기 위해 사용된다.
1. GENERATED_BODY의 역할
GENERATED_BODY는 언리얼 엔진의 오브젝트 시스템에서 매우 중요한 역할을 한다. 이 매크로는 컴파일 타임에 엔진이 자동으로 생성하는 코드 블록을 삽입하여, 클래스와 관련된 다양한 메타데이터와 기능을 포함하게 된다. 이로 인해 개발자는 별도의 수작업 없이도 클래스가 언리얼 엔진의 다양한 기능을 활용할 수 있도록 지원된다.
GENERATED_BODY 매크로는 주로 UCLASS, USTRUCT, UINTERFACE 등의 클래스 선언에서 사용된다. 각 선언마다 GENERATED_BODY를 포함해야 하는데, 이를 통해 엔진은 해당 클래스가 엔진의 리플렉션 시스템과 상호작용할 수 있도록 코드 생성을 자동화한다.
2. GENERATED_BODY와 GENERATED_UCLASS_BODY의 차이점
이전 버전의 언리얼 엔진에서는 GENERATED_UCLASS_BODY를 사용했으나, 현재는 GENERATED_BODY로 대체되었다. 두 매크로의 차이점은 주로 코드 생성 방식에 있다. GENERATED_UCLASS_BODY는 헤더 파일에만 코드를 삽입하는 반면, GENERATED_BODY는 헤더와 CPP 파일 모두에 필요한 코드를 생성하여 더 유연하고 강력한 구조를 제공한다.
3. GENERATED_BODY의 내부 구조
GENERATED_BODY는 단순한 매크로가 아니라, 수많은 코드를 자동으로 생성하는 역할을 한다. 내부적으로는 다양한 접근자 함수와 메타데이터 관련 코드를 생성하여 엔진이 클래스를 인식하고 사용할 수 있도록 만든다.
주요 역할
- 리플렉션 시스템 지원
- 직렬화 코드 생성
- 블루프린트 통합
- 클래스 메타데이터 등록
GENERATED_BODY 정의 경로
대부분의 경우 언리얼 엔진 소스 코드에서 다음과 같은 경로에서 찾을 수 있다 :
Engine/Source/Runtime/CoreUObject/Public/UObject/ObjectMacros. h
정의 코드(예시)
아래는 ObjectMacros. h 파일에서 확인할 수 있는 GENERATED_BODY의 정의이다 :
#define GENERATED_BODY(. . . ) \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ BODY_MACRO_COMBINE(CURRENT_FILE_ID, _, __LINE__, _GENERATED_BODY) \ PRAGMA_ENABLE_DEPRECATION_WARNINGS
이 매크로는 사실상 다른 매크로와 결합하여 동작하며, 내부적으로 복잡한 전처리기 지시문과 코드 생성 과정을 포함하고 있다. BODY_MACRO_COMBINE 부분이 가장 핵심적인 역할을 하며, 각 파일 ID와 줄 번호를 활용하여 유일한 코드 블록을 생성하도록 구성되어 있다.
핵심 매크로와 구조
매크로 내부에는 코드 경합을 방지하기 위해 디프리케이션 경고를 비활성화하고 다시 활성화하는 코드가 포함되어 있다. 이로 인해 엔진 업데이트나 코드 변화에 유연하게 대응할 수 있다.
언리얼 엔진의 소스 코드 구조가 워낙 방대하기 때문에 GENERATED_BODY 매크로의 최종 생성 코드까지 추적하는 것은 다소 복잡하다. 그러나 핵심은 ObjectMacros. h에 정의된 이 매크로를 통해 여러 가지 부가 코드와 메타데이터가 자동으로 삽입된다는 점이다.
4. 왜 GENERATED_BODY가 필요한가 ?
언리얼 엔진에서 C++ 클래스를 작성할 때, 해당 클래스가 블루프린트에서 사용되거나, 엔진의 다양한 시스템과 상호작용하기 위해서는 메타데이터가 필요하다. GENERATED_BODY 매크로는 이러한 메타데이터를 자동으로 생성하여 엔진이 인식할 수 있도록 만든다. 만약 이 매크로를 사용하지 않는다면, 블루프린트와의 호환성이 떨어지고 엔진의 다양한 기능을 활용하지 못하게 된다.
5. GENERATED_BODY 사용 시 주의사항
- GENERATED_BODY 매크로는 반드시 클래스 선언의 첫 부분에 위치해야 한다.
- 언리얼 엔진의 버전에 따라 매크로 사용법이 달라질 수 있으므로, 최신 문서를 참조하여 작성하는 것이 중요하다.
- 잘못된 위치에 매크로를 사용하면 컴파일 오류가 발생할 수 있으므로 주의해야 한다.
결론
언리얼 엔진에서 GENERATED_BODY는 필수적인 매크로로, 엔진의 핵심 시스템과 클래스가 상호작용할 수 있도록 돕는 중요한 역할을 한다. 이 매크로를 올바르게 이해하고 사용하는 것은 언리얼 엔진 기반 프로젝트에서 매우 중요하다.
구분 | 역할 | 사용 위치 |
리플렉션 시스템 지원 | 클래스 메타데이터 등록 및 접근자 함수 생성 | UCLASS, USTRUCT 등 |
직렬화 코드 생성 | 엔진의 직렬화 및 데이터 저장/로드 처리 지원 | UObject 기반 클래스 |
블루프린트 통합 | 블루프린트에서 클래스 및 변수 활용 가능 | 블루프린트 지원 클래스 |
메타데이터 등록 | 엔진 내부에서 클래스 속성 및 특성 자동화 | 모든 언리얼 클래스 선언부 |
GENERATED_BODY를 제대로 이해하고 활용한다면, 언리얼 엔진에서의 C++ 개발이 훨씬 수월해진다. 코드의 가독성을 높이고 엔진의 강력한 기능을 활용할 수 있는 핵심 매크로이므로, 항상 정확한 위치와 용도로 사용하도록 주의해야 한다.