GameplayTag 대신 NativeTag로 만들기

김여울·2025년 11월 21일

내일배움캠프

목록 보기
119/139

[CommonUI] UIMapDataAsset, UIManageSubsystem, HUD (GameplayTag 쓰는 방식)

기존 GameplayTag 기반 UI 시스템을 NativeTag 기반 구조로 전환했다.
NativeTag는 C++에서 선언되기 때문에 오타나 잘못된 경로 같은 문제를 컴파일 단계에서 막을 수 있고, .ini 파싱 비용도 없어 초기화가 더 단순해진다.

UI 요청 태그(UI.Request.)와 레이어 태그(UI.Layer.)를 네임스페이스로 묶어 관리하니 구조가 명확해졌고, DataAsset(UUIMapDataAsset)에 UI 정책을 TMap으로 정리해 UI 흐름을 완전히 데이터 기반으로 운영할 수 있게 했다.

UIManageSubsystem에서는 DefaultGame.ini에서 SoftObjectPath를 읽고 DataAsset을 동적으로 로드하도록 변경해 BP 의존도를 제거했다.

1. GameplayTag와 NativeTag 차이

GameplayTag

  • 설정 기반(DefaultGameplayTags.ini)으로 태그를 등록
  • 에디터에서 추가/수정 가능 → 기획/디자이너 협업에 유리
  • 런타임에 .ini 파일을 읽어 태그를 로딩하는 구조
  • 문자열 기반이지만 내부적으로 FName 해시로 저장되어 성능 부담 거의 없음

NativeTag

  • 태그를 C++ 코드로 정의 (컴파일 타임 확정)
  • 실수로 삭제되거나 이름이 바뀔 위험 적음
  • UE_DECLARE_GAMEPLAY_TAG_EXTERN / UE_DEFINE_GAMEPLAY_TAG 로 선언 및 정의
  • 타입 안정성(type safety)이 뛰어나 오타·런타임 오류 방지
  • .ini 파싱이 필요 없어 초기화가 미세하게 더 빠름 (큰 차이는 아님)
  • 에디터에서도 NativeTag가 태그처럼 보임

➡ 유연성은 GameplayTag, 안정성과 유지보수성은 NativeTag

2. NativeTag 사용 이유 & 성능

  • GameplayTag는 문자열 비교가 아니고 FName(정수) 기반 → 매우 빠름
  • NativeTag도 동일한 구조를 사용
  • NativeTag는 태그를 코드에서 선언하므로 런타임 생성 비용이 없음
  • 오타나 경로 오류를 컴파일 단계에서 걸러줌

3. NativeTag 구조 만들기

UITags 파일 구조

UITags.h

  • UE_DECLARE_GAMEPLAY_TAG_EXTERN
  • 네임스페이스
  • API 매크로
namespace LNGameplayTags
{
	// Request
	OURLONGNUGHT_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(UI_Request_MainMenu);
    
    // Layer
    OURLONGNUGHT_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(UI_Layer_Main);
}

UITags.cpp

#include "UITags.h"

namespace LNGameplayTags
{
	UE_DEFINE_GAMEPLAY_TAG(UI_Request_MainMenu, "UI.Request.MainMenu");

	UE_DEFINE_GAMEPLAY_TAG(UI_Layer_Main, "UI.Layer.Main");
}

➡ 네임스페이스로 묶는 방식은 UE 공식 샘플(AbilitySystem 포함)에서도 권장됨

4. UIMapDataAsset 설계

FUIWidgetPolicy (struct)

  • SoftClass WidgetClass
  • GameplayTag LayerTag (UI.Layer.*)

UUIMapDataAsset (class)

  • TMap<FGameplayTag, FUIWidgetPolicy>
  • Key: UI.Request.*
  • Value: 해당 요청을 처리할 위젯 정책

➡ NativeTag + DataAsset 조합은 UI 레이어/위젯 매핑을 코드 분리 + 데이터 주도 방식으로 관리할 때 매우 적합

5. DefaultGame.ini에서 DataAsset 경로 로딩

  • SoftObjectPath를 Config에 적어두고 Subsystem에서 TryLoad()
  • BP에서 직접 Subsystem에 에셋 참조를 박아두던 방식보다 안전하고 깔끔함
[/Script/OurLongNight.LNUIManageSubsystem]
LNMapDataAssetPath="/Game/UI/DataAssets/DA_LNMap.DA_LNMap"

6. UIManageSubsystem Initialize 흐름

  • UIMapDataAssetPath 값으로 DataAsset 로드
  • 캐싱 → 런타임 UI 생성 시 Lookup 비용 최소화
void UUIManageSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);

    if (UIMapDataAsset)
    {
        CachedWidgetMap = UIMapDataAsset->WidgetMap;
        UE_LOG(LogTemp, Log, TEXT("UIManageSubsystem: %d개의 UI 맵 로드됨."), CachedWidgetMap.Num());
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("UIManageSubsystem: UIMapDataAsset 설정 필요"));
    }
}

0개의 댓글