C++ RTTI 직접 구현하기 (2): TypeInfo로 언리얼 엔진 스타일 RTTI 만들기 (3편)

🚀 들어가며

이전 글에서는 TypeId 기반으로
👉 dynamic_cast 없이 타입을 비교하는 방법을 구현했습니다.

if (obj->Is(Player::TypeId()))

이 방식은 매우 빠르고 단순합니다.
하지만 실제로 사용하다 보면 한 가지 한계에 부딪힙니다.

❗ 타입에 대한 “정보”가 부족하다


🎯 이번 글의 목표

이번 글에서는 TypeId 기반 시스템을 확장하여
👉 엔진 수준의 RTTI 구조를 만들어봅니다.

구체적으로는:

  • 타입 이름 저장
  • 상속 구조 표현
  • 부모 타입까지 포함한 타입 체크

⚠️ TypeId 방식의 한계

TypeId 방식은 다음과 같은 특징이 있습니다:

  • ✔ 빠른 비교 (주소 기반)
  • ✔ 상속 체크 가능 (재귀 호출)

하지만:

  • ❌ 타입 이름 없음
  • ❌ 디버깅 어려움
  • ❌ 확장성 부족 (메타데이터 불가)

👉 즉:

“타입은 구분되지만, 설명할 수는 없다”


🧠 해결 아이디어

필요한 것은 단순한 ID가 아니라:

“타입을 설명할 수 있는 구조”

👉 이를 위해 다음 정보를 묶습니다:

  • 타입 이름
  • 부모 타입
  • 타입 비교 기능

🧩 TypeInfo 클래스 설계

class TypeInfo
{
public:
    TypeInfo(const char* name, const TypeInfo* parent)
        : className(name), parentType(parent) {}

    const char* GetName() const
    {
        return className;
    }

    bool IsChildOf(const TypeInfo* other) const
    {
        for (const TypeInfo* current = this; current; current = current->parentType)
        {
            if (current == other)
                return true;
        }
        return false;
    }

private:
    const char* className;
    const TypeInfo* parentType;
};

🔍 핵심 기능 설명

✔ className

const char* className;
👉 디버깅 / 로그 출력 / 리플렉션 기반

✔ parentType

const TypeInfo* parentType;
👉 상속 구조 표현

✔ IsChildOf

current = current->parentType
👉 부모 체인을 따라 올라가며 타입 비교

🎯 베이스 클래스 수정

기존 TypeId 기반 구조를 확장합니다.

class CraftObject
{
public:
    virtual ~CraftObject() = default;

    static const TypeInfo* StaticClass()
    {
        static TypeInfo typeInfo("CraftObject", nullptr);
        return &typeInfo;
    }

    virtual const TypeInfo* GetClass() const
    {
        return CraftObject::StaticClass();
    }

    bool Is(const TypeInfo* type) const
    {
        return GetClass()->IsChildOf(type);
    }

    template<typename T>
    bool IsTypeOf() const
    {
        return Is(T::StaticClass());
    }
};

⚙️ 매크로로 자동화

#define TYPE_DECLARATIONS(Type, ParentType)				\
public:									\
    using super = ParentType;						\
    static const TypeInfo* StaticClass()				\
    {									\
        static TypeInfo typeInfo(#Type, ParentType::StaticClass());	\
        return &typeInfo;						\
    }									\
                                                                        \
    virtual const TypeInfo* GetClass() const override			\
    {									\
        return Type::StaticClass();					\
    }

🧩 실제 클래스 적용

class Actor : public CraftObject
{
    TYPE_DECLARATIONS(Actor, CraftObject)
};

class Player : public Actor
{
    TYPE_DECLARATIONS(Player, Actor)
};

🎯 사용 예제

std::shared_ptr<CraftObject> obj = std::make_shared<Player>();

if (obj->Is(Player::StaticClass()))
{
    // 정확히 Player
}

if (obj->Is(Actor::StaticClass()))
{
    // Player는 Actor의 자식이므로 true
}

🔥 이 구조의 핵심 장점

1. 상속 구조 완벽 지원

👉 부모 체인 탐색


2. 타입 이름 제공

👉 디버깅 / 로그 가능


3. 확장성 확보

👉 메타데이터 / 리플렉션 확장 가능


🧠 Unreal Engine과의 연결

이 구조는 실제로 Unreal Engine의 다음 개념과 유사합니다:

👉 Unreal은 여기에:

  • GC (Garbage Collection)
  • 프로퍼티 시스템
  • 에디터 연동

까지 확장합니다


⚠️ dynamic_cast vs 커스텀 RTTI

항목 dynamic_cast 커스텀 RTTI
타입 검사 자동 직접 구현
성능 상대적으로 느림 빠름
확장성 제한적 매우 높음
제어 불가능 완전 제어

🎯 언제 사용하는가

이 구조는 다음과 같은 경우에 사용됩니다:

  • 게임 엔진
  • ECS 시스템
  • 런타임 오브젝트 관리
  • 플러그인 시스템

🔥 다음 단계

이제 RTTI는 단순한 “타입 체크”를 넘어

👉 “타입으로 객체를 생성하는 단계”

로 확장할 수 있습니다.


🎯 다음 글 예고

다음 글에서는:

👉 TSubclassOf 스타일 시스템 구현

  • 타입을 변수로 저장
  • 런타임 객체 생성
  • 엔진에서의 활용 방식

💡 핵심 정리

  • TypeId → TypeInfo로 확장
  • 타입 정보를 구조로 관리
  • 상속 체인을 기반으로 타입 체크
  • 엔진 수준 RTTI 완성

🎮 마무리

이번 글에서는
👉 엔진 수준 RTTI 구조의 핵심 아이디어를 구현했습니다.

이 구조를 이해하면:

  • Unreal Engine 내부 구조
  • 커스텀 엔진 설계
  • 런타임 시스템 설계

까지 자연스럽게 연결됩니다.


👉 다음 편에서 계속됩니다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Please turn AdBlock off

Notice for AdBlock users

Please turn AdBlock off