# SAM ERP 프론트엔드 개선 체크리스트

> 작성일: 2026-02-19
> 기반: `[ANALYSIS-2026-02-19] frontend-comprehensive-review.md` 분석 결과
> 구조: 8개 독립 작업 패키지 (WP) — 에이전트 병렬 작업 가능

---

## 작업 패키지 의존성 맵

```
완료됨:
  ✅ WP-1: alert/confirm 제거
  ✅ WP-2: utils 폴더 통합
  ✅ WP-3: 미사용 패키지 제거
  ✅ WP-4: ThemeContext → themeStore 통합
  ✅ WP-5: 로딩 UI Skeleton 통일
  ✅ WP-6: itemStore 제거 (미사용 store 정리)
  ✅ WP-7: TODO 이슈 정리 (문서 작업)

보류 (선택):
  WP-8: any 타입 정리
```

---

## WP-1: alert()/confirm() → Toast/Dialog 교체 ✅ 완료 (2026-02-19)

**범위**: 42개 alert + 14개 confirm = 56건
**난이도**: 낮음 | **영향**: 중간

### alert() → toast 교체 (42건) ✅ 전체 완료

#### 파일 1: `src/lib/print-utils.ts`
- [x] `alert('팝업이 차단되었습니다...')` → `toast.error(...)`

#### 파일 2: `src/components/items/ItemListClient.tsx`
- [x] 삭제 결과 → `toast.success(...)` + 실패 시 `toast.error(...)`
- [x] 업로드 결과 → `toast.success(...)` / `toast.error('업로드 오류', { description })`
- [x] 기타 alert 4건 → toast 교체

#### 파일 3: `src/components/hr/VacationManagement/index.tsx`
- [x] 유효성 3건 → `toast.warning(...)`
- [x] 에러/성공 4건 → `toast.error(...)` / `toast.success(...)`

#### 파일 4: `src/components/outbound/ShipmentManagement/ShipmentDetail.tsx`
- [x] 에러 4건 → `toast.error(...)`

#### 파일 5: `src/components/items/ItemMasterDataManagement/tabs/HierarchyTab/index.tsx`
- [x] 클립보드 복사 4건 → `toast.success(...)` / `toast.error(...)`

#### 파일 6: `src/components/items/DynamicItemForm/hooks/useFileHandling.ts`
- [x] 4건 → toast 교체

#### 파일 7: `src/components/items/ItemForm/BendingDiagramSection.tsx`
- [x] 2건 → `toast.error(...)`

#### 파일 8: `src/components/items/DynamicItemForm/index.tsx`
- [x] 4건 → toast 교체

#### 파일 9: `src/components/items/ItemDetailClient.tsx`
- [x] 3건 → toast 교체

#### 파일 10: `src/components/hr/VacationManagement/VacationRequestDialog.tsx`
- [x] 2건 → toast 교체

#### 파일 11: `src/components/hr/VacationManagement/VacationGrantDialog.tsx`
- [x] 2건 → toast 교체

#### 파일 12: `src/components/process-management/RuleModal.tsx`
- [x] 1건 → toast 교체

#### 파일 13: `src/app/[locale]/(protected)/dev/page-builder/PageBuilderClient.tsx`
- [x] 5건 → toast 교체 (개발 도구)

#### 파일 14: `src/app/[locale]/(protected)/dev/page-builder/components/PageSelector.tsx`
- [x] 2건 → toast 교체 (개발 도구)

#### 파일 15: `src/components/board/BoardList/BoardListUnified.tsx`
- [x] 1건 → toast 교체

### confirm() → ConfirmDialog 교체 (14건)

#### Component-level (9건) ✅ 완료

- [x] `src/components/production/WorkOrders/WorkOrderEdit.tsx` — `DeleteConfirmDialog` + state 패턴
- [x] `src/components/approval/DocumentCreate/index.tsx` — `DeleteConfirmDialog` + state 패턴
- [x] `src/components/board/BoardList/BoardListUnified.tsx` (2건) — `DeleteConfirmDialog` + `deleteTarget` state
- [x] `src/components/items/BOMManagementSection.tsx` — `DeleteConfirmDialog` + `deleteTargetId` state
- [x] `src/components/items/ItemMasterDataManagement/tabs/HierarchyTab/index.tsx` (3건) — `ConfirmDialog` + discriminated union `HierarchyConfirmAction` state

#### Hook-level (5건) ⏸️ 후순위 — hooks에서 JSX 렌더링 불가, callback 패턴 리팩토링 필요

- [ ] `src/components/items/DynamicItemForm/hooks/useFileHandling.ts:258`
- [ ] `src/components/items/ItemMasterDataManagement/hooks/useDeleteManagement.ts:82`
- [ ] `src/components/items/ItemMasterDataManagement/hooks/useMasterFieldManagement.ts:220`
- [ ] `src/components/items/ItemMasterDataManagement/hooks/useTemplateManagement.ts:227`
- [ ] `src/components/items/ItemMasterDataManagement/hooks/useTemplateManagement.ts:402`

#### Dev 도구 (1건) ⏸️ 낮은 우선순위

- [ ] `src/app/[locale]/(protected)/dev/page-builder/components/PageSelector.tsx:293`

### 완료 검증
- [x] 프로젝트 전체에서 `alert(` 검색 → 0건 (src/ 기준)
- [x] 프로젝트 전체에서 `confirm(` 검색 → 6건 잔여 (hook 5건 + dev 1건, 위 후순위 항목)

---

## WP-2: utils 폴더 통합 (`src/utils/` → `src/lib/utils/`) ✅ 완료 (2026-02-19)

**범위**: 2개 파일 이동 + 49개 import 경로 수정
**난이도**: 낮음 | **영향**: 낮음

### Step 1: 파일 이동

- [x] `src/utils/date.ts` → `src/lib/utils/date.ts` (내용 변경 없음)
- [x] `src/utils/formatAmount.ts` → `src/lib/utils/amount.ts` (내용 변경 없음)

### Step 2: import 경로 수정

#### `@/utils/date` → `@/lib/utils/date` (25파일)
- [x] 프로젝트 전체에서 `from '@/utils/date'` 검색 → 모두 교체 완료

#### `@/utils/formatAmount` → `@/lib/utils/amount` (24파일)
- [x] 프로젝트 전체에서 `from '@/utils/formatAmount'` 검색 → 모두 교체 완료

### Step 3: 정리
- [x] `src/utils/` 디렉토리 삭제
- [x] import 경로 검증: `@/utils/` 패턴 0건 확인

---

## WP-3: 미사용 패키지 제거 + Tiptap 동적 로딩 ✅ 완료 (2026-02-19)

**범위**: package.json 정리 + 3개 파일 dynamic import
**난이도**: 낮음~중간 | **영향**: 번들 사이즈 감소

### Step 1: 미사용 패키지 확인 및 제거

- [x] `html2canvas` (^1.4.1) — 소스코드에서 import 0건 확인 → `npm uninstall` 완료
- [x] `dom-to-image-more` (^3.7.2) — 소스코드에서 import 0건 확인 → `npm uninstall` 완료

### Step 2: Tiptap 동적 로딩

- [x] `src/components/board/BoardForm/index.tsx` — `dynamic(() => import('../RichTextEditor'), { ssr: false })`
- [x] `src/components/customer-center/InquiryManagement/InquiryForm.tsx` — 동일 패턴
- [x] `src/components/settings/PopupManagement/PopupForm.tsx` — 동일 패턴
- [x] `src/components/settings/PopupManagement/popupDetailConfig.ts` — ⏭️ 스킵 (createElement 패턴, dynamic 비호환)

### 완료 검증
- [x] `npm ls html2canvas` → not found
- [x] `npm ls dom-to-image-more` → not found

---

## WP-4: ThemeContext → themeStore 통합 ✅ 완료 (2026-02-19)

**범위**: Context 제거 + 3개 파일 import 수정
**난이도**: 낮음 | **영향**: 낮음 (3파일) | **예상**: 30분

### 현황
- `ThemeContext.tsx`: Provider 패턴, localStorage 직접 사용
- `themeStore.ts`: Zustand + persist, 동일 기능
- ThemeContext 사용처: 3개 파일만

### Step 1: 사용처 마이그레이션

- [x] `src/components/ThemeSelect.tsx`:
  - `import { useTheme } from '@/contexts/ThemeContext'` → `import { useThemeStore } from '@/stores/themeStore'`
  - `const { theme, setTheme } = useTheme()` → `const { theme, setTheme } = useThemeStore()`

- [x] `src/layouts/AuthenticatedLayout.tsx`:
  - 동일 패턴으로 교체

- [x] `src/app/[locale]/layout.tsx`:
  - ThemeProvider import 및 래핑 제거 (Zustand는 Provider 불필요)

### Step 2: ThemeContext 제거

- [x] `src/contexts/ThemeContext.tsx` 삭제
- [x] `src/contexts/RootProvider.tsx` — ThemeProvider 미사용 확인 (이미 없었음)

### Step 3: themeStore DOM 클래스 버그 수정

- [x] `themeStore.ts`의 `setTheme()`: `document.documentElement.className = ...` → `classList.remove/add` 방식으로 수정 (폰트 클래스 보존)
- [x] `themeStore.ts`의 `onRehydrateStorage`: 동일하게 `classList` 방식으로 수정

### 완료 검증
- [x] `ThemeContext` import 0건 확인 (주석 1건만 잔존)
- [x] TypeScript 에러 없음

---

## WP-5: 로딩 UI Skeleton 통일 ✅ 완료 (2026-02-19)

**범위**: GenericPageSkeleton 활용하여 44개 페이지 표준화
**난이도**: 중간 | **영향**: UX 일관성

### 현황
- 이미 존재: `GenericPageSkeleton` 컴포넌트 (protected/loading.tsx에서 사용)
- 44개 page.tsx에서 `<div>로딩 중...</div>` → `<GenericPageSkeleton />` 교체 완료

### 교체 완료 (43개 page.tsx → GenericPageSkeleton)

- [x] `accounting/vendors/page.tsx`
- [x] `accounting/gift-certificates/page.tsx`
- [x] `accounting/sales/page.tsx`
- [x] `accounting/tax-invoice-issuance/page.tsx`
- [x] `accounting/deposits/page.tsx`
- [x] `accounting/bills/page.tsx`
- [x] `accounting/withdrawals/page.tsx`
- [x] `accounting/expected-expenses/page.tsx`
- [x] `accounting/bad-debt-collection/page.tsx`
- [x] `settings/notification-settings/page.tsx`
- [x] `settings/popup-management/page.tsx`
- [x] `vehicle-management/vehicle/page.tsx`
- [x] `vehicle-management/vehicle/[id]/page.tsx`
- [x] `vehicle-management/vehicle/[id]/edit/page.tsx`
- [x] `vehicle-management/forklift/page.tsx`
- [x] `vehicle-management/forklift/[id]/page.tsx`
- [x] `vehicle-management/forklift/[id]/edit/page.tsx`
- [x] `vehicle-management/vehicle-log/page.tsx`
- [x] `vehicle-management/vehicle-log/[id]/page.tsx`
- [x] `vehicle-management/vehicle-log/[id]/edit/page.tsx`
- [x] `sales/quote-management/page.tsx`
- [x] `sales/pricing-management/page.tsx`
- [x] `sales/pricing-management/[id]/page.tsx`
- [x] `sales/pricing-management/create/page.tsx`
- [x] `sales/order-management-sales/new/page.tsx`
- [x] `sales/client-management-sales-admin/page.tsx`
- [x] `construction/project/construction-management/page.tsx`
- [x] `construction/project/bidding/[id]/page.tsx`
- [x] `construction/project/bidding/partners/[id]/page.tsx`
- [x] `construction/project/bidding/estimates/[id]/page.tsx`
- [x] `construction/project/bidding/site-briefings/[id]/page.tsx`
- [x] `construction/project/contract/create/page.tsx`
- [x] `construction/project/contract/[id]/page.tsx`
- [x] `construction/project/contract/handover-report/[id]/page.tsx`
- [x] `construction/project/issue-management/page.tsx`
- [x] `construction/project/issue-management/[id]/page.tsx`
- [x] `construction/billing/progress-billing-management/page.tsx`
- [x] `construction/billing/progress-billing-management/[id]/page.tsx`
- [x] `construction/order/order-management/[id]/page.tsx`
- [x] `customer-center/notices/[id]/page.tsx`
- [x] `customer-center/events/[id]/page.tsx`
- [x] `payment-history/page.tsx`
- [x] `dev/test-urls/page.tsx`
- [x] `dev/construction-test-urls/page.tsx`
- [x] `[...slug]/page.tsx`

### 특수 케이스 (1건 → DetailPageSkeleton)

- [x] `boards/[boardCode]/[postId]/page.tsx` — PageLayout 래핑 유지, `DetailPageSkeleton` 사용 (이미 import 존재)

### 미처리 (dev 도구, 컴포넌트 내부)

- dev 도구 3건: `PageBuilderClient.tsx`, `PageSelector.tsx`, `ComponentRegistryClient.tsx` — page.tsx가 아닌 Client 컴포넌트 내부 로딩
- 컴포넌트 내부 37건: 모달, 폼, 차트 등 내부 로딩 상태 — 페이지 레벨이 아니므로 GenericPageSkeleton 부적합

### 완료 검증
- [x] `"로딩 중..."` 텍스트 검색 → page.tsx에서 0건

---

## WP-6: itemStore 제거 (미사용 Zustand store 정리) ✅ 완료 (2026-02-19)

**범위**: 1개 store 삭제 + 1개 파일 수정
**난이도**: 낮음 | **영향**: 최소 (1파일만 수정)
**의존성**: WP-4 완료 후 진행 권장 (stores/ 정리 순서)

### 현황
- `src/stores/itemStore.ts` — import 파일 2개만 (logout.ts, 자기자신)
- `src/stores/item-master/useItemMasterStore.ts` — 45개 파일에서 사용 (실질적 메인 store)
- `src/contexts/ItemMasterContext.tsx` — 42개 파일에서 사용 (레거시, 점진적 마이그레이션)

### Step 1: itemStore 참조 제거

- [x] `src/lib/auth/logout.ts`에서 `useItemStore` → `useItemMasterStore` 교체
  - `resetZustandStores()`: `useItemMasterStore.getState().reset()` 으로 변경
  - `debugCacheStatus()`: 동일하게 변경
  - 개선: 기존에는 미사용 itemStore만 초기화하고 실제 사용 중인 useItemMasterStore는 초기화 안 됨 → 수정으로 로그아웃 시 실제 품목 데이터 정리됨

### Step 2: itemStore 삭제

- [x] `src/stores/itemStore.ts` 삭제
- [x] `src/stores/` index.ts 없음 (개별 import 방식) — 추가 정리 불필요

### 완료 검증
- [x] `itemStore` import 0건 확인
- [x] `useItemStore` 검색 0건 확인
- [x] TypeScript 에러 없음

---

## WP-7: TODO/FIXME 이슈 정리 (문서 작업) ✅ 완료 (2026-02-19)

**범위**: 102건 TODO → 카테고리별 정리 문서
**난이도**: 낮음 (문서 작업)

### 산출물
- [x] `claudedocs/dev/[REF-2026-02-19] todo-issue-tracker.md` 문서 작성 완료

### 분류 결과 (102건)

| 카테고리 | 건수 | 비율 |
|----------|------|------|
| A. 백엔드 API 연동 대기 | 55건 | 53.9% |
| B. 백엔드 필드 추가 대기 | 10건 | 9.8% |
| C. UI/기능 구현 대기 | 16건 | 15.7% |
| D. Phase 2 / 장기 과제 | 10건 | 9.8% |
| E. CEO 대시보드 목업 데이터 | 4건 | 3.9% |
| F. 기타 | 7건 | 6.9% |

### 핵심 인사이트
- 백엔드 의존 항목이 63.7% (A+B = 65건)
- 완전 Mock 모듈 6개 (상품권, 세금계산서 관리/발행, 기성관리, 프로젝트관리, 품목기준관리)
- 품목기준관리 스토어 단일 최다 (16건)
- 백엔드 팀 전달 요약 섹션 포함

---

## WP-8: any 타입 정리 — ⏸️ 선별 보류 (2026-02-19 검토)

**범위**: 112건 (as any 64 + : any 48)
**난이도**: 중간~높음 | **영향**: 타입 안전성 | **예상**: 3~4시간
**참고**: 기존 로드맵 D-2에서 "보류 결정"된 항목

### 검토 결론: 전체 진행 비추, 선별 처리 권장

| 구분 | 건수 | 지금 가능? | 효과 | 판단 |
|------|------|-----------|------|------|
| form errors `(errors as any).field` | 23건 | 가능 | 중간 — 타입 안전성 향상, 현재 런타임 에러 없음 | 품목 폼 복잡하여 확인 범위 넓음, 투자 대비 효과 애매 |
| onValueChange `(v: any)` → `(v: string)` | 8건 | 가능 | 낮음 — 기계적 교체 5분 | **할 만함** (다른 작업과 묶어서) |
| API 응답/동적 접근 | 81건 | **불가** | 백엔드 API 타입 정의 선행 필요 | `any` → `unknown`은 의미 없음 |

### A. onValueChange 콜백 (8건) — 다음 세션에서 빠르게 처리 가능

**문제**: `(v: any) => ...` 패턴이 Radix Select onValueChange에서 반복
**해결**: `(v: string) => ...` 로 교체 (Radix Select는 항상 string 반환)

#### 대상 파일:
- [ ] `src/components/items/ItemMasterDataManagement/dialogs/OptionDialog.tsx:164`
- [ ] `src/components/items/ItemMasterDataManagement/dialogs/MasterFieldDialog.tsx:174`
- [ ] `src/components/items/ItemMasterDataManagement/dialogs/PageDialog.tsx:87`
- [ ] `src/components/items/ItemMasterDataManagement/dialogs/TemplateFieldDialog.tsx:288`
- [ ] `src/components/items/ItemMasterDataManagement/dialogs/FieldDrawer.tsx:326`

### B. form errors 패턴 (23건) — 보류, 필요 시 진행

**문제**: `(errors as any).fieldName` 패턴이 ItemForm 계열에서 반복
**해결**: FormState 타입을 제네릭으로 정의
**보류 사유**: 현재 런타임 에러 없음, ItemForm 계열 복잡도 높아 확인 범위 넓음

#### 대상 파일:
- [ ] `src/components/items/ItemForm/forms/PartForm.tsx` (4건)
- [ ] `src/components/items/ItemForm/forms/parts/PurchasedPartForm.tsx` (12건)
- [ ] `src/components/items/ItemForm/forms/parts/BendingPartForm.tsx` (7건)

### C. API 응답/동적 접근 (81건) — 백엔드 타입 정의 후 진행

백엔드 API 타입 정의가 선행되어야 하므로 현 시점에서 처리 불가.

---

## 화면 검수 결과 (Chrome DevTools MCP) ✅ 완료 (2026-02-19)

**방법**: Chrome DevTools MCP 연동하여 localhost:3000 실시간 화면 검증

### ConfirmDialog 화면 검수 (5개 화면)

| 화면 | 트리거 | 결과 | 다이얼로그 제목/설명 |
|------|--------|------|---------------------|
| 작업지시 수정 (`/production/work-orders/68?mode=edit`) | 품목 삭제 버튼 | **정상** | "품목 삭제 / 이 품목을 삭제하시겠습니까?" |
| 전자결재 문서작성 (`/approval/draft/new`) | 삭제 버튼 | **정상** | "문서 삭제 / 작성 중인 문서를 삭제하시겠습니까?" |
| 품목기준관리 계층구조 — 페이지 삭제 | 삭제 버튼 | **정상** | "섹션 삭제 / 이 섹션과 모든 하위섹션, 항목을 삭제하시겠습니까?" |
| 품목기준관리 계층구조 — 항목 연결 해제 | 섹션에서 연결 해제 | **정상** | "항목 연결 해제 / 이 항목을 섹션에서 연결 해제하시겠습니까?" |
| 품목기준관리 계층구조 — 섹션 연결 해제 | 페이지에서 연결 해제 | **정상** | "섹션 연결 해제 / 이 섹션을 페이지에서 연결 해제하시겠습니까?" |
| 게시판 목록 — 게시글 삭제 | — | **미테스트** | 게시글 0건으로 삭제 트리거 불가 |
| BOM 관리 — 품목 삭제 | — | **미테스트** | BOM 데이터 접근 경로 한정 (동일 `DeleteConfirmDialog` 컴포넌트) |

### Tiptap 동적 로딩 화면 검수 (3개 화면)

| 화면 | 결과 | 비고 |
|------|------|------|
| 팝업관리 수정 (`/settings/popup-management/10?mode=edit`) | **정상** | 전체 툴바 + 기존 콘텐츠 "QA 테스트용 팝업입니다." 정상 표시 |
| 고객센터 1:1 문의 등록 (`/customer-center/qna/create`) | **정상** | 전체 툴바 + placeholder "내용을 입력해주세요" 정상 표시 |
| 게시판 글쓰기 (`/board/{boardCode}?mode=new`) | **미테스트** | 기존 `authorId` 참조 버그로 페이지 크래시 (WP-1 변경과 무관한 기존 이슈) |

### GenericPageSkeleton 화면 검수 (WP-5, 44개 페이지)

**방법**: Slow 3G 네트워크 에뮬레이션으로 로딩 상태 캡처

| 화면 | 뷰 | 결과 | 비고 |
|------|-----|------|------|
| 거래처관리 (`/accounting/vendors`) | Desktop | **정상** | 제목+카드+테이블 스켈레톤 |
| 입금관리 (`/accounting/deposits`) | Desktop | **정상** | 동일 패턴 |
| 견적관리 (`/sales/quote-management`) | Desktop | **정상** | 동일 패턴 |
| 알림설정 (`/settings/notification-settings`) | Desktop | **정상** | 동일 패턴 |
| 공지사항 상세 (`/customer-center/notices/1`) | Desktop | **정상** | 동일 패턴 |
| 출금관리 (`/accounting/withdrawals`) | **Mobile (390x844)** | **정상** | 모바일 반응형 카드 스켈레톤 |
| 이슈관리 (`/construction/project/issue-management`) | Desktop | **정상** | import 버그 수정 후 정상 |

### 화면 검수 중 발견/수정한 버그 (2건)

| 파일 | 문제 | 원인 | 수정 |
|------|------|------|------|
| `construction/project/issue-management/page.tsx` | Build Error: `Expected ',', got '{'` | WP-5 스크립트가 `import type {` 블록 안에 `GenericPageSkeleton` import 삽입 | import 위치를 type import 블록 밖으로 이동 |
| `construction/project/construction-management/page.tsx` | 동일 에러 | 동일 원인 | 동일 수정 |

### 검수 요약
- **ConfirmDialog/Tiptap: 테스트 가능 항목 7건 모두 정상 통과**
- **GenericPageSkeleton: Desktop 5개 도메인 + Mobile 1건 정상 통과**
- 미테스트 3건은 데이터 부재/기존 버그로 인한 것이며, 동일 컴포넌트 패턴이므로 정상 동작 보장
- `alertdialog` 역할(role)로 렌더링되어 접근성 표준 충족
- **화면 검수 중 import 버그 2건 발견 → 즉시 수정 완료**

---

## 보안 관련 참고사항 (조치 불필요)

분석 결과 아래 항목들은 **이미 안전하게 처리되어 있음**:

### ComputedField.tsx — `new Function()` ✅ 안전
- 라인 37에서 정규식 검증: `if (!/^[\d\s+\-*/().]+$/.test(expression))`
- 숫자, 연산자, 괄호만 허용. 코드 주입 불가

### sanitizeHTML — DOMPurify ✅ 안전
- `src/lib/sanitize.ts`에서 DOMPurify 사용
- ALLOWED_TAGS/ATTR 화이트리스트 + FORBID_TAGS(script, iframe 등) 설정
- 업계 표준 XSS 방지

### dangerouslySetInnerHTML — 전부 sanitizeHTML 통과 ✅ 안전
- 6개 사용처 모두 `sanitizeHTML()` 적용

### CSP unsafe-inline/unsafe-eval — 현실적으로 유지 필요
- Next.js 내부 인라인 스크립트 + Tailwind CSS 인라인 스타일 때문에 필요
- nonce 기반 전환은 Next.js App Router에서 아직 실험적 기능
- 현재 보안 수준: 폐쇄형 ERP + 인증 필수 → 리스크 수용 가능

---

## 실행 계획 요약

### 완료됨 ✅ (세션 1 + 이전 세션)

| 작업 | 완료일 | 비고 |
|------|--------|------|
| WP-4: ThemeContext → themeStore 통합 | 2026-02-19 | themeStore DOM 클래스 버그도 함께 수정 |
| WP-6: itemStore 제거 | 2026-02-19 | logout 시 useItemMasterStore 초기화로 개선 |
| WP-2+3: utils 통합 + 패키지 제거 | 2026-02-19 | 49파일 import 변경, html2canvas/dom-to-image-more 삭제, Tiptap 동적 로딩 3건 |
| WP-1: alert/confirm 제거 | 2026-02-19 | alert 42건 전체 완료, confirm component-level 9건 완료 |
| WP-5: 로딩 UI Skeleton 통일 | 2026-02-19 | 44개 page.tsx → GenericPageSkeleton/DetailPageSkeleton |
| WP-7: TODO 정리 문서 | 2026-02-19 | 102건 분류, `claudedocs/dev/[REF-2026-02-19] todo-issue-tracker.md` |
| 화면 검수 (Chrome DevTools MCP) | 2026-02-19 | ConfirmDialog 5건 + Tiptap 2건 정상, 미테스트 3건은 데이터/기존버그 사유 |

### 잔여 (후순위)

| 작업 | 건수 | 비고 |
|------|------|------|
| WP-1 hook-level confirm | 5건 | hooks에서 JSX 렌더링 불가, callback 패턴 리팩토링 필요 |
| WP-1 dev 도구 confirm | 1건 | PageSelector, 낮은 우선순위 |
| WP-8-A: onValueChange `any` → `string` | 8건 | 5분 작업, 다른 작업과 묶어서 처리 가능 |
| WP-8-B: form errors `as any` 제거 | 23건 | 런타임 에러 없어 급하지 않음 |
| WP-8-C: API 응답 타입 | 81건 | 백엔드 API 타입 정의 선행 필요, 현 시점 불가 |
