diff --git a/plans/mng-menu-system-plan.md b/plans/mng-menu-system-plan.md new file mode 100644 index 0000000..1994d66 --- /dev/null +++ b/plans/mng-menu-system-plan.md @@ -0,0 +1,485 @@ +# MNG 메뉴 시스템: DB 기반 동적 메뉴 전환 계획 + +> 작성일: 2025-12-16 +> 목적: mng 사이드바를 DB 기반으로 전환하여 직원별 권한에 따라 메뉴 동적 표시 +> 선택: **Option A - DB 메뉴 기반** + +--- + +## 1. 현재 시스템 분석 + +### 1.1 현재 구조 (AS-IS) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 현재 mng 메뉴 시스템 │ +├─────────────────────────────────────────────────────────────────┤ +│ sidebar.blade.php (하드코딩) │ +│ ├── 일반 메뉴 (7개 그룹) │ +│ ├── 개발도구 메뉴 │ +│ └── R&D Labs 메뉴 │ +├─────────────────────────────────────────────────────────────────┤ +│ 권한 체크: hq.member 미들웨어만 (HQ 소속 확인) │ +│ 메뉴별 권한 체크: 없음 (전체 접근) │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 1.2 목표 구조 (TO-BE) + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 목표 mng 메뉴 시스템 │ +├─────────────────────────────────────────────────────────────────┤ +│ DB (menus 테이블, tenant_id=1) │ +│ ├── 일반 메뉴 (역할/부서/개인 권한으로 제어) │ +│ ├── 개발도구 메뉴 (슈퍼관리자 전용) │ +│ └── R&D Labs 메뉴 (슈퍼관리자 전용) │ +├─────────────────────────────────────────────────────────────────┤ +│ 동적 사이드바 렌더링: SidebarMenuService → Blade Component │ +│ 권한 체크: 메뉴별 permission (menu:{id}.view) │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 1.3 DB 테이블 구조 + +**menus 테이블** (기존) +``` +id, tenant_id, parent_id, global_menu_id +name, url, icon, sort_order +is_active, hidden, is_customized, is_external, external_url +created_by, updated_by, deleted_by, created_at, updated_at, deleted_at +``` + +**permissions 테이블** (Spatie) +``` +id, tenant_id, name, guard_name, created_at, updated_at +``` + +**권한 연결 테이블** +- `role_has_permissions`: 역할-권한 매핑 +- `department_permissions`: 부서-권한 매핑 (is_allowed) +- `user_permission_overrides`: 개인-권한 오버라이드 (is_allowed) + +--- + +## 2. 권한 체계 설계 + +### 2.1 권한 우선순위 + +``` +개인 DENY > 개인 ALLOW > 부서 DENY > 부서 ALLOW > 역할 권한 > 기본 거부 +``` + +### 2.2 메뉴 권한 명명 규칙 + +``` +menu:{menu_id}.view # 메뉴 조회 (사이드바 표시) +menu:{menu_id}.create # 생성 권한 +menu:{menu_id}.update # 수정 권한 +menu:{menu_id}.delete # 삭제 권한 +``` + +### 2.3 특수 메뉴 처리 + +| 메뉴 유형 | 권한 처리 | +|-----------|----------| +| 일반 메뉴 | 역할/부서/개인 권한으로 제어 | +| 개발도구 | `is_super_admin` 체크 또는 특별 권한 | +| R&D Labs | `is_super_admin` 체크 또는 특별 권한 | + +--- + +## 3. 개발 계획 + +### Phase 1: DB 스키마 및 시딩 (1-2일) + +#### 3.1.1 mng 메뉴용 컬럼 추가 (선택적) + +```php +// 마이그레이션: add_mng_flag_to_menus_table +Schema::table('menus', function (Blueprint $table) { + $table->string('menu_type', 20)->default('normal') + ->comment('메뉴 유형: normal, dev_tool, lab') + ->after('external_url'); + $table->string('route_name', 100)->nullable() + ->comment('Laravel 라우트 이름') + ->after('menu_type'); +}); +``` + +#### 3.1.2 mng 메뉴 시더 생성 + +```php +// database/seeders/MngMenuSeeder.php +class MngMenuSeeder extends Seeder +{ + public function run(): void + { + $tenantId = 1; // HQ 테넌트 + + $menus = [ + // 일반 메뉴 + ['name' => '대시보드', 'url' => '/dashboard', 'icon' => 'home', 'route_name' => 'dashboard', 'menu_type' => 'normal'], + + // 그룹: 프로젝트 관리 + ['name' => '프로젝트 관리', 'url' => null, 'icon' => 'folder', 'menu_type' => 'normal', 'children' => [ + ['name' => '프로젝트 대시보드', 'url' => '/project-management', 'route_name' => 'pm.index'], + ['name' => '프로젝트', 'url' => '/project-management/projects', 'route_name' => 'pm.projects.index'], + ['name' => '일일 스크럼', 'url' => '/daily-logs', 'route_name' => 'daily-logs.index'], + ]], + + // ... 기타 메뉴 그룹 + + // 개발도구 (슈퍼관리자 전용) + ['name' => '개발 도구', 'url' => null, 'icon' => 'cog', 'menu_type' => 'dev_tool', 'children' => [ + ['name' => 'API 플로우 테스터', 'url' => '/dev-tools/flow-tester', 'route_name' => 'dev-tools.flow-tester.index'], + ['name' => 'API 요청 로그', 'url' => '/dev-tools/api-logs', 'route_name' => 'dev-tools.api-logs.index'], + ]], + + // R&D Labs (슈퍼관리자 전용) + ['name' => 'R&D Labs', 'url' => null, 'icon' => 'beaker', 'menu_type' => 'lab', 'children' => [ + // S, A, M 탭 구조 + ]], + ]; + + $this->seedMenus($tenantId, $menus); + } +} +``` + +### Phase 2: 사용자별 메뉴 조회 서비스 (2-3일) + +#### 3.2.1 SidebarMenuService 생성 + +```php +// app/Services/SidebarMenuService.php +class SidebarMenuService +{ + /** + * 현재 사용자가 접근 가능한 메뉴 트리 조회 + */ + public function getUserMenuTree(?User $user = null): Collection + { + $user = $user ?? auth()->user(); + $tenantId = session('selected_tenant_id', 1); + + // 1. 테넌트의 모든 활성 메뉴 조회 + $allMenus = Menu::where('tenant_id', $tenantId) + ->where('is_active', true) + ->where('hidden', false) + ->orderBy('sort_order') + ->get(); + + // 2. 슈퍼관리자는 모든 메뉴 표시 + if ($user->is_super_admin) { + return $this->buildMenuTree($allMenus); + } + + // 3. 일반 사용자: 권한 기반 필터링 + $permittedMenuIds = $this->getPermittedMenuIds($user, $tenantId); + + // 4. 개발도구/Labs 제외 (일반 사용자) + $filteredMenus = $allMenus->filter(function ($menu) use ($permittedMenuIds) { + // 개발도구/Labs는 일반 사용자에게 표시 안함 + if (in_array($menu->menu_type, ['dev_tool', 'lab'])) { + return false; + } + return in_array($menu->id, $permittedMenuIds); + }); + + return $this->buildMenuTree($filteredMenus); + } + + /** + * 사용자가 접근 가능한 메뉴 ID 목록 조회 + * 우선순위: 개인 DENY > 개인 ALLOW > 부서 DENY > 부서 ALLOW > 역할 + */ + private function getPermittedMenuIds(User $user, int $tenantId): array + { + // 역할 기반 권한 + $rolePermissions = $this->getRoleMenuPermissions($user, $tenantId); + + // 부서 기반 권한 (ALLOW/DENY) + $deptPermissions = $this->getDepartmentMenuPermissions($user, $tenantId); + + // 개인 오버라이드 (ALLOW/DENY) + $userOverrides = $this->getUserMenuOverrides($user, $tenantId); + + // 권한 병합 (우선순위 적용) + return $this->mergePermissions($rolePermissions, $deptPermissions, $userOverrides); + } + + private function buildMenuTree(Collection $menus, ?int $parentId = null): Collection + { + return $menus->where('parent_id', $parentId) + ->map(function ($menu) use ($menus) { + $menu->children = $this->buildMenuTree($menus, $menu->id); + return $menu; + }); + } +} +``` + +### Phase 3: 동적 사이드바 컴포넌트 (2-3일) + +#### 3.3.1 Blade 컴포넌트 구조 + +``` +resources/views/ +├── components/ +│ └── sidebar/ +│ ├── menu-tree.blade.php # 메뉴 트리 전체 +│ ├── menu-group.blade.php # 그룹 (접기/펼치기) +│ ├── menu-item.blade.php # 개별 메뉴 아이템 +│ └── menu-icon.blade.php # 아이콘 렌더링 +└── partials/ + └── sidebar-dynamic.blade.php # 동적 사이드바 (기존 대체) +``` + +#### 3.3.2 메뉴 트리 컴포넌트 + +```blade +{{-- components/sidebar/menu-tree.blade.php --}} +@props(['menus']) + + +``` + +#### 3.3.3 ViewServiceProvider에서 메뉴 공유 + +```php +// app/Providers/ViewServiceProvider.php +class ViewServiceProvider extends ServiceProvider +{ + public function boot(): void + { + View::composer('partials.sidebar-dynamic', function ($view) { + $menuService = app(SidebarMenuService::class); + $view->with('sidebarMenus', $menuService->getUserMenuTree()); + }); + } +} +``` + +### Phase 4: 라우트 권한 미들웨어 (1-2일) + +#### 3.4.1 메뉴 권한 체크 미들웨어 + +```php +// app/Http/Middleware/CheckMenuPermission.php +class CheckMenuPermission +{ + public function handle(Request $request, Closure $next, ?string $permission = null) + { + $user = $request->user(); + + // 슈퍼관리자는 패스 + if ($user->is_super_admin) { + return $next($request); + } + + // 권한 체크 + $routeName = $request->route()->getName(); + $menu = Menu::where('route_name', $routeName)->first(); + + if (!$menu) { + return $next($request); // 메뉴 없으면 패스 + } + + $permissionName = $permission ?? "menu:{$menu->id}.view"; + + if (!$this->hasMenuPermission($user, $menu, $permissionName)) { + abort(403, '접근 권한이 없습니다.'); + } + + return $next($request); + } +} +``` + +#### 3.4.2 라우트에 미들웨어 적용 + +```php +// routes/web.php +Route::middleware(['auth', 'hq.member', 'menu.permission'])->group(function () { + // 기존 라우트들... +}); +``` + +--- + +## 4. 마이그레이션 전략 + +### 4.1 단계별 전환 + +``` +Phase 1: 준비 (하드코딩 + DB 병행) +├── DB에 mng 메뉴 시딩 +├── SidebarMenuService 개발 +└── 기존 sidebar.blade.php 유지 + +Phase 2: 테스트 (환경변수로 전환) +├── .env에 MNG_DYNAMIC_SIDEBAR=false +├── 동적 사이드바 개발 완료 +└── 슈퍼관리자만 동적 사이드바 테스트 + +Phase 3: 전환 (동적 사이드바 활성화) +├── MNG_DYNAMIC_SIDEBAR=true +├── 권한 시딩 및 역할 배정 +└── 기존 sidebar.blade.php 백업 + +Phase 4: 안정화 +├── 하드코딩 사이드바 제거 +├── 권한 관리 UI 활성화 +└── 문서화 완료 +``` + +### 4.2 롤백 계획 + +```php +// partials/sidebar.blade.php +@if(config('app.mng_dynamic_sidebar', false)) + @include('partials.sidebar-dynamic') +@else + @include('partials.sidebar-static') // 기존 하드코딩 +@endif +``` + +--- + +## 5. 파일 변경 목록 + +### 신규 생성 + +| 파일 | 설명 | +|------|------| +| `database/migrations/xxxx_add_menu_type_to_menus.php` | menu_type, route_name 컬럼 추가 | +| `database/seeders/MngMenuSeeder.php` | mng 메뉴 시더 | +| `database/seeders/MngMenuPermissionSeeder.php` | mng 메뉴 권한 시더 | +| `app/Services/SidebarMenuService.php` | 사용자별 메뉴 조회 | +| `app/Http/Middleware/CheckMenuPermission.php` | 메뉴 권한 미들웨어 | +| `app/Providers/ViewServiceProvider.php` | 뷰 컴포저 | +| `resources/views/partials/sidebar-dynamic.blade.php` | 동적 사이드바 | +| `resources/views/components/sidebar/*.blade.php` | 사이드바 컴포넌트들 | + +### 수정 + +| 파일 | 변경 내용 | +|------|----------| +| `app/Http/Kernel.php` | CheckMenuPermission 미들웨어 등록 | +| `config/app.php` | mng_dynamic_sidebar 설정 추가 | +| `routes/web.php` | 미들웨어 적용 | +| `resources/views/partials/sidebar.blade.php` | 조건부 렌더링 | + +--- + +## 6. 예상 일정 + +| Phase | 작업 | 예상 기간 | +|-------|------|----------| +| Phase 1 | DB 스키마 및 시딩 | 1-2일 | +| Phase 2 | SidebarMenuService | 2-3일 | +| Phase 3 | 동적 사이드바 컴포넌트 | 2-3일 | +| Phase 4 | 권한 미들웨어 | 1-2일 | +| 테스트 | 통합 테스트 및 버그 수정 | 2-3일 | +| **총합** | | **8-13일** | + +--- + +## 7. 체크리스트 + +### 개발 전 + +- [ ] 현재 mng 메뉴 목록 완전히 정리 (그룹/항목/라우트) +- [ ] 권한 명명 규칙 확정 +- [ ] 개발도구/Labs 접근 정책 확정 + +### Phase 1 완료 조건 + +- [ ] 마이그레이션 실행 성공 +- [ ] mng 메뉴 시더 실행 성공 +- [ ] DB에 모든 mng 메뉴 존재 확인 + +### Phase 2 완료 조건 + +- [ ] SidebarMenuService 단위 테스트 통과 +- [ ] 슈퍼관리자 전체 메뉴 조회 확인 +- [ ] 일반 사용자 권한 기반 필터링 확인 + +### Phase 3 완료 조건 + +- [ ] 동적 사이드바 렌더링 정상 +- [ ] 메뉴 접기/펼치기 동작 +- [ ] 활성 메뉴 하이라이트 동작 +- [ ] 사이드바 collapse 상태 동작 + +### Phase 4 완료 조건 + +- [ ] 미들웨어 권한 체크 동작 +- [ ] 403 에러 페이지 표시 +- [ ] 권한 없는 메뉴 URL 직접 접근 차단 + +### 전환 완료 조건 + +- [ ] 모든 테스트 통과 +- [ ] 기존 기능 동일 동작 확인 +- [ ] 성능 영향 최소화 확인 (캐싱) +- [ ] 롤백 가능 확인 + +--- + +## 8. 추가 고려사항 + +### 8.1 캐싱 전략 + +```php +// 사용자별 메뉴 캐싱 (권한 변경 시 무효화) +Cache::remember("user:{$userId}:menus", 3600, function () use ($userId) { + return $this->getUserMenuTree(User::find($userId)); +}); +``` + +### 8.2 권한 변경 시 캐시 무효화 + +```php +// 역할 권한 변경 시 +Cache::tags(['menus'])->flush(); + +// 개인 권한 변경 시 +Cache::forget("user:{$userId}:menus"); +``` + +### 8.3 감사 로그 + +```php +// 메뉴 접근 로그 (선택적) +AuditLog::create([ + 'action' => 'menu_access', + 'target_type' => 'menu', + 'target_id' => $menu->id, + 'actor_id' => auth()->id(), +]); +``` + +--- + +## 9. 다음 단계 + +이 계획을 승인하시면 다음 순서로 진행합니다: + +1. **현재 mng 메뉴 전체 목록 정리** (그룹/항목/라우트/아이콘) +2. **마이그레이션 및 시더 작성** +3. **SidebarMenuService 개발** +4. **동적 사이드바 컴포넌트 개발** +5. **권한 미들웨어 적용** +6. **테스트 및 전환** + +진행하시겠습니까? diff --git a/projects/migration-5130-mng/MIGRATION_TRACKER.md b/projects/migration-5130-mng/MIGRATION_TRACKER.md new file mode 100644 index 0000000..49f7683 --- /dev/null +++ b/projects/migration-5130-mng/MIGRATION_TRACKER.md @@ -0,0 +1,167 @@ +# 5130 → MNG 마이그레이션 작업 추적 + +> **시작일**: 2025-12-16 +> **현재 상태**: ✅ Phase 1 완료 +> **마지막 업데이트**: 2025-12-16 + +--- + +## 📊 전체 진행 현황 + +| Phase | 상태 | 완료 | 전체 | 진행률 | +|-------|------|------|------|--------| +| Phase 1: 레이아웃 변환 | ✅ 완료 | 13 | 13 | 100% | +| Phase 2: AI 기능 구현 | ⏳ 대기 | 0 | 10 | 0% | +| Phase 3: Management 구현 | ⏳ 대기 | 0 | 11 | 0% | +| Phase 4: Strategy placeholder | ⏳ 대기 | 0 | 3 | 0% | +| **전체** | | **14** | **38** | **36.8%** | + +--- + +## 🔧 Phase 1: 레이아웃 변환 (13개) ✅ 완료 + +> **작업 유형**: `layouts.presentation` → `layouts.app` 변환 +> **완료일**: 2025-12-16 +> **우선순위**: 🔴 높음 (기존 컨텐츠 있어 빠른 적용 가능) + +### Strategy 메뉴 (12개) + +| # | 파일명 | 메뉴명 | 상태 | 작업일 | 비고 | +|---|--------|--------|:----:|--------|------| +| 1 | `tax.blade.php` | 세무 전략 | ✅ | 2025-12-16 | 높이/슬라이드번호 조정 | +| 2 | `labor.blade.php` | 노무 전략 | ✅ | 2025-12-16 | 높이/슬라이드번호 조정 | +| 3 | `debt.blade.php` | 채권추심 전략 | ✅ | 2025-12-16 | 높이/슬라이드번호 조정 | +| 4 | `chatbot.blade.php` | 상담용 챗봇 전략 | ✅ | 2025-12-16 | 높이/슬라이드번호 조정 | +| 5 | `kodata-vs-nice.blade.php` | KoDATA vs NICE API | ✅ | 2025-12-16 | | +| 6 | `barobill-vs-popbill.blade.php` | 바로빌 vs 팝빌 API | ✅ | 2025-12-16 | | +| 7 | `knowledge-search.blade.php` | 사내 지식 검색 시스템 | ✅ | 2025-12-16 | | +| 8 | `chatbot-compare.blade.php` | 챗봇 솔루션 비교 분석 | ✅ | 2025-12-16 | | +| 9 | `rag-startups.blade.php` | RAG 스타트업 현황 | ✅ | 2025-12-16 | | +| 10 | `douzone.blade.php` | 더존비즈온 분석 | ✅ | 2025-12-16 | | +| 11 | `confluence-vs-notion.blade.php` | Confluence vs Notion | ✅ | 2025-12-16 | | +| 12 | `sales-strategy.blade.php` | SAM 영업전략 | ✅ | 2025-12-16 | | + +### AI 메뉴 (1개) + +| # | 파일명 | 메뉴명 | 상태 | 작업일 | 비고 | +|---|--------|--------|:----:|--------|------| +| 13 | `sam-ai-menu.blade.php` | SAM AI 메뉴 이동 | ✅ | 2025-12-16 | 높이 조정 | + +### 상태 범례 +- ⬜ 대기 +- 🔄 진행중 +- ✅ 완료 +- ⚠️ 이슈 발생 + +--- + +## 📋 Phase 2: AI 기능 구현 (10개) + +> **작업 유형**: placeholder → 전체 구현 +> **예상 시간**: 각 2~8시간 +> **우선순위**: 🟡 중간 + +| # | 파일명 | 메뉴명 | 상태 | 작업일 | 비고 | +|---|--------|--------|:----:|--------|------| +| 1 | `web-recording.blade.php` | 웹 녹음 AI 요약 | ⬜ | - | | +| 2 | `meeting-summary.blade.php` | 회의록 AI 요약 | ⬜ | - | | +| 3 | `work-memo-summary.blade.php` | 업무협의록 AI 요약 | ⬜ | - | | +| 4 | `operator-chatbot.blade.php` | 운영자용 챗봇 | ⬜ | - | | +| 5 | `vertex-rag.blade.php` | Vertex RAG 챗봇 | ⬜ | - | | +| 6 | `tenant-knowledge.blade.php` | 테넌트 지식 업로드 | ⬜ | - | | +| 7 | `tenant-chatbot.blade.php` | 테넌트 챗봇 | ⬜ | - | | +| 8 | `sam-ai-alarm.blade.php` | SAM AI 알람음 제작 | ⬜ | - | | +| 9 | `gps-attendance.blade.php` | GPS 출퇴근 관리 | ⬜ | - | | +| 10 | `company-overview.blade.php` | 기업개황 조회 | ⬜ | - | | + +--- + +## 📋 Phase 3: Management 구현 (11개) + +> **작업 유형**: placeholder → 전체 구현 +> **예상 시간**: 각 2~8시간 +> **우선순위**: 🟢 낮음 (외부 서비스 연동 필요) + +| # | 파일명 | 메뉴명 | 상태 | 작업일 | 비고 | +|---|--------|--------|:----:|--------|------| +| 1 | `barobill-tenant.blade.php` | 바로빌 테넌트 관리 | ⬜ | - | | +| 2 | `tax-invoice-strategy.blade.php` | 전자세금계산서 전략 | ⬜ | - | | +| 3 | `tax-invoice.blade.php` | 전자세금계산서 | ⬜ | - | | +| 4 | `business-verify.blade.php` | 사업자등록번호 진위 확인 | ⬜ | - | | +| 5 | `sales-meeting.blade.php` | 영업관리 & 매니저 미팅관리 | ⬜ | - | | +| 6 | `card-tax-matching.blade.php` | 카드 세무항목 매칭 전략 | ⬜ | - | | +| 7 | `card-api-report.blade.php` | 한국 카드사 API 보고서 | ⬜ | - | | +| 8 | `card-usage-matching.blade.php` | 카드 사용내역 수집 후 매칭 | ⬜ | - | | +| 9 | `account-api.blade.php` | 계좌입출금 내역 조회 API | ⬜ | - | | +| 10 | `sales-scenario.blade.php` | 영업관리 시나리오 | ⬜ | - | | +| 11 | `manager-scenario.blade.php` | 매니저 시나리오 | ⬜ | - | | + +--- + +## 📋 Phase 4: Strategy placeholder (3개) + +> **작업 유형**: placeholder → 전체 구현 +> **예상 시간**: 각 2~8시간 +> **우선순위**: 🟢 낮음 + +| # | 파일명 | 메뉴명 | 상태 | 작업일 | 비고 | +|---|--------|--------|:----:|--------|------| +| 1 | `stablecoin.blade.php` | 스테이블코인 보고서 | ⬜ | - | | +| 2 | `mrp-overseas.blade.php` | MRP 해외사례 | ⬜ | - | | +| 3 | `qa-solution.blade.php` | 차세대 QA 솔루션 | ⬜ | - | | + +--- + +## ✅ 완료된 항목 + +| # | 파일명 | 메뉴명 | 완료일 | 비고 | +|---|--------|--------|--------|------| +| 1 | `business-ocr.blade.php` | 사업자등록증 OCR | 2025-12-XX | 이미 완료 | + +--- + +## 📝 작업 체크리스트 + +### 레이아웃 변환 (🔧) 체크리스트 + +``` +□ 1. @extends('layouts.presentation') → @extends('layouts.app') 변경 +□ 2. 기존 presentation 스타일 제거/조정 +□ 3. 페이지 헤더 컴포넌트 추가 (필요시) +□ 4. 반응형 스타일 조정 +□ 5. 테스트 및 검증 +``` + +### 전체 구현 (📋) 체크리스트 + +``` +□ 1. 5130 소스 분석 +□ 2. Service 클래스 설계/생성 +□ 3. API 컨트롤러 생성 (필요시) +□ 4. Blade 뷰 구현 +□ 5. HTMX 연동 +□ 6. 테스트 및 검증 +``` + +--- + +## 📚 참고 문서 + +- **마이그레이션 계획**: `docs/plans/5130-to-mng-migration-plan.md` +- **MNG 기술 표준**: `mng/docs/99_TECHNICAL_STANDARDS.md` +- **MNG 레이아웃 패턴**: `mng/docs/LAYOUT_PATTERN.md` +- **MNG Critical Rules**: `mng/docs/MNG_CRITICAL_RULES.md` +- **5130 레거시 개요**: `docs/projects/legacy-5130/00_OVERVIEW.md` + +--- + +## 변경 이력 + +| 날짜 | 내용 | 작업자 | +|------|------|--------| +| 2025-12-16 | Phase 1 완료 - 13개 파일 레이아웃 변환 | Claude | +| 2025-12-16 | 작업 추적 문서 생성 | Claude | + +--- + +*최종 수정: 2025-12-16*