본문으로 건너뛰기
Unreal Engine 모듈 · 플러그인 개발LESSON 35

실습 2: Editor 데이터 검증 플러그인 완성

난이도심화
예상 시간260분
선수지식18~27강의 Editor Plugin과 31~33강의 배포 품질

35강. 실습 2: Editor 데이터 검증 플러그인 완성

1. 이번 강의에서 해결할 문제​

메뉴, Tab, Validator, Registry Scanner가 각각 존재해도 같은 규칙과 결과 모델을 공유하지 않으면 사용자가 서로 다른 오류를 봅니다. Module 종료 시 등록 항목 하나라도 남으면 Reload·종료 Crash가 생길 수 있습니다. 최종 Editor Plugin은 한 검사 정책, 한 결과 구조, 명확한 등록·해제 순서를 가져야 합니다.

2. 학습 목표​

3. 핵심 개념​

DataGuard는 Runtime 기능이 아니라 개발 단계 품질 도구입니다. 따라서 Editor Target에서만 로드되고 Game·Server·Shipping Target에 포함되지 않습니다. Plugin이 꺼져도 게임은 실행되어야 하며, 켰을 때 프로젝트 Asset을 수정 없이 검사합니다.

최종 데이터 흐름은 다음과 같습니다.

Rule Set Asset
├─▶ DataGuard Validator ─▶ Content Browser / Commandlet 결과
└─▶ Asset Registry Scanner ─▶ Data Guard Slate Tab 목록
└─▶ 에셋 선택·재검사

4. 단계별 실습​

최종 구조를 고정합니다.

Plugins/DataGuard/
├─ Resources/Icon128.png
├─ Source/DataGuardEditor/
│ ├─ Private/
│ │ ├─ Audit/DataGuardAssetScanner.h/.cpp
│ │ ├─ Details/InteractionSettingsCustomization.h/.cpp
│ │ ├─ Rules/DataGuardRuleSet.h
│ │ ├─ Rules/DataGuardRuleSetFactory.h/.cpp
│ │ ├─ Rules/AssetDefinition_DataGuardRuleSet.h/.cpp
│ │ ├─ Validation/DataGuardNamingValidator.h/.cpp
│ │ ├─ Widgets/SDataGuardPanel.h/.cpp
│ │ ├─ DataGuardEditorModule.h
│ │ └─ DataGuardEditorModule.cpp
│ └─ DataGuardEditor.Build.cs
├─ CHANGELOG.md
├─ README.md
└─ DataGuard.uplugin

Descriptor는 Editor Module만 선언합니다.

DataGuard.uplugin
{
"FileVersion": 3,
"Version": 10000,
"VersionName": "1.0.0",
"FriendlyName": "Data Guard",
"Description": "Editor-only asset validation and audit tools.",
"Category": "Editor",
"CanContainContent": false,
"Modules": [
{
"Name": "DataGuardEditor",
"Type": "Editor",
"LoadingPhase": "Default"
}
]
}

Runtime Plugin 검사 규칙을 필수로 포함하는 배포본이라면 Descriptor의 Plugin 의존과 Build.cs 의존을 모두 명시합니다. 독립형 DataGuard 배포본이라면 ReusableInteraction 전용 Customization을 별도 Adapter Module로 빼야 합니다.

DataGuardEditor.Build.cs
using UnrealBuildTool;

public class DataGuardEditor : ModuleRules
{
public DataGuardEditor(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

PrivateDependencyModuleNames.AddRange(new[]
{
"Core",
"CoreUObject",
"Engine",
"UnrealEd",
"ToolMenus",
"Slate",
"SlateCore",
"PropertyEditor",
"DataValidation",
"AssetRegistry",
"ContentBrowser",
"AssetTools",
"ReusableInteraction"
});
}
}

Module 생명주기를 한곳에서 대칭으로 관리합니다.

DataGuardEditorModule.cpp의 통합 생명주기
void FDataGuardEditorModule::StartupModule()
{
RegisterTabSpawner();
RegisterDetails();

UToolMenus::RegisterStartupCallback(
FSimpleMulticastDelegate::FDelegate::CreateRaw(
this, &FDataGuardEditorModule::RegisterMenus));

FAssetRegistryModule& RegistryModule =
FModuleManager::LoadModuleChecked<FAssetRegistryModule>(
"AssetRegistry");
FilesLoadedHandle = RegistryModule.Get().OnFilesLoaded().AddRaw(
this, &FDataGuardEditorModule::HandleAssetRegistryReady);
}

void FDataGuardEditorModule::ShutdownModule()
{
if (FModuleManager::Get().IsModuleLoaded("AssetRegistry"))
{
FAssetRegistryModule& RegistryModule =
FModuleManager::GetModuleChecked<FAssetRegistryModule>(
"AssetRegistry");
RegistryModule.Get().OnFilesLoaded().Remove(FilesLoadedHandle);
}

if (UToolMenus::IsToolMenuUIEnabled() && UToolMenus::Get())
{
UToolMenus::UnRegisterStartupCallback(this);
UToolMenus::UnregisterOwner(this);
}

UnregisterDetails();
UnregisterTabSpawner();
}

FDelegateHandle은 Header의 멤버로 보관합니다. Asset Registry가 이미 준비된 경우에는 초기 상태를 즉시 갱신하고, 아직 수집 중인 경우에만 OnFilesLoaded를 기다립니다. 같은 Handle을 두 번 해제하지 않도록 IsValid()와 Reset을 적용합니다.

Tab의 실행 버튼은 Rule Set을 읽고 Scanner를 호출합니다.

SDataGuardPanel의 검사 흐름 축약
FReply SDataGuardPanel::HandleRunValidation()
{
Issues.Reset();

const UDataGuardRuleSet* Rules = ResolveRuleSet();
if (!IsValid(Rules))
{
StatusMessage = LOCTEXT(
"MissingRules", "No Data Guard Rule Set is configured.");
return FReply::Handled();
}

FDataGuardAssetScanner Scanner;
for (const FDataGuardPathRule& Rule : Rules->PathRules)
{
Issues.Append(Scanner.ScanBlueprintNames(
FName(*Rule.RootPath.Path),
Rule.RequiredPrefix));
}

IssueListView->RequestListRefresh();
StatusMessage = FText::Format(
LOCTEXT("IssueCount", "Scan complete: {0} issues"),
FText::AsNumber(Issues.Num()));
return FReply::Handled();
}

UI는 색상과 함께 통과, 오류 N건, Registry 준비 중, 규칙 없음 텍스트를 표시합니다. 결과 행은 키보드 포커스와 더블클릭·Enter 이동을 지원합니다.

Commandlet 검증도 실행합니다.

Data Guard 자동 검증
UnrealEditor-Cmd.exe EmptyPluginTest.uproject `
-run=DataValidation `
-unattended -nop4 -NullRHI `
-log=Saved/Logs/DataGuardValidation.log

최종 검증표​

  • Editor 메뉴가 한 번만 표시된다.
  • Dockable Tab이 닫기·재열기·Docking을 지원한다.
  • Rule Set 저장·재시작 뒤 같은 규칙이 적용된다.
  • 이름 오류가 Tab과 Data Validation 양쪽에 표시된다.
  • 결과에서 Content Browser 에셋으로 이동한다.
  • Plugin 비활성화 뒤 Project가 정상 시작된다.
  • Game·Shipping Target에 DataGuardEditor가 포함되지 않는다.
  • Editor 종료와 Plugin Reload에서 Delegate 오류가 없다.

5. 코드가 동작하는 이유​

Rule Set이 정책 원본이고 Validator와 Scanner가 이를 읽으므로 수동 UI와 자동 검사가 같은 기준을 공유합니다. Module이 모든 Editor 등록의 수명을 소유하고 종료 시 역순으로 정리합니다. Editor Type Module이므로 Runtime 패키지에는 도구 코드가 들어가지 않습니다.

6. 자주 하는 실수와 해결법​

7. 직접 실습​

8. 이해 점검 질문 3개​

9. 핵심 요약​

MINI QUIZ

실습 2: Editor 데이터 검증 플러그인 완성 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“실습 2: Editor 데이터 검증 플러그인 완성”의 위험한 선택을 피하려면 어떤 원칙을 적용해야 하나요?
  2. 문제 2‘Scanner와 Validator의 규칙 중복’ 상태에 관한 “실습 2: Editor 데이터 검증 플러그인 완성” 본문의 설명으로 가장 알맞은 것은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

35강. 실습 2: Editor 데이터 검증 플러그인 완성 미완료 상태