실습 2: Editor 데이터 검증 플러그인 완성
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만 선언합니다.
{
"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로 빼야 합니다.
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 생명주기를 한곳에서 대칭으로 관리합니다.
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를 호출합니다.
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 검증도 실행합니다.
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. 핵심 요약
실습 2: Editor 데이터 검증 플러그인 완성 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.