- claudedocs 폴더 구조 재정리: archive/sessions, guides/migration·mobile·universal-list, refactoring 분류 - 오래된 세션 컨텍스트/체크리스트 문서 정리 (아카이브 이동 또는 삭제) - AuthContext → authStore(Zustand) 전환 시작, RootProvider 간소화 - GenericCRUDDialog 공통 다이얼로그 컴포넌트 추가 - PermissionDialog 삭제 → GenericCRUDDialog로 대체 - RankDialog/TitleDialog GenericCRUDDialog 기반으로 리팩토링 - toast-utils.ts 삭제 (미사용) - fileDownload.ts 개선, excel-download.ts 정리 - menuStore/themeStore Zustand 셀렉터 최적화 - useColumnSettings/useTableColumnStore 기능 보강 - 세금계산서/견적/작업자화면/결재 등 소규모 개선 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
481 lines
25 KiB
Markdown
481 lines
25 KiB
Markdown
# 코드 중복 제거 및 공통화 체크리스트
|
||
|
||
> 작성일: 2026-02-19
|
||
> 기반: 4개 에이전트 병렬 분석 결과 (회계 page.tsx / 회계 컴포넌트 / 유틸 중복 / 비회계 페이지)
|
||
> 구조: 6개 작업 패키지 (WP) — 의존성 기반 병렬화 설계
|
||
|
||
---
|
||
|
||
## 작업 패키지 의존성 맵
|
||
|
||
```
|
||
Phase 1 (독립 — 전부 병렬 가능):
|
||
[x] WP-1: 날짜 하드코딩 긴급 수정 (10파일) ✅
|
||
[x] WP-2: formatAmount/formatDate import 통일 (35+파일) ✅
|
||
[x] WP-3: 차량관리 edit 페이지 리다이렉트 전환 (6파일) ✅
|
||
|
||
Phase 2 (Phase 1 완료 후 — 서로 간 병렬 가능):
|
||
[x] WP-4: 공통 훅 추출 (useDateRange, useAccountingListPage 등) ✅
|
||
[x] WP-5: 회계 컴포넌트 공통 패턴 추출 (팩토리 함수, 공통 컴포넌트) ✅
|
||
|
||
Phase 3 (Phase 2 완료 후):
|
||
[x] WP-6: .toISOString().split('T')[0] → getTodayString() 전환 (15파일 26건) ✅
|
||
```
|
||
|
||
### 병렬 실행 판단 기준
|
||
|
||
| 판단 | 조건 |
|
||
|------|------|
|
||
| **병렬 가능** | 수정 파일이 겹치지 않고, 새 유틸/훅에 의존하지 않음 |
|
||
| **순차 필요** | 새로 만드는 훅/유틸을 다른 WP에서 import해야 하는 경우 |
|
||
|
||
---
|
||
|
||
## WP-1: 날짜 필터 하드코딩 긴급 수정 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🔴 CRITICAL (데이터 누락 버그)
|
||
**난이도**: 낮음 | **파일 수**: 10 | **예상 변경량**: 각 2줄
|
||
**병렬**: Phase 1 — 독립 실행 가능
|
||
|
||
### 현황
|
||
매출관리와 동일한 버그. `2025-xx-xx` 하드코딩으로 잘못된 기간 데이터 표시.
|
||
|
||
### 수정 완료
|
||
|
||
**WP-4에서 useDateRange('currentYear') 적용으로 이미 수정된 파일:**
|
||
- [x] `accounting/DepositManagement/index.tsx`
|
||
- [x] `accounting/WithdrawalManagement/index.tsx`
|
||
- [x] `accounting/BillManagement/index.tsx`
|
||
|
||
**이번 세션에서 추가 발견 및 수정한 파일 (동일 버그):**
|
||
- [x] `accounting/BillManagement/BillManagementClient.tsx` — 실제 page에서 사용되는 컴포넌트 (`'2025-09-01'`~`'2025-09-03'` → `useDateRange('currentYear')`)
|
||
- [x] `accounting/PurchaseManagement/index.tsx` — (`'2025-01-01'`~`'2025-12-31'` → `useDateRange('currentYear')`)
|
||
- [x] `approval/ApprovalBox/index.tsx` — (`'2025-09-01'`~`'2025-09-03'` → `useDateRange('currentYear')`)
|
||
- [x] `approval/ReferenceBox/index.tsx` — (`'2025-09-01'`~`'2025-09-03'` → `useDateRange('currentYear')`)
|
||
- [x] `approval/DraftBox/index.tsx` — (`'2025-01-01'`~`'2025-12-31'` → `useDateRange('currentYear')`)
|
||
- [x] `process-management/ProcessListClient.tsx` — (`'2025-01-01'`~`'2025-12-31'` → `useDateRange('currentYear')`)
|
||
- [x] `hr/VacationManagement/index.tsx` — (`'2025-12-01'`~`'2025-12-31'` → `useDateRange('currentMonth')`)
|
||
- [x] `hr/SalaryManagement/index.tsx` — (`'2025-12-01'`~`'2025-12-31'` → `useDateRange('currentMonth')`)
|
||
- [x] `pricing-table-management/PricingTableListClient.tsx` — (`'2025-01-01'`~`'2025-12-31'` → `useDateRange('currentYear')`)
|
||
- [x] `checklist-management/ChecklistListClient.tsx` — (`'2025-01-01'`~`'2025-12-31'` → `useDateRange('currentYear')`)
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과
|
||
- [x] `useState('2025` 잔존 0건 확인
|
||
|
||
---
|
||
|
||
## WP-2: formatAmount / formatDate import 통일 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🟡 HIGH (코드 품질)
|
||
**난이도**: 낮음 | **파일 수**: 24파일 수정 / 10파일 스킵 | **예상 변경량**: 각 파일 2-5줄 (로컬 함수 삭제 + import 추가)
|
||
**병렬**: Phase 1 — 독립 실행 가능
|
||
|
||
### 2-A: formatAmount/formatNumber/formatCurrency 통일 — 21파일 완료
|
||
|
||
**canonical**: `src/lib/utils/amount.ts` → `formatNumber()`, `formatAmountWon()`
|
||
|
||
- [x] VehicleDispatch 3파일 → `import { formatNumber as formatAmount } from '@/lib/utils/amount'`
|
||
- [x] 결재 문서 5파일 → `import { formatNumber as formatCurrency } from '@/lib/utils/amount'`
|
||
- [x] SalesDetail, PurchaseDetail → `import { formatNumber as formatAmount } from '@/lib/utils/amount'`
|
||
- [x] GiftCertificateManagement, DailyReport → `import { formatNumber as formatAmount } from '@/lib/utils/amount'`
|
||
- [x] StageCard, ProjectCard → `import { formatNumber as formatAmount } from '@/lib/utils/amount'`
|
||
- [x] ProjectListClient → `import { formatAmountWon as formatAmount } from '@/lib/utils/amount'`
|
||
- [x] PricingTableForm, PricingTableListClient → `import { formatNumber } from '@/lib/utils/amount'`
|
||
- [x] DirectConstructionContent, IndirectConstructionContent → `import { formatNumber } from '@/lib/utils/amount'`
|
||
- [x] SubscriptionClient, SubscriptionManagement → `import { formatAmountWon as formatCurrency } from '@/lib/utils/amount'`
|
||
|
||
**스킵 (다른 동작):**
|
||
- ReceivablesStatus (0일 때 '' 반환), VendorLedger (0일 때 '' 반환), VendorLedgerDetail (괄호 옵션)
|
||
- CEODashboard/components.tsx (showUnit 옵션)
|
||
|
||
### 2-B: formatDate 통일 — 3파일 완료
|
||
|
||
**canonical**: `src/lib/utils/date.ts` → `formatDate()`
|
||
|
||
- [x] OrderManagementListClient, OrderManagementUnified, ConstructionManagementListClient → `import { formatDate } from '@/lib/utils/date'`
|
||
|
||
**스킵 (다른 출력 형식 — canonical formatDate와 비호환):**
|
||
- BoardDetail, BoardForm (formatDateTime: `YYYY-MM-DD HH:MM`)
|
||
- SubscriptionClient, SubscriptionManagement (한국어: `YYYY년 M월 D일`)
|
||
- PermissionManagement (date-fns format 사용)
|
||
- ProductionDashboard (`M/D` 형식)
|
||
- HandoverReportDocumentModal (한국어 long date)
|
||
|
||
### 검증
|
||
- [x] TypeScript 빌드 에러 없음 확인
|
||
- [x] 각 수정 파일에서 포맷 결과가 기존과 동일한지 확인 (동일 로직 import)
|
||
|
||
---
|
||
|
||
## WP-3: 차량관리 edit 페이지 리다이렉트 전환 ✅ 이전 세션에서 완료
|
||
|
||
**심각도**: 🟡 HIGH (코드 중복)
|
||
**난이도**: 낮음 | **파일 수**: 6 (3쌍)
|
||
**병렬**: Phase 1 — 독립 실행 가능
|
||
|
||
### 현황
|
||
이전 세션에서 이미 완료됨. 3개 edit 페이지 모두 리다이렉트 스텁으로 교체되어 있고,
|
||
3개 `[id]/page.tsx` 모두 `useSearchParams`로 mode를 읽고 있음.
|
||
|
||
### 수정 완료
|
||
|
||
- [x] `vehicle-management/vehicle/[id]/edit/page.tsx` → `router.replace(...?mode=edit)` 리다이렉트 스텁
|
||
- [x] `vehicle-management/vehicle/[id]/page.tsx` → `useSearchParams` + mode 처리
|
||
- [x] `vehicle-management/forklift/[id]/edit/page.tsx` → 리다이렉트 스텁
|
||
- [x] `vehicle-management/forklift/[id]/page.tsx` → `useSearchParams` + mode 처리
|
||
- [x] `vehicle-management/vehicle-log/[id]/edit/page.tsx` → 리다이렉트 스텁
|
||
- [x] `vehicle-management/vehicle-log/[id]/page.tsx` → `useSearchParams` + mode 처리
|
||
|
||
---
|
||
|
||
## WP-4: 공통 훅 추출 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🟡 HIGH (아키텍처 개선)
|
||
**난이도**: 중간 | **신규 파일**: 2개 | **적용 파일**: 18개
|
||
**병렬**: Phase 2 — WP-4와 WP-5는 서로 병렬 가능.
|
||
|
||
### 4-A: `useDateRange` 훅 — 15파일 적용 완료
|
||
|
||
**위치**: `src/hooks/useDateRange.ts`
|
||
**프리셋**: `'currentYear'` | `'currentMonth'` | `'today'` | `'none'`
|
||
|
||
- [x] `src/hooks/useDateRange.ts` 생성
|
||
- [x] 회계 5개 컴포넌트 적용:
|
||
- SalesManagement → `useDateRange('currentYear')`
|
||
- DepositManagement → `useDateRange('currentYear')`
|
||
- WithdrawalManagement → `useDateRange('currentYear')`
|
||
- BillManagement → `useDateRange('currentYear')`
|
||
- GiftCertificateManagement → `useDateRange('currentMonth')` (date-fns import 제거)
|
||
- [x] 건설 10개 ListClient 적용 (모두 `useDateRange('today')` — UTC 버그도 동시 수정):
|
||
- ProgressBillingManagementListClient, OrderManagementListClient
|
||
- ConstructionManagementListClient, IssueManagementListClient
|
||
- WorkerStatusListClient, PricingListClient
|
||
- UtilityManagementListClient, SiteManagementListClient
|
||
- StructureReviewListClient, HandoverReportListClient
|
||
|
||
**스킵 (비호환):**
|
||
- ExpectedExpenseManagement (현재월 ~ 3개월 후 커스텀 범위)
|
||
- TaxInvoiceIssuance (filters 객체 패턴, 별도 날짜 관리)
|
||
|
||
### 4-B: `useAccountingListPage` 훅 — 3개 page.tsx 적용 완료
|
||
|
||
**위치**: `src/hooks/useAccountingListPage.ts`
|
||
**효과**: 50줄 → 20줄 (DEFAULT_PAGINATION + useSearchParams + useEffect + state 통합)
|
||
|
||
- [x] `src/hooks/useAccountingListPage.ts` 생성 (DEFAULT_PAGINATION 포함)
|
||
- [x] `src/hooks/index.ts`에 양쪽 훅 export 추가
|
||
- [x] 회계 3개 page.tsx 적용:
|
||
- `accounting/sales/page.tsx` (56줄 → 22줄)
|
||
- `accounting/deposits/page.tsx` (53줄 → 20줄)
|
||
- `accounting/withdrawals/page.tsx` (53줄 → 20줄)
|
||
|
||
**미적용 (패턴 비호환):**
|
||
- bills: 추가 searchParams (billType, page, vendorId)
|
||
- expected-expenses: mode 없음, 커스텀 fetch params
|
||
- gift-certificates: 리스트 자체 로딩, edit 모드 별도
|
||
- bad-debt-collection: Promise.all + summary
|
||
- vendors: total 사용 (pagination 미사용)
|
||
- tax-invoice-issuance: 복합 mode (edit+id), Promise.all
|
||
|
||
### 검증
|
||
- [x] TypeScript 빌드 에러 없음 확인
|
||
- [x] 15파일 useDateRange 적용 + 3파일 useAccountingListPage 적용
|
||
|
||
---
|
||
|
||
## WP-5: 회계 컴포넌트 공통 패턴 추출 ✅ 완료
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 품질)
|
||
**난이도**: 중간 | **신규 파일**: 1개 | **영향 파일**: 5개 컴포넌트
|
||
**병렬**: Phase 2 — WP-4와 서로 병렬 가능 (겹치는 파일 없음)
|
||
|
||
### 5-A: 팩토리 함수 추출 ✅
|
||
|
||
**위치**: `src/components/accounting/shared/index.ts` (신규 생성)
|
||
|
||
4개 유틸리티 함수 생성 및 적용:
|
||
|
||
- [x] `createDeleteItemHandler(deleteFn, setData, msg)` — 4개 컴포넌트 적용 (Sales, Deposit, Withdrawal, Bill)
|
||
- 7줄 inline handler → 1줄 팩토리 호출 (컴포넌트당 -6줄)
|
||
- [x] `extractUniqueOptions(data, fieldKey, opts?)` — 5개 컴포넌트 적용 (Sales, Deposit, Withdrawal, Bill, ExpectedExpense)
|
||
- 4-6줄 useMemo body → 1줄 호출 (컴포넌트당 -3~5줄)
|
||
- [x] `createDateAmountSortFn(dateField, amountField, direction)` — 3개 컴포넌트 적용 (Sales, Deposit, Withdrawal)
|
||
- 15줄 switch문 → 1줄 팩토리 호출 (컴포넌트당 -14줄)
|
||
- Bill은 'maturityDate' 추가 정렬이 있어 제외, ExpectedExpense는 createdAt 정렬이라 제외
|
||
- [x] `computeMonthlyTotal(data, dateField, amountField)` — 3개 컴포넌트 적용 (Sales, Deposit, Withdrawal)
|
||
- 6줄 (currentMonth/currentYear + filter + reduce) → 1줄 (컴포넌트당 -5줄)
|
||
|
||
### 5-B: 스코프 조정 (계획 대비)
|
||
|
||
**적용하지 않은 항목과 사유:**
|
||
- `createFilterFn` — 각 컴포넌트의 customFilterFn이 너무 상이 (필드명, 조건문 구조 다름). 추상화 비용 > 이점
|
||
- `AccountSubjectSavePanel` — UI+로직이 각 컴포넌트마다 미묘하게 다름 (Withdrawal은 배열, Deposit은 Set). 현재 수준으로 충분
|
||
- `useRefreshableData` — Deposit/Withdrawal 2곳만 사용. 훅 생성 오버헤드가 이점을 초과
|
||
|
||
### 검증
|
||
- [x] TypeScript 빌드 에러 없음 (`npx tsc --noEmit` 통과)
|
||
- [x] 삭제/정렬/필터 로직이 기존과 동일한 동작 보장 (동일한 switch/filter 구현을 shared로 이동)
|
||
|
||
### 정량 결과
|
||
- **삭제된 중복 코드**: ~120줄 (5파일 × 평균 24줄/파일)
|
||
- **신규 공통 코드**: ~130줄 (shared/index.ts)
|
||
- **순 효과**: 중복 제거 + 단일 소스 오브 트루스 확보
|
||
|
||
---
|
||
|
||
## WP-6: toISOString UTC 버그 전환 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🟢 MEDIUM (잠재적 타임존 버그)
|
||
**난이도**: 중간 | **파일 수**: 15파일 26건 | **예상 변경량**: 각 1-2줄
|
||
**병렬**: Phase 3 — WP-4의 useDateRange가 먼저 필요 (일부 파일 중복)
|
||
|
||
### 현황
|
||
`new Date().toISOString().split('T')[0]`은 UTC 기준이라 KST 00:00~08:59에 전날 날짜 반환.
|
||
`src/lib/utils/date.ts`에 `getTodayString()`/`getLocalDateString()` 이미 존재.
|
||
|
||
### 수정 완료
|
||
|
||
**건설관리 10파일 — WP-4에서 useDateRange('today')로 이미 수정됨 (Phase 2에서 완료)**
|
||
|
||
**getTodayString() 적용 (7파일, 11건):**
|
||
- [x] `quotes/QuoteTransactionModal.tsx` — const today 초기화 (1건)
|
||
- [x] `vehicle-management/VehicleLogList/actions.ts` — writeDate + createdAt 기본값 (2건)
|
||
- [x] `pricing-table-management/actions.ts` — create/update changedDate (2건)
|
||
- [x] `pricing-table-management/PricingTableForm.tsx` — 변경일 Input value (1건)
|
||
- [x] `material/ReceivingManagement/actions.ts` — reportDate ×2 + today 변수 (3건)
|
||
- [x] `material/ReceivingManagement/ReceivingDetail.tsx` — adjustmentDate (1건)
|
||
- [x] `accounting/TaxInvoiceManagement/ManualEntryModal.tsx` — writeDate 기본값 (1건)
|
||
|
||
**getLocalDateString() 적용 (7파일, 13건):**
|
||
- [x] `pricing-distribution/PriceDistributionList.tsx` — startDate + endDate (2건)
|
||
- [x] `pricing-distribution/actions.ts` — createdAt + effectiveDate (2건)
|
||
- [x] `material/StockStatus/StockStatusList.tsx` — startDate + endDate (2건)
|
||
- [x] `quality/InspectionManagement/InspectionList.tsx` — startDate + endDate (2건)
|
||
- [x] `material/ReceivingManagement/ReceivingList.tsx` — startDate + endDate (2건)
|
||
- [x] `outbound/ShipmentManagement/ShipmentList.tsx` — startDate + endDate (2건)
|
||
- [x] `outbound/VehicleDispatchManagement/VehicleDispatchList.tsx` — startDate + endDate (2건)
|
||
|
||
**both 적용 (1파일, 2건):**
|
||
- [x] `accounting/TaxInvoiceManagement/CardHistoryModal.tsx` — today (getTodayString) + monthAgo (getLocalDateString)
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과 — TypeScript 에러 0건
|
||
- [x] `src/` 내 잔여 `.toISOString().split('T')[0]` = 0건 (date.ts 주석 1건 제외)
|
||
|
||
---
|
||
|
||
## 병렬 실행 계획 요약
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Phase 1 (독립 — 동시 3개 병렬) │
|
||
│ │
|
||
│ WP-1 날짜 하드코딩 WP-2 format 통일 WP-3 edit 리다이렉트 │
|
||
│ (3파일, ~10분) (35파일, ~40분) (6파일, ~20분) │
|
||
│ ↓ ↓ ↓ │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ Phase 2 (Phase 1 완료 후 — 동시 2개 병렬) │
|
||
│ │
|
||
│ WP-4 공통 훅 추출 WP-5 컴포넌트 공통화 │
|
||
│ (신규 2-3파일 + 70파일 적용) (신규 3-5파일 + 7파일 적용) │
|
||
│ ↓ ↓ │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ Phase 3 (Phase 2 완료 후) │
|
||
│ │
|
||
│ WP-6 toISOString UTC 버그 전환 │
|
||
│ (60+파일, 가장 큰 작업) │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Phase별 병렬 가능 근거
|
||
|
||
| Phase | WP 조합 | 병렬 가능 이유 |
|
||
|-------|---------|---------------|
|
||
| 1 | WP-1 + WP-2 + WP-3 | 수정 파일이 완전히 겹치지 않음. 기존 유틸만 사용, 신규 생성 없음 |
|
||
| 2 | WP-4 + WP-5 | WP-4는 hooks/ + page.tsx, WP-5는 components/accounting/shared/ + 컴포넌트 내부. 파일 겹침 없음 |
|
||
| 3 | WP-6 단독 | WP-4의 useDateRange 훅을 일부 파일에서 활용해야 하므로 Phase 2 이후 |
|
||
|
||
---
|
||
|
||
## WP-7: .toLocaleString() → formatNumber() 마이그레이션 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 일관성)
|
||
**난이도**: 낮음 | **파일 수**: 52파일, 183건 | **방법**: Node.js 자동 마이그레이션 스크립트
|
||
|
||
### 수정 완료
|
||
- [x] 52개 파일에서 183건 `.toLocaleString()` → `formatNumber()` 자동 치환
|
||
- [x] `formatNumber` import 자동 추가
|
||
- [x] 5개 파일 수동 import 수정 (double-quote import 패턴)
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과
|
||
- [x] `src/` 내 잔여 `.toLocaleString()` = 0건 (amount.ts 내부 제외)
|
||
|
||
---
|
||
|
||
## WP-8: 인라인 formatDate → date.ts import 마이그레이션 ✅ 완료 (2026-02-19)
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 일관성)
|
||
**난이도**: 낮음 | **파일 수**: 21파일, 32건 | **방법**: Node.js 자동 마이그레이션 스크립트
|
||
|
||
### 수정 완료
|
||
- [x] `.split('T')[0]` → `formatDate()` 변환 (21파일)
|
||
- [x] `new Date().toISOString().slice(0, 10)` → `getTodayString()` 변환
|
||
- [x] `dateVar.toISOString().slice(0, 10)` → `getLocalDateString(dateVar)` 변환
|
||
- [x] 6개 파일 수동 import 수정 (JSDoc 삽입 버그)
|
||
|
||
### 스킵 항목
|
||
- `?.split('T')[0] || ''` — formatDate는 null일 때 '-' 반환 (falsy 의미 다름)
|
||
- `.toLocaleDateString()` — 42건, 로케일 표시 형식으로 canonical과 비호환
|
||
- `.toISOString().slice(0,10).replace(/-/g,'')` — YYYYMMDD 형식 (파일명용)
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과
|
||
|
||
---
|
||
|
||
## WP-9: useDeleteDialog 훅 채택 확대 ✅ 완료 (2026-02-20)
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 일관성)
|
||
**난이도**: 중간 | **전체 후보**: ~56파일 | **기존 채택자**: 7파일
|
||
|
||
### 완료된 작업 (9파일)
|
||
- [x] `src/hooks/index.ts`에 useDeleteDialog export 추가
|
||
- [x] `settings/RankManagement/index.tsx` 마이그레이션 (단건 삭제, number ID)
|
||
- [x] `settings/TitleManagement/index.tsx` 마이그레이션 (단건 삭제, number ID)
|
||
- [x] `settings/AccountManagement/AccountDetail.tsx` 마이그레이션 (상세→삭제→목록, number ID)
|
||
- [x] `settings/PermissionManagement/PermissionDetailClient.tsx` 마이그레이션 (상세→삭제→목록, number ID)
|
||
- [x] `accounting/DepositManagement/DepositDetail.tsx` 마이그레이션 (상세→삭제→목록)
|
||
- [x] `accounting/WithdrawalManagement/WithdrawalDetail.tsx` 마이그레이션 (상세→삭제→목록)
|
||
- [x] `hr/CardManagement/CardDetail.tsx` 마이그레이션 (상세→삭제→목록)
|
||
- [x] `board/BoardDetail/index.tsx` 마이그레이션 (deletePost 클로저 캡처, 2-arg delete)
|
||
- [x] `board/BoardManagement/BoardDetailClientV2.tsx` 마이그레이션 (deleteBoard + forceRefreshMenus)
|
||
|
||
### 의도적 스킵 (마이그레이션 비적합)
|
||
- `settings/AccountManagement/AccountDetailForm.tsx` — prop 기반 삭제 + isSaving 공유
|
||
- `settings/PermissionManagement/PermissionDetail.tsx` — prop 기반 + IntegratedDetailTemplate 연동
|
||
- `settings/PermissionManagement/index.tsx` — bulk+single 혼합 다이얼로그
|
||
- `board/CommentSection/CommentItem.tsx` — void onDelete prop, 행동 변경됨
|
||
- `hr/EmployeeManagement/index.tsx` — 780줄, 복잡한 useMemo, 위험도 높음
|
||
- `hr/DepartmentManagement/index.tsx` — bulk+single 혼합 다이얼로그
|
||
- `settings/PopupManagement/PopupDetailClientV2.tsx` — IntegratedDetailTemplate 내부 처리
|
||
|
||
### 최종 채택 현황: 7(기존) + 9(신규) = 16파일
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과 (모든 수정 파일 tsc 에러 0건)
|
||
|
||
---
|
||
|
||
### Phase 간 의존성 상세
|
||
|
||
| 의존 관계 | 이유 |
|
||
|-----------|------|
|
||
| WP-4 → WP-1 | WP-1에서 수정한 날짜 초기값 패턴을 useDateRange 훅 설계에 반영 |
|
||
| WP-5 → WP-2 | WP-2에서 통일된 formatAmount를 공통 컴포넌트에서 import |
|
||
| WP-6 → WP-4 | useDateRange가 getTodayString()을 내부 사용하므로 훅 완성 후 적용 |
|
||
|
||
---
|
||
|
||
## WP-10: 검색 필터 유틸 search.ts ✅ 완료 (2026-02-20)
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 일관성)
|
||
**난이도**: 중간 | **신규 파일**: 1개 | **적용 파일**: 9개
|
||
|
||
### 10-A: search.ts 유틸 생성 ✅
|
||
|
||
**위치**: `src/lib/utils/search.ts` (~70줄)
|
||
- [x] `filterByText<T>(data, query, fields, options?)` — 텍스트 검색 (case-insensitive 기본)
|
||
- [x] `filterByEnum<T>(data, field, value, allValue?)` — enum 필터 ('all' short-circuit)
|
||
- [x] `filterByDateRange<T>(data, field, startDate?, endDate?)` — 날짜 범위 필터
|
||
- [x] `applyFilters<T>(data, filters)` — 필터 체이닝 파이프라인
|
||
- [x] `textFilter`, `enumFilter`, `dateRangeFilter` — 팩토리 함수 (applyFilters용)
|
||
|
||
### 10-B: 회계 모듈 적용 (9파일) ✅
|
||
|
||
| # | 파일 | 변경 내용 | 상태 |
|
||
|---|------|----------|------|
|
||
| 1 | `VendorManagement/VendorManagementClient.tsx` | useMemo 체인 → `applyFilters` (text 3필드 + enum 4개) | ✅ |
|
||
| 2 | `BadDebtCollection/index.tsx` | customFilterFn → `applyFilters` (enum 2개) | ✅ |
|
||
| 3 | `ExpectedExpenseManagement/index.tsx` | useMemo 체인 → `applyFilters` (text 3필드 + enum 1개) | ✅ |
|
||
| 4 | `SalesManagement/index.tsx` | customFilterFn → `applyFilters` (enum 2개 + issuance 인라인 유지) | ✅ |
|
||
| 5 | `DepositManagement/index.tsx` | customFilterFn → `applyFilters` (text 4필드 + enum 2개) | ✅ |
|
||
| 6 | `WithdrawalManagement/index.tsx` | customFilterFn → `applyFilters` (text 4필드 + enum 2개) | ✅ |
|
||
| 7 | `CardTransactionInquiry/index.tsx` | filteredData useMemo → `filterByEnum` (1개) | ✅ |
|
||
| 8 | `ReceivablesStatus/index.tsx` | filteredData useMemo → `filterByText` (1필드) | ✅ |
|
||
| 9 | `GiftCertificateManagement/index.tsx` | customFilterFn → `applyFilters` (enum 2개) | ✅ |
|
||
|
||
**스킵**: BillManagement — 서버 사이드 필터링 (API params), 클라이언트 사이드 필터 없음
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과 (기존 orders/actions.ts 1건 외 에러 0건)
|
||
|
||
---
|
||
|
||
## WP-11: 상태 설정 채택 확대 ✅ 완료 (2026-02-20)
|
||
|
||
**심각도**: 🟢 MEDIUM (코드 일관성)
|
||
**난이도**: 중간 | **수정 파일**: status-config.ts + types.ts 4개
|
||
|
||
### 11-A: 도메인별 상태 설정 추가 (status-config.ts) ✅
|
||
|
||
7개 회계 도메인 설정 추가:
|
||
- [x] `BAD_DEBT_COLLECTION_STATUS_CONFIG` (collecting, legalAction, recovered, badDebt)
|
||
- [x] `TAX_INVOICE_STATUS_CONFIG` (pending, journalized, error)
|
||
- [x] `BILL_STATUS_CONFIG` (stored~dishonored 8개)
|
||
- [x] `SALES_STATUS_CONFIG` (monthlyClose, lastMonth, agreed, outstanding)
|
||
- [x] `DEPOSIT_STATUS_CONFIG` (inputWaiting~confirmed 7개)
|
||
- [x] `PAYMENT_STATUS_CONFIG` (pending, partial, paid, overdue)
|
||
- [x] `MATCH_STATUS_CONFIG` (matched, unmatched)
|
||
|
||
### 11-B: types.ts 인라인 상수 마이그레이션 (4파일) ✅
|
||
|
||
| # | 파일 | 제거한 인라인 상수 | 대체 |
|
||
|---|------|-------------------|------|
|
||
| 1 | `BadDebtCollection/types.ts` | COLLECTION_STATUS_LABELS, STATUS_BADGE_STYLES, STATUS_FILTER_OPTIONS, STATUS_SELECT_OPTIONS | `BAD_DEBT_COLLECTION_STATUS_CONFIG` re-export |
|
||
| 2 | `ExpectedExpenseManagement/types.ts` | PAYMENT_STATUS_LABELS, PAYMENT_STATUS_FILTER_OPTIONS | `PAYMENT_STATUS_CONFIG` re-export |
|
||
| 3 | `DailyReport/types.ts` | MATCH_STATUS_LABELS, MATCH_STATUS_COLORS | `MATCH_STATUS_CONFIG` re-export |
|
||
| 4 | `DepositManagement/types.ts` | DEPOSIT_STATUS_LABELS, DEPOSIT_STATUS_COLORS | `DEPOSIT_STATUS_CONFIG` re-export |
|
||
|
||
**스킵 (shape 비호환):**
|
||
- SalesManagement — `SALES_STATUS_LABELS`에 'all' 키 포함, STATUS_LABELS와 shape 불일치
|
||
- TaxInvoiceManagement — `INVOICE_STATUS_MAP`가 `{label, color}` 결합 형태, 분리하면 더 복잡
|
||
- WithdrawalManagement — WITHDRAWAL_TYPE 설정 미추가 (status가 아닌 type 분류)
|
||
- BillManagement — 수취/발행 분기 헬퍼 함수 복잡
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과 (기존 orders/actions.ts 1건 외 에러 0건)
|
||
- [x] types.ts re-export로 소비 컴포넌트 import 경로 변경 불필요
|
||
|
||
---
|
||
|
||
## WP-12: Loading Skeleton 전환 (GenericPageSkeleton → ListPageSkeleton) ✅ 완료 (2026-02-20)
|
||
|
||
**심각도**: 🟢 MEDIUM (UX 개선)
|
||
**난이도**: 낮음 | **파일 수**: 9 | **예상 변경량**: 각 2줄 (import + JSX)
|
||
|
||
### 현황
|
||
회계 모듈 9개 page.tsx가 `GenericPageSkeleton`(form 레이아웃 고정)을 사용하여 실제 리스트 페이지 구조(필터+통계카드+테이블)와 불일치.
|
||
이미 `ListPageSkeleton`이 존재하지만 회계 모듈에서 미사용.
|
||
|
||
### 수정 완료 (9파일)
|
||
|
||
| # | 파일 | props | 상태 |
|
||
|---|------|-------|------|
|
||
| 1 | `accounting/deposits/page.tsx` | `showStats statsCount={4} tableColumns={7}` | ✅ |
|
||
| 2 | `accounting/sales/page.tsx` | `showStats statsCount={4} tableColumns={10}` | ✅ |
|
||
| 3 | `accounting/withdrawals/page.tsx` | `showStats statsCount={4} tableColumns={7}` | ✅ |
|
||
| 4 | `accounting/bad-debt-collection/page.tsx` | `showDateRange={false} showCreateButton={false} showStats statsCount={4} tableColumns={8}` | ✅ |
|
||
| 5 | `accounting/bills/page.tsx` | `tableColumns={9}` | ✅ |
|
||
| 6 | `accounting/expected-expenses/page.tsx` | `showStats statsCount={2} tableColumns={7}` | ✅ |
|
||
| 7 | `accounting/vendors/page.tsx` | `showDateRange={false} showStats statsCount={3} tableColumns={10}` | ✅ |
|
||
| 8 | `accounting/tax-invoice-issuance/page.tsx` | `showStats statsCount={4} tableColumns={10}` | ✅ |
|
||
| 9 | `accounting/gift-certificates/page.tsx` | `showStats statsCount={4} tableColumns={8}` | ✅ |
|
||
|
||
### 검증
|
||
- [x] `npx tsc --noEmit` 통과 (기존 orders/actions.ts 1건 외 에러 0건)
|
||
- [x] `GenericPageSkeleton` 회계 모듈 내 잔존 0건
|
||
- [x] 브라우저 화면 검수: Slow 3G + CPU 20x 쓰로틀링으로 스켈레톤 캡처 확인
|
||
- [x] vendors 페이지 showCreateButton 수정 (화면 검수에서 발견)
|