25 KiB
TopMenu UIToolkit 마이그레이션 작업지시서
📋 개요
UGUI 기반의 TopMenu 시스템을 UI Toolkit 기반으로 마이그레이션하는 작업입니다. 기존의 MenuItemData 구조와 TopMenuController의 public 메서드를 동일하게 유지하면서, 관심사 분리 원칙을 준수합니다.
🎯 작업 목표
- 독립적인 데이터 구조:
UTKMenuItemData,UTKTopMenuModel을 UIToolkit 전용으로 별도 구현 - Controller 호환성:
TopMenuController의 public API 동일하게 구현 - UIToolkit 전환:
TopMenuView를 UIToolkit 기반으로 재구현 - 관심사 분리: Model, View, Controller 명확히 분리
- 메모리 관리: IDisposable 구현, 이벤트 정리, 메모리 누수 방지
- 성능 최적화: 쿼리 캐싱, GC 최소화, 불필요한 리빌드 방지
- 완전한 문서화: 모든 public/protected 멤버에 XML 주석 필수
📁 파일 구조
기존 파일 (참조용)
Assets/Scripts/UVC/UI/Menu/
├── TopMenuModel.cs # MenuItemData, TopMenuModel (참조만, 재사용 X)
├── TopMenuController.cs # UGUI Controller (참조)
└── TopMenuView.cs # UGUI View (참조)
신규 파일 (생성)
Assets/Scripts/UVC/UIToolkit/Menu/
├── UTKMenuItemData.cs # ⭐ UIToolkit 전용 메뉴 데이터
├── UTKTopMenuModel.cs # ⭐ UIToolkit 전용 모델
├── UTKTopMenuController.cs # UIToolkit Controller
├── UTKTopMenuView.cs # UIToolkit View
└── UTKTopMenuItem.cs # UIToolkit 메뉴 아이템 컴포넌트
Assets/Resources/UIToolkit/Menu/
├── UTKTopMenu.uxml # 메인 메뉴 구조
├── UTKTopMenuUss.uss # 메인 메뉴 스타일
├── UTKMenuItem.uxml # 메뉴 아이템 구조
├── UTKMenuItemUss.uss # 메뉴 아이템 스타일
├── UTKSubMenuItem.uxml # 하위 메뉴 아이템 구조
└── UTKSubMenuItemUss.uss # 하위 메뉴 아이템 스타일
🔧 구현 상세
1. 데이터 레이어 (신규 구현)
1.1 UTKMenuItemData ⭐
파일 경로: Assets/Scripts/UVC/UIToolkit/Menu/UTKMenuItemData.cs
책임:
- UIToolkit 전용 메뉴 아이템 데이터 구조
- 메모리 효율적인 데이터 관리
- IDisposable 구현으로 리소스 정리
필수 구현:
#nullable enable
using System;
using System.Collections.Generic;
using UVC.UI.Commands;
namespace UVC.UIToolkit.Menu
{
/// <summary>
/// UIToolkit 메뉴 시스템에서 개별 메뉴 아이템을 나타내는 데이터 클래스입니다.
/// IDisposable을 구현하여 Command 등의 리소스를 안전하게 정리합니다.
/// </summary>
public class UTKMenuItemData : IDisposable
{
// --- 속성 ---
/// <summary>메뉴 아이템의 고유 식별자</summary>
public string ItemId { get; private set; }
/// <summary>UI에 표시될 이름 (다국어 키)</summary>
public string DisplayName { get; private set; }
/// <summary>실행될 명령</summary>
public ICommand? Command { get; private set; }
/// <summary>Command 실행 시 전달될 파라미터</summary>
public object? CommandParameter { get; set; }
/// <summary>하위 메뉴 아이템 리스트</summary>
public List<UTKMenuItemData>? SubMenuItems { get; private set; }
/// <summary>구분선 여부</summary>
public bool IsSeparator { get; private set; }
/// <summary>활성화 상태</summary>
public bool IsEnabled { get; set; }
/// <summary>단축키 문자열</summary>
public string? Shortcut { get; set; }
/// <summary>메뉴 깊이 (0: 최상위)</summary>
public int Depth { get; internal set; }
/// <summary>부모 메뉴 아이템</summary>
public UTKMenuItemData? Parent { get; internal set; }
// --- 생성자 ---
public UTKMenuItemData(
string itemId,
string displayName,
ICommand? command = null,
object? commandParameter = null,
List<UTKMenuItemData>? subMenuItems = null,
bool isSeparator = false,
bool isEnabled = true,
string? shortcut = null);
// --- 메서드 ---
/// <summary>하위 메뉴 아이템 추가</summary>
public void AddSubMenuItem(UTKMenuItemData subItem);
/// <summary>구분선 생성 팩토리 메서드</summary>
public static UTKMenuItemData CreateSeparator(string? itemId = null);
/// <summary>특정 ID의 하위 메뉴 존재 여부</summary>
public bool HasSubMenuItem(string itemId);
// --- IDisposable ---
private bool _disposed;
/// <summary>
/// 리소스를 정리합니다. Command가 IDisposable인 경우 함께 정리합니다.
/// </summary>
public void Dispose();
protected virtual void Dispose(bool disposing);
}
}
구현 지침:
-
메모리 관리:
Dispose()에서SubMenuItems재귀적으로 정리Command가IDisposable이면 함께Dispose()_disposed플래그로 중복 호출 방지
-
성능 최적화:
SubMenuItems는List<T>사용 (배열 변환 지양)- 문자열 비교는
StringComparison.Ordinal사용 - 깊이/부모 설정은 생성 시 한 번만 수행
-
주석:
- 모든 public/protected 멤버에 XML 주석
- 예외 상황 명시 (
<exception>태그) - 사용 예제 제공 (
<example>태그)
1.2 UTKTopMenuModel ⭐
파일 경로: Assets/Scripts/UVC/UIToolkit/Menu/UTKTopMenuModel.cs
책임:
- 메뉴 아이템 컬렉션 관리
- 메뉴 아이템 검색/추가/제거
- IDisposable 구현으로 전체 메뉴 데이터 정리
필수 구현:
#nullable enable
using System;
using System.Collections.Generic;
namespace UVC.UIToolkit.Menu
{
/// <summary>
/// UIToolkit 메뉴 시스템의 데이터 모델입니다.
/// 메뉴 아이템 컬렉션을 관리하고 검색 기능을 제공합니다.
/// </summary>
public class UTKTopMenuModel : IDisposable
{
/// <summary>최상위 메뉴 아이템 리스트</summary>
public List<UTKMenuItemData> MenuItems { get; private set; }
// --- 생성자 ---
public UTKTopMenuModel();
// --- 메서드 ---
/// <summary>메뉴 아이템 추가</summary>
public void AddMenuItem(UTKMenuItemData item);
/// <summary>메뉴 아이템 제거</summary>
public bool RemoveMenuItem(string itemId);
/// <summary>재귀적으로 메뉴 아이템 검색</summary>
public UTKMenuItemData? FindMenuItem(string itemId);
/// <summary>모든 메뉴 아이템 초기화</summary>
public void ClearMenuItems();
// --- IDisposable ---
private bool _disposed;
/// <summary>
/// 모든 메뉴 아이템을 정리합니다.
/// </summary>
public void Dispose();
protected virtual void Dispose(bool disposing);
}
}
구현 지침:
-
메모리 관리:
Dispose()에서 모든MenuItems재귀적으로 정리ClearMenuItems()도 각 아이템Dispose()호출
-
성능 최적화:
FindMenuItem()은 캐싱 고려 (Dictionary<string, UTKMenuItemData>)- 검색 빈도가 높으면 인덱스 사용
-
주석:
- 모든 메서드에 XML 주석
- 시간 복잡도 명시 (
<remarks>태그)
2. Controller 레이어
2.1 UTKTopMenuController
파일 경로: Assets/Scripts/UVC/UIToolkit/Menu/UTKTopMenuController.cs
책임:
- UTKTopMenuModel과 UTKTopMenuView 중재
- 메뉴 아이템 추가/제거/업데이트 로직
- Command 실행 및 Undo/Redo 연동
- 언어 변경 처리
- 메모리 관리 (이벤트 구독/해제)
필수 구현 메서드 (TopMenuController와 동일한 public API):
#nullable enable
using UnityEngine;
using UVC.UI.Menu;
using UVC.UI.Commands;
using UVC.Locale;
namespace UVC.UIToolkit.Menu
{
public class UTKTopMenuController : MonoBehaviour
{
// --- 필수 Public 메서드 (TopMenuController와 동일) ---
/// <summary>메뉴 초기화</summary>
public virtual void Initialize();
/// <summary>메뉴 아이템 추가</summary>
public void AddMenuItem(MenuItemData newItem);
/// <summary>메뉴 아이템 제거</summary>
public void RemoveMenuItem(string itemId);
/// <summary>메뉴 아이템 활성화 상태 변경</summary>
public virtual void SetMenuItemEnabled(string itemId, bool isEnabled);
/// <summary>메뉴 아이템 단축키 변경</summary>
public virtual void SetMenuItemShortcut(string itemId, string shortcut);
/// <summary>모든 단축키 갱신</summary>
public virtual void RefreshAllShortcuts();
// --- Protected 메서드 ---
protected virtual void Awake();
protected virtual void Start();
protected virtual void OnDestroy();
protected virtual void HandleMenuItemClicked(MenuItemData clickedItemData);
protected virtual void ExecuteCommand(ICommand command, object? parameter = null);
protected virtual void HandleLanguageChanged(string newLanguageCode);
protected MenuItemData? FindMenuItemRecursive(List<MenuItemData> items, string itemId);
}
}
구현 지침:
-
메모리 관리:
OnDestroy()에서model.Dispose()호출view.OnMenuItemClicked이벤트 구독 해제LocalizationManager.OnLanguageChanged구독 해제
-
성능 최적화:
FindMenuItem()은model에 위임 (캐시 활용)- 불필요한 View 업데이트 방지 (상태 변경 시에만)
-
주석:
- 모든 public/protected 메서드에 XML 주석
- Command 실행 흐름 문서화
- 예외 케이스 명시
3. View 레이어
3.1 UTKTopMenuView
파일 경로: Assets/Scripts/UVC/UIToolkit/Menu/UTKTopMenuView.cs
책임:
- VisualElement 기반 UI 생성 및 관리
- 메뉴 아이템 표시/숨김
- 사용자 입력 이벤트 전달
필수 속성/메서드:
#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UI.Menu;
namespace UVC.UIToolkit.Menu
{
[UxmlElement]
public partial class UTKTopMenuView : VisualElement, IDisposable
{
// --- Constants ---
private const string UXML_PATH = "UIToolkit/Menu/UTKTopMenu";
private const string USS_PATH = "UIToolkit/Menu/UTKTopMenuUss";
// --- 필수 Public 메서드 (TopMenuView와 동일) ---
/// <summary>메뉴 아이템 클릭 이벤트</summary>
public event Action<MenuItemData>? OnMenuItemClicked;
/// <summary>메뉴 아이템 생성</summary>
public virtual void CreateMenuItems(List<MenuItemData> items, VisualElement parentContainer, int depth = 0);
/// <summary>메뉴 아이템 제거</summary>
public virtual void ClearMenuItems();
/// <summary>모든 메뉴 텍스트 업데이트 (언어 변경 시)</summary>
public virtual void UpdateAllMenuTexts(List<MenuItemData> items);
/// <summary>단축키 텍스트 업데이트</summary>
public virtual void UpdateShortcutText(string itemId, string shortcut);
/// <summary>모든 단축키 업데이트</summary>
public virtual void UpdateAllShortcuts(List<MenuItemData> items);
/// <summary>메뉴 아이템 GameObject 가져오기</summary>
public bool TryGetMenuItemElement(string itemId, out VisualElement menuItemElement);
/// <summary>모든 하위 메뉴 닫기</summary>
public virtual void CloseAllOpenSubMenus();
// --- IDisposable ---
public void Dispose();
}
}
구현 지침:
-
Unity 6 방식 사용:
[UxmlElement]어트리뷰트partial class선언[UxmlAttribute]케밥 케이스 사용
-
VisualElement 기반 구현:
- UXML 로드:
Resources.Load<VisualTreeAsset>(UXML_PATH) - USS 적용:
styleSheets.Add() - 쿼리 결과 캐싱:
Q<T>()결과를 필드에 저장
- UXML 로드:
-
이벤트 등록/해제:
RegisterCallback<ClickEvent>()/UnregisterCallback<ClickEvent>()- 주의:
RegisterValueChangedCallback사용 금지
-
테마 연동:
UTKThemeManager.Instance.ApplyThemeToElement(this)OnThemeChanged구독
-
메모리 관리 ⭐:
IDisposable구현 필수OnDetachFromPanelEvent에서 모든 이벤트 해제_menuItemElementsDictionary 정리_subMenuContainersDictionary 정리- 모든 EventCallback 필드 null 처리
-
성능 최적화 ⭐:
Q<T>()호출은 생성 시 한 번만 (필드 캐싱)- 메뉴 아이템 100개 이상에서도 렉 없어야 함
- GC Alloc 최소화: LINQ 지양, foreach 사용
- 불필요한
MarkDirtyRepaint()호출 방지
-
주석 작성 ⭐:
- 모든 public/protected 멤버에 XML 주석 필수
- 복잡한 로직은 인라인 주석으로 설명
- 예외 상황 명시 (
<exception>태그) - 사용 예제 제공 (
<example>태그)
3.2 UTKTopMenuItem
파일 경로: Assets/Scripts/UVC/UIToolkit/Menu/UTKTopMenuItem.cs
책임:
- 개별 메뉴 아이템 UI 표현
- 클릭 이벤트 처리
- 활성화/비활성화 상태 표시
구조:
#nullable enable
using UnityEngine.UIElements;
using UVC.UI.Menu;
namespace UVC.UIToolkit.Menu
{
[UxmlElement]
public partial class UTKTopMenuItem : VisualElement, IDisposable
{
// --- UXML/USS ---
private const string UXML_PATH = "UIToolkit/Menu/UTKMenuItem";
private const string USS_PATH = "UIToolkit/Menu/UTKMenuItemUss";
// --- UXML Attributes ---
[UxmlAttribute("item-id")]
public string ItemId { get; set; } = "";
[UxmlAttribute("display-name")]
public string DisplayName { get; set; } = "";
[UxmlAttribute("is-enabled")]
public bool IsEnabled { get; set; } = true;
[UxmlAttribute("shortcut")]
public string? Shortcut { get; set; }
// --- Events ---
public event Action<MenuItemData>? OnClicked;
// --- Constructor ---
public UTKTopMenuItem();
// --- Public Methods ---
public void SetData(MenuItemData data);
public void UpdateEnabled(bool enabled);
public void UpdateShortcut(string shortcut);
// --- IDisposable ---
public void Dispose();
}
}
4. UXML/USS 리소스
4.1 UTKTopMenu.uxml
경로: Assets/Resources/UIToolkit/Menu/UTKTopMenu.uxml
구조:
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit.Menu">
<ui:VisualElement name="top-menu-container" class="top-menu">
<ui:VisualElement name="menu-container" class="top-menu__items" />
<ui:VisualElement name="blocker" class="top-menu__blocker" style="display: none;" />
</ui:VisualElement>
</ui:UXML>
4.2 UTKTopMenuUss.uss
경로: Assets/Resources/UIToolkit/Menu/UTKTopMenuUss.uss
스타일 (StyleGuide 참조):
.top-menu {
flex-direction: row;
width: 100%;
height: 40px;
background-color: var(--color-bg-secondary);
border-bottom-width: 1px;
border-bottom-color: var(--color-border);
}
.top-menu__items {
flex-direction: row;
flex-grow: 1;
}
.top-menu__blocker {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.001);
}
4.3 UTKMenuItem.uxml
경로: Assets/Resources/UIToolkit/Menu/UTKMenuItem.uxml
구조:
<ui:UXML xmlns:ui="UnityEngine.UIElements">
<ui:Button name="menu-button" class="menu-item">
<ui:Label name="label" class="menu-item__label" />
<ui:VisualElement name="arrow" class="menu-item__arrow" style="display: none;" />
</ui:Button>
</ui:UXML>
4.4 UTKMenuItemUss.uss
경로: Assets/Resources/UIToolkit/Menu/UTKMenuItemUss.uss
스타일:
.menu-item {
padding: 0 12px;
height: 40px;
border-width: 0;
background-color: transparent;
transition: background-color 0.2s;
}
.menu-item:hover {
background-color: var(--color-bg-hover);
}
.menu-item:active {
background-color: var(--color-bg-active);
}
.menu-item:disabled {
opacity: 0.5;
}
.menu-item__label {
-unity-font-style: normal;
font-size: 14px;
color: var(--color-text-primary);
}
.menu-item__arrow {
width: 8px;
height: 8px;
margin-left: 4px;
background-image: url('project://database/Assets/Resources/UIToolkit/Icons/arrow_down.png');
}
4.5 UTKSubMenuItem.uxml
경로: Assets/Resources/UIToolkit/Menu/UTKSubMenuItem.uxml
구조:
<ui:UXML xmlns:ui="UnityEngine.UIElements">
<ui:Button name="submenu-button" class="submenu-item">
<ui:Label name="label" class="submenu-item__label" />
<ui:Label name="shortcut" class="submenu-item__shortcut" />
<ui:VisualElement name="arrow" class="submenu-item__arrow" style="display: none;" />
</ui:Button>
</ui:UXML>
4.6 UTKSubMenuItemUss.uss
경로: Assets/Resources/UIToolkit/Menu/UTKSubMenuItemUss.uss
스타일:
.submenu-item {
flex-direction: row;
justify-content: space-between;
padding: 8px 16px;
min-width: 200px;
height: 32px;
border-width: 0;
background-color: var(--color-bg-primary);
}
.submenu-item:hover {
background-color: var(--color-bg-hover);
}
.submenu-item__label {
font-size: 14px;
color: var(--color-text-primary);
}
.submenu-item__shortcut {
font-size: 12px;
color: var(--color-text-secondary);
margin-left: 24px;
}
.submenu-item__arrow {
width: 8px;
height: 8px;
margin-left: 8px;
background-image: url('project://database/Assets/Resources/UIToolkit/Icons/arrow_right.png');
}
🔄 마이그레이션 순서
Phase 1: 기본 구조 구축
- ✅ 폴더 생성:
Assets/Scripts/UVC/UIToolkit/Menu/ - ✅ 폴더 생성:
Assets/Resources/UIToolkit/Menu/ - ✅ UXML/USS 파일 생성 (6개)
- ✅
UTKMenuItemData.cs구현 ⭐- IDisposable 구현
- XML 주석 작성
- ✅
UTKTopMenuModel.cs구현 ⭐- IDisposable 구현
- 검색 최적화 (Dictionary 캐싱)
- XML 주석 작성
- ✅
UTKTopMenuItem.cs구현- IDisposable 구현
- 이벤트 정리
- XML 주석 작성
- ✅
UTKTopMenuView.cs기본 구조 구현- IDisposable 구현
- 쿼리 캐싱
- XML 주석 작성
- ✅
UTKTopMenuController.cs기본 구조 구현- Model/View 참조 정리
- XML 주석 작성
Phase 2: 핵심 기능 구현
- ✅
CreateMenuItems()구현 (재귀적 메뉴 생성) - ✅
ToggleSubMenuDisplay()구현 (하위 메뉴 표시/숨김) - ✅
CloseAllOpenSubMenus()구현 - ✅ 메뉴 클릭 이벤트 처리
- ✅ Command 실행 로직
Phase 3: 상태 관리
- ✅
SetMenuItemEnabled()구현 - ✅
SetMenuItemShortcut()구현 - ✅ 언어 변경 처리 (
HandleLanguageChanged) - ✅ 단축키 갱신 (
RefreshAllShortcuts)
Phase 4: 테마 및 스타일
- ✅ UTKThemeManager 연동
- ✅ StyleGuide 스타일 적용
- ✅ 라이트/다크 테마 지원
Phase 5: 테스트, 최적화, 문서화 ⭐
- ✅ 샘플 씬 생성 및 기능 테스트
- ✅ 메모리 누수 점검 (필수):
- Unity Profiler로 메모리 확인
- 씬 전환 시 메모리 증가 없는지 확인
- IDisposable 정상 호출 확인
- 이벤트 구독 해제 확인
- ✅ 성능 최적화 (필수):
- Unity Profiler로 CPU/GC 확인
- 메뉴 아이템 100개 생성 테스트
- Update 루프에서 GC Alloc 0 확인
- 쿼리 캐싱 적용 확인
- ✅ 완전한 문서화 (필수):
- 모든 public 멤버: XML 주석 작성
- 모든 protected 멤버: XML 주석 작성
- 복잡한 로직: 인라인 주석 작성
- README.md 작성 (사용법, 예제)
⚠️ 주의사항
필수 준수 사항 (위반 시 재작업)
#nullable enable파일 선두에 필수- Unity 6 방식:
[UxmlElement],partial class,[UxmlAttribute]사용 - 이벤트 등록:
RegisterCallback<ChangeEvent<T>>()사용 (RegisterValueChangedCallback 금지) - UXML/USS 네이밍:
- UXML:
UTKTopMenu.uxml - USS:
UTKTopMenuUss.uss(접미사Uss필수)
- UXML:
- 케밥 케이스:
[UxmlAttribute("item-id")]소문자 + 하이픈 - IDisposable 구현 ⭐:
- 모든 데이터/View 클래스에 필수
_disposed플래그로 중복 호출 방지RegisterCallback↔UnregisterCallback대칭DetachFromPanelEvent에서 정리- 하위 객체도 재귀적으로 Dispose
메모리 관리 체크리스트 ⭐
- 모든
new EventCallback<T>()필드화 및 해제 - 모든
RegisterCallback()대칭적으로UnregisterCallback() UTKThemeManager.OnThemeChanged구독 해제LocalizationManager.OnLanguageChanged구독 해제Dictionary<>전체 Clear() 호출- 하위 메뉴 재귀적 Dispose
- Unity Profiler로 메모리 누수 확인
성능 최적화 체크리스트 ⭐
Q<T>()결과 필드 캐싱 (생성 시 1회만)- Update/OnGUI에서 GC Alloc 0
- LINQ 사용 금지 (foreach 사용)
- 문자열 연결 시
StringBuilder사용 - 불필요한
MarkDirtyRepaint()제거 - 메뉴 아이템 100개 생성 시 60fps 유지
- Unity Profiler로 CPU/GC 확인
문서화 체크리스트 ⭐
- 모든 public 멤버:
<summary>태그 - 모든 protected 멤버:
<summary>태그 - 모든 매개변수:
<param>태그 - 모든 반환값:
<returns>태그 - 예외 발생 가능:
<exception>태그 - 복잡한 로직:
<remarks>태그 또는 인라인 주석 - 사용 예제:
<example>태그 (Controller, View) - README.md 작성
코드 스타일
- ✅ 한국어 주석 (XML 문서 포함)
- ✅ BEM 네이밍 (CSS 클래스)
- ✅ 파일 경로 참조:
file_path:line_number형식
📝 테스트 체크리스트
기능 테스트
- 메뉴 아이템 생성/삭제
- 하위 메뉴 열기/닫기
- 메뉴 클릭 시 Command 실행
- 활성화/비활성화 상태 변경
- 단축키 표시 및 갱신
- 언어 변경 시 텍스트 업데이트
- 구분선 표시
- 외부 클릭 시 하위 메뉴 닫기
성능 테스트
- 메뉴 아이템 100개 생성 시 렉 없음
- 메모리 누수 없음 (Profiler 확인)
- GC Alloc 최소화 (Update 루프에서 0)
호환성 테스트
- TopMenuController public API 호환성
- MenuItemData 재사용 가능
- 기존 프로젝트와 동시 사용 가능 (UGUI/UIToolkit)
📚 참고 자료
CLAUDE.md 관련 섹션
StyleGuide 이미지
StyleGuide/style_guide_Menu.pngStyleGuide/style_guide_Buttons.pngStyleGuide/style_guide_Typography.png
기존 구현 참조
Assets/Scripts/UVC/UI/Menu/TopMenuController.cs(로직)Assets/Scripts/UVC/UI/Menu/TopMenuView.cs(View 패턴)Assets/Scripts/UVC/UI/Menu/TopMenuModel.cs(데이터 구조)
🎓 예상 학습 내용
UIToolkit 특화
- VisualElement 계층 구조
- UXML 템플릿 인스턴스화
- USS 선택자 우선순위
- 이벤트 버블링/캡처링
schedule.Execute()활용
패턴 적용
- MVVM 패턴 (ViewModel은 Controller가 대신)
- 이벤트 기반 통신
- 재귀적 UI 생성
- 상태 동기화 (Model ↔ View)
✅ 완료 조건 (모두 충족 필수)
기능 완료
- 모든 파일 생성 완료 (UTKMenuItemData, UTKTopMenuModel 포함)
- TopMenuController public API 동일하게 구현
- 샘플 씬에서 정상 동작 확인
- 모든 기능 테스트 통과
메모리 관리 완료 ⭐
- 모든 클래스 IDisposable 구현
- Unity Profiler로 메모리 누수 0 확인
- 씬 전환 10회 후 메모리 증가 없음
- 이벤트 구독/해제 대칭 확인
성능 완료 ⭐
- Unity Profiler로 GC Alloc 0 확인 (Update 루프)
- 메뉴 아이템 100개 생성 시 60fps 유지
- 쿼리 캐싱 적용 확인
- CPU 프로파일링 이상 없음
문서화 완료 ⭐
- 모든 public/protected 멤버 XML 주석 완료
- 복잡한 로직 인라인 주석 완료
- README.md 작성 완료
- 사용 예제 코드 작성 완료
스타일 완료
- StyleGuide 스타일 적용
- BEM 네이밍 준수
- CLAUDE.md 가이드 100% 준수
작성일: 2026-02-13 작성자: Claude Code Assistant 버전: 1.0