PART 1 · 강의 1/3

위젯 시스템 개요

UE5 UI의 근간인 UMG 위젯 시스템의 전체 아키텍처를 이해하고, UWidget과 SWidget의 관계, 위젯 생명주기를 학습합니다.

01

UMG와 Slate의 관계

UMG는 Slate 위에 구축된 디자이너 친화적 UI 프레임워크입니다

Unreal Engine의 UI 시스템은 두 개의 레이어로 구성됩니다. 하위 레벨의 Slate 프레임워크가 순수 C++로 동작하며, 그 위에 UMG(Unreal Motion Graphics)가 블루프린트와 에디터를 통한 시각적 작업을 가능하게 합니다.

[UMG Layer - 디자이너/블루프린트]
  ├─ UWidget (UObject 기반, 리플렉션 지원)
  ├─ UUserWidget (블루프린트 UI 기본 클래스)
  └─ Widget Blueprint (에디터 WYSIWYG)
          ↓ 래핑
[Slate Layer - C++ 코어]
  ├─ SWidget (모든 Slate 위젯의 베이스)
  ├─ SCompoundWidget (복합 위젯)
  └─ SLeafWidget (리프 위젯, 직접 렌더링)
핵심 개념

각 UMG 위젯(UWidget)은 내부적으로 대응하는 Slate 위젯(SWidget)을 생성하고 래핑합니다. 예를 들어, UButton은 내부에 SButton을 생성합니다. UMG는 Slate의 기능을 UObject 리플렉션 시스템에 노출시켜 블루프린트와 에디터에서 사용 가능하게 만든 "프론트엔드"입니다.

C++ - UWidget과 SWidget의 관계
// UWidget.h 에서 발췌 class UWidget : public UVisual { GENERATED_BODY() protected: // 이 UWidget이 래핑하는 실제 Slate 위젯 TSharedPtr<SWidget> MyWidget; // Slate 위젯을 생성하는 가상 함수 (서브클래스에서 오버라이드) virtual TSharedRef<SWidget> RebuildWidget() override; // Slate 리소스 해제 virtual void ReleaseSlateResources(bool bReleaseChildren) override; };
특성 Slate (SWidget) UMG (UWidget)
언어 순수 C++ C++ + 블루프린트
베이스 클래스 SWidget (비 UObject) UWidget (UObject 파생)
메모리 관리 TSharedPtr / TSharedRef 가비지 컬렉션 (GC)
에디터 지원 없음 (코드만) Widget Blueprint Designer
사용 대상 에디터 UI, 커스텀 위젯 게임 UI 전반
02

UWidget 클래스 계층

UMG 위젯의 상속 구조와 주요 클래스를 파악합니다

UVisual
  └─ UWidget (모든 UMG 위젯의 베이스)
      ├─ UPanelWidget (자식을 가질 수 있는 위젯)
      │   ├─ UCanvasPanel
      │   ├─ UHorizontalBox
      │   ├─ UVerticalBox
      │   ├─ UOverlay
      │   └─ UGridPanel
      ├─ UContentWidget (단일 자식)
      │   ├─ UBorder
      │   ├─ UButton
      │   └─ USizeBox
      ├─ UUserWidget (블루프린트 UI 클래스)
      ├─ UTextBlock
      ├─ UImage
      └─ UProgressBar

주요 위젯 카테고리

UPanelWidget

여러 자식 위젯을 포함할 수 있는 컨테이너 위젯입니다. CanvasPanel, HorizontalBox, VerticalBox 등이 이에 해당합니다. 각 패널은 고유한 레이아웃 규칙(Slot)을 가집니다.

UContentWidget

단일 자식만 가질 수 있는 위젯입니다. Button, Border, SizeBox 등이 여기에 속합니다. 자식에 특정 동작이나 시각적 효과를 부여합니다.

UUserWidget

개발자가 Widget Blueprint로 생성하는 커스텀 위젯의 베이스 클래스입니다. 게임 UI의 대부분은 이 클래스를 상속합니다.

리프 위젯

자식을 가지지 않고 직접 콘텐츠를 표시하는 말단 위젯입니다. TextBlock, Image, ProgressBar 등이 여기에 해당합니다.

03

위젯 생명주기

위젯이 생성되고 화면에 표시되며 제거되기까지의 전체 과정을 이해합니다

CreateWidget()
Initialize()
NativeConstruct()
AddToViewport()
Tick()
RemoveFromParent()
NativeDestruct()
C++ - 위젯 생성 및 표시
// PlayerController 또는 GameMode에서 위젯 생성 void AMyPlayerController::BeginPlay() { Super::BeginPlay(); // 1. CreateWidget으로 UUserWidget 인스턴스 생성 UMyHUDWidget* HUDWidget = CreateWidget<UMyHUDWidget>(this, HUDWidgetClass); if (HUDWidget) { // 2. 뷰포트에 추가 (ZOrder로 레이어 순서 지정) HUDWidget->AddToViewport(0); } } // UUserWidget 서브클래스에서 생명주기 함수 오버라이드 void UMyHUDWidget::NativeConstruct() { Super::NativeConstruct(); // 위젯이 뷰포트에 추가된 직후 호출 // 초기 바인딩, 애니메이션 시작 등을 여기서 수행 } void UMyHUDWidget::NativeDestruct() { // 위젯이 뷰포트에서 제거될 때 호출 // 리소스 정리, 타이머 해제 등 Super::NativeDestruct(); }
주의: 생성 vs 표시 시점

CreateWidget()은 UWidget 객체와 내부 SWidget을 생성하지만, 아직 화면에 표시하지는 않습니다. AddToViewport() 또는 AddToPlayerScreen()을 호출해야 실제로 화면에 나타납니다. NativeConstruct()는 뷰포트에 추가될 때 호출되므로, 생성 시점과 혼동하지 마세요.

블루프린트에서의 생명주기 이벤트

블루프린트 이벤트 C++ 대응 함수 호출 시점
Pre Construct NativePreConstruct() 위젯 디자이너 미리보기 + 런타임
Construct NativeConstruct() 뷰포트에 추가된 직후 (런타임만)
Destruct NativeDestruct() 뷰포트에서 제거될 때
Tick NativeTick() 매 프레임 (활성화 시)
04

RebuildWidget 패턴

C++에서 UWidget이 내부 SWidget을 생성하는 핵심 메커니즘

커스텀 UWidget을 C++로 작성할 때, RebuildWidget()ReleaseSlateResources()는 반드시 오버라이드해야 하는 핵심 함수입니다. 이 두 함수가 UMG와 Slate를 연결하는 브릿지 역할을 합니다.

C++ - 커스텀 UWidget 생성 패턴
UCLASS() class UMyCustomWidget : public UWidget { GENERATED_BODY() protected: // 내부 Slate 위젯 참조 TSharedPtr<STextBlock> MyTextBlock; // Slate 위젯 생성 - UMG가 이 위젯을 처음 사용할 때 호출 virtual TSharedRef<SWidget> RebuildWidget() override { MyTextBlock = SNew(STextBlock) .Text(FText::FromString("Hello UMG!")); return MyTextBlock.ToSharedRef(); } // Slate 리소스 해제 - 위젯이 파괴될 때 호출 virtual void ReleaseSlateResources(bool bReleaseChildren) override { Super::ReleaseSlateResources(bReleaseChildren); MyTextBlock.Reset(); } // 프로퍼티 변경 시 Slate 위젯 동기화 virtual void SynchronizeProperties() override { Super::SynchronizeProperties(); if (MyTextBlock.IsValid()) { MyTextBlock->SetText(DisplayText); } } public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Content") FText DisplayText; };
팁: SynchronizeProperties

SynchronizeProperties()는 에디터에서 프로퍼티가 변경될 때와 런타임에 UWidget의 UPROPERTY가 변경될 때 호출됩니다. 이 함수에서 UWidget의 프로퍼티 값을 내부 SWidget에 전달하여 동기화합니다. UMG가 Slate를 "제어"하는 핵심 통로입니다.

SUMMARY

핵심 요약

  • UE5의 UI 시스템은 Slate(C++ 코어) 위에 UMG(디자이너/블루프린트 레이어)가 구축된 2계층 아키텍처입니다
  • 모든 UWidget은 내부적으로 SWidget을 생성하여 래핑합니다 — RebuildWidget()이 이 연결을 담당합니다
  • UPanelWidget(다중 자식), UContentWidget(단일 자식), 리프 위젯(자식 없음)으로 위젯이 분류됩니다
  • 위젯 생명주기: CreateWidgetNativeConstructTickNativeDestruct 순서로 진행됩니다
  • SynchronizeProperties()를 통해 UWidget의 UPROPERTY 변경사항이 내부 SWidget에 전달됩니다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: UWidget 서브클래스 생성

C++에서 UWidget을 상속받는 커스텀 위젯 클래스를 만들고, RebuildWidget()에서 STextBlock을 생성하여 뷰포트에 표시해 보세요. SynchronizeProperties()로 UPROPERTY 값을 SWidget에 동기화하는 것까지 구현합니다.

실습 2: 위젯 생명주기 디버깅

UUserWidget 서브클래스에서 NativePreConstruct, NativeConstruct, NativeTick, NativeDestruct 각 함수에 UE_LOG를 추가하고, 위젯을 AddToViewport/RemoveFromParent 하면서 호출 순서를 확인해 보세요.

심화 과제

프로젝트에서 자주 사용할 3개 이상의 커스텀 UWidget(예: 라벨+값 표시, 아이콘+텍스트, 퍼센트 바)을 C++로 구현하고, Widget Blueprint에서 재사용 가능하도록 에디터 카테고리와 프로퍼티를 설정해 보세요.