- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동) - 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/) - 기획팀 폴더 requests/ 생성 - plans/ → dev/dev_plans/ 이름 변경 - README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용) - resources.md 신규 (노션 링크용, assets/brochure 이관 예정) - CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동 - 전체 참조 경로 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 KiB
React 목업 데이터 → API 연동 마이그레이션 계획
작성일: 2025-12-23 목적: React 프론트엔드의 목업 데이터를 실제 API와 연동 참고 문서:
react-api-integration-plan.md,erp-api-development-plan-d1.0-changes.md참조 구현: 단가관리 (/sales/pricing-management)
1. 개요
1.1 현황 분석
목업 데이터 사용 페이지: 80개+ 파일에서 목업 데이터 사용 중
┌─────────────────────────────────────────────────────────────────┐
│ 🎯 연동 목표 │
├─────────────────────────────────────────────────────────────────┤
│ - React 목업 데이터 → 실제 API 호출로 전환 │
│ - 단가관리(pricing-management) 패턴을 표준으로 적용 │
│ - Phase A~B (API 완료 기능) 우선 연동 │
└─────────────────────────────────────────────────────────────────┘
1.4 전수 조사 결과 (2025-12-26 최신)
MCP Serena를 활용한 React 전체 Mock 데이터 사용 현황 전수 조사 결과
🔍 발견된 주요 패턴
| 문제 유형 | 파일 수 | 설명 |
|---|---|---|
| mockData.ts 파일 | 8개 | 별도 Mock 데이터 파일 (삭제 필요) |
| MOCK_ 상수* | 15개+ | 인라인 Mock 상수 |
| console.log CRUD | 40개+ | API 대신 console.log 출력 |
| TODO 주석 | 30개+ | 미구현 기능 |
🚨 "완료" 표시됐지만 잔여 작업 있는 Phase
| Phase | 항목 | 발견된 문제 |
|---|---|---|
| B-2 | 매입 관리 | MOCK_ACCOUNTS, MOCK_VENDORS 사용 (PurchaseDetailModal) |
| C-1 | 직원 관리 | TODO: 파일 업로드, console.log('Invite user') |
| D-4 | 근태 설정 | MOCK_DEPARTMENTS 사용 |
| F-1~4 | 결재 시스템 | MOCK_EMPLOYEES 사용 (결재선/참조자 선택) |
📋 문서에 누락된 모듈 (Phase J~L로 추가됨)
| 카테고리 | 경로 | Mock 사용 현황 |
|---|---|---|
| 게시판 | /board/* |
MOCK_BOARDS, MOCK_DEPARTMENTS |
| FAQ | /customer-center/faq |
MOCK_FAQS 전체 사용 |
| 이벤트 | /customer-center/events |
MOCK_EVENTS 전체 사용 |
| 문의 | /customer-center/inquiries |
MOCK_INQUIRIES, MOCK_REPLY, MOCK_COMMENTS |
| 공지사항 | /customer-center/notices |
MOCK_NOTICES 전체 사용 |
| 공정관리 | /master-data/process-management |
✅ 완료 (2025-12-26) |
| 견적 | /sales/quote-management |
✅ 완료 (2025-12-26) |
📁 mockData.ts 삭제 대상
react/src/components/
├── production/ProductionDashboard/mockData.ts ← G-3
├── production/WorkOrders/mockData.ts ← G-1 (부분 사용)
├── production/WorkResults/mockData.ts ← G-2 (부분 사용)
├── quality/InspectionManagement/mockData.ts ← G-5
├── material/ReceivingManagement/mockData.ts ← H-1 연동 완료
├── material/StockStatus/mockData.ts ← H-2 연동 완료
├── outbound/ShipmentManagement/mockData.ts ← H-3 연동 완료
└── reports/mockData.ts ← 확인 필요
1.5 작업 진행 정책
단위 작업 → 검수 → 승인 → 문서 업데이트 → 커밋 순서로 진행
1.6 세션 규칙 및 Serena 메모리 관리
세션 간 일관성 보장을 위한 필수 규칙
세션 시작 프로토콜 (필수)
1. Serena 메모리 로드
read_memory("mock-to-api-state") → 현재 Phase/작업 확인
read_memory("mock-to-api-snapshot") → 마지막 작업 내용 확인
2. 현재 상태 확인
- 이 문서 읽기
- 현재 Phase의 기능별 상태 확인
- "다음 작업은 [Phase]-[번호]의 [기능] 입니다" 명시
3. 작업 범위 명확화
- 사용자에게 작업 범위 확인
- "[Phase] 전체를 진행할까요, 특정 기능만 진행할까요?"
Serena 메모리 구조
// mock-to-api-state
{
"current_phase": "G",
"current_item": "G-1",
"current_feature": "목록 조회",
"progress": {
"G-1": { "목록": "완료", "상세": "진행중", "등록": "대기" }
},
"last_update": "2025-12-26 14:30"
}
// mock-to-api-snapshot
"G-1 작업지시관리: 목록 조회 API 연동 완료.
다음: 상세 조회 연동 예정"
작업 완료 시 (필수)
1. 문서 업데이트
- 해당 기능 상태 변경 (⏳ → ✅)
- 변경 이력 추가
2. Serena 메모리 저장
write_memory("mock-to-api-state", 현재 상태)
write_memory("mock-to-api-snapshot", 작업 내용 요약)
3. 커밋
feat: [Phase]-[번호] [페이지명] Mock → API 연동
1.7 작업 템플릿 (표준)
각 기능별 작업 시 사용하는 표준 템플릿
## [Phase-번호] 페이지명 - [기능명] 연동
**작업 대상:**
- 컴포넌트: `ComponentName.tsx`
- 액션: `actions.ts`
- API: `GET/POST/PUT/DELETE /api/v1/endpoint`
**작업 절차:**
1. [ ] API 스펙 확인 (Swagger)
2. [ ] actions.ts 함수 확인/생성
3. [ ] 타입 정의 확인 (API ↔ Frontend)
4. [ ] 컴포넌트에서 actions 호출
5. [ ] console.log/MOCK 제거
6. [ ] 브라우저 테스트
**결과:**
- [ ] 검수 요청
- [ ] [승인] 문서 업데이트
- [ ] [승인] 커밋
┌─────────────────────────────────────────────────────────────────┐
│ 📋 작업 흐름 (페이지 단위) │
├─────────────────────────────────────────────────────────────────┤
│ 1️⃣ 작업 시작: 대상 페이지 Mock → API 연동 작업 │
│ 2️⃣ 작업 완료: 코드 수정 완료 후 사용자에게 검수 요청 │
│ 3️⃣ 검수: 사용자가 기능 확인 (브라우저 테스트) │
│ 4️⃣ [승인] 문서 업데이트: 이 문서의 상태 갱신 │
│ 5️⃣ [승인] 커밋: Git 커밋 생성 │
│ 6️⃣ 다음 페이지로 이동 │
└─────────────────────────────────────────────────────────────────┘
⚠️ 중요 규칙:
- 각 단계에서
[승인]표시된 작업은 사용자 승인 후 진행 - 한 번에 하나의 페이지만 작업 (병렬 작업 금지)
- 검수 실패 시 수정 후 재검수
- 커밋 메시지:
feat: [Phase]-[번호] [페이지명] Mock → API 연동
📌 현재 진행 순서:
A-1 악성채권(완료 - 상세+CRUD+메모 API 연동)A-2 팝업 관리(완료 - 상세+CRUD API 연동)- A-3 결제 내역 (조회 전용, 완료)
- A-4 구독 관리 (조회 전용, 완료)
- A-5 알림 설정 (완료)
- B-1 매출 관리
- B-2 매입 관리
- B-3 입금 관리
- B-4 출금 관리
- B-5 거래처 관리
- B-6 어음 관리
1.2 단가관리 연동 패턴 (표준 참조)
┌─────────────────────────────────────────────────────────────────┐
│ 📂 파일 구조 │
├─────────────────────────────────────────────────────────────────┤
│ react/src/ │
│ ├── app/[locale]/(protected)/sales/pricing-management/ │
│ │ └── page.tsx ← 서버 컴포넌트 (API 호출) │
│ │ │
│ └── components/pricing/ │
│ ├── types.ts ← 타입 정의 │
│ ├── actions.ts ← Server Actions (CRUD) │
│ ├── PricingListClient.tsx ← 클라이언트 컴포넌트 │
│ └── index.ts ← Export │
└─────────────────────────────────────────────────────────────────┘
데이터 흐름:
page.tsx (서버)
↓ API 호출 (fetch)
↓ 데이터 변환 (API → Frontend)
↓ initialData prop 전달
ListClient.tsx (클라이언트)
↓ useState로 데이터 관리
↓ UI 렌더링
1.3 핵심 패턴 요약
| 구분 | 파일 | 역할 |
|---|---|---|
| 타입 | types.ts |
프론트엔드 인터페이스 정의 |
| 서버 페이지 | page.tsx |
API 호출, 데이터 병합, 초기 데이터 전달 |
| 서버 액션 | actions.ts |
CRUD 작업, 데이터 변환 함수 |
| 클라이언트 | *Client.tsx |
UI 렌더링, 사용자 상호작용 |
2. 우선순위별 연동 대상
상태 범례:
- ✅ 완료: API 연동 완료 (Server Actions 호출)
- 🔄 Mock: Mock 데이터 또는 console.log 사용
- ⚠️ API 필요: 백엔드 API 개발 선행 필요
- ⏭️ 건너뜀: API 미존재 또는 해당 없음
- 📦 actions.ts: Server Actions 파일 존재 (UI 연동 필요)
2.1 Phase A: API 완료 기능 (즉시 연동 가능)
이미 API가 구현되어 있어 React 연동만 필요 ⚠️ 2025-12-24 전수 조사 결과: 리스트 API 연동 완료했으나 상세/CRUD 작업에서 Mock 사용 확인
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| A-1 | 악성채권 관리 | /accounting/bad-debt-collection |
✅ | ✅ | ✅ | ✅ | ✅ | 상세+CRUD+메모 API 연동 완료 (2025-12-24) |
| A-2 | 팝업 관리 | /settings/popup-management |
✅ | ✅ | ✅ | ✅ | ✅ | 상세+CRUD API 연동 완료 (2025-12-24) |
| A-3 | 결제 내역 | /settings/payment-history |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 조회 전용 |
| A-4 | 구독 관리 | /settings/subscription |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 조회 전용 |
| A-5 | 알림 설정 | /settings/notifications |
✅ | ⏭️ | ⏭️ | ✅ | ⏭️ | 저장 기능 완료 |
2.2 Phase B: 핵심 업무 기능
⚠️ 2025-12-24 전수 조사 결과: actions.ts 존재하나 UI에서 console.log로 Mock 처리
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| B-1 | 매출 관리 | /accounting/sales |
✅ | ✅ | ✅ | ✅ | ✅ | API 연동 완료, alert→toast 변환 |
| B-2 | 매입 관리 | /accounting/purchase |
✅ | ✅ | ✅ | ✅ | ✅ | API 연동 완료, alert→toast 변환 |
| B-3 | 입금 관리 | /accounting/deposit |
✅ | ✅ | ✅ | ✅ | ✅ | API 연동 완료, alert→toast 변환 |
| B-4 | 출금 관리 | /accounting/withdrawal |
✅ | ✅ | ✅ | ✅ | ✅ | API 연동 완료, alert→toast 변환 |
| B-5 | 거래처 관리 | /accounting/vendor |
✅ | ✅ | ✅ | ✅ | ✅ | API 연동 완료, console.error 제거 |
| B-6 | 어음 관리 | /accounting/bills |
✅ | ⏭️ 모달 | ✅ | ✅ | ✅ | API 연동 완료 |
2.3 Phase C: 인사/근태
2025-12-24 분석 결과: API 존재, 전체 Mock 사용 중
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| C-1 | 직원 관리 | /hr/employee-management |
✅ | ✅ | ✅ | ✅ | ✅ | 2025-12-24 연동 완료 - actions.ts, utils.ts 생성, 전체 CRUD API 연동 |
| C-2 | 근태 관리 | /hr/attendance |
✅ | ⏭️ | ✅ | ⏭️ | ⏭️ | 2025-12-24 연동 완료 - actions.ts 생성, check-in/check-out/today API 연동 |
| C-3 | 휴가 관리 | /hr/vacation-management |
✅ | ⏭️ | ✅ | ⏭️ | ⏭️ | 2025-12-24 연동 완료 - actions.ts 생성, 신청현황 탭 API 연동 (목록/승인/반려/신청), 사용현황/부여현황 탭 API 연동 |
| C-4 | 부서 관리 | /hr/departments |
✅ | ⏭️ | ✅ | ✅ | ✅ | 2025-12-24 연동 완료 - actions.ts 생성, 트리 조회/생성/수정/삭제 API 연동 |
2.4 Phase D: 설정/시스템 관리
2025-12-24 분석 결과: 대부분 Mock, console.log로 저장 처리
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| D-1 | 회사 정보 관리 | /settings/company-info |
✅ | ⏭️ | ⏭️ | ✅ | ⏭️ | 2025-12-24 연동 완료 - actions.ts 생성, API 조회/수정 연동 |
| D-2 | 계정 관리 | /settings/accounts |
✅ | ✅ | ✅ | ✅ | ✅ | 2025-12-24 연동 완료 - actions.ts 생성, CRUD API 연동 |
| D-3 | 근무 일정 관리 | /settings/work-schedule |
✅ | ⏭️ | ⏭️ | ✅ | ⏭️ | 2025-12-24 연동 완료 - actions.ts 생성, 조회/수정 API 연동 |
| D-4 | 근태 설정 관리 | /settings/attendance-settings |
✅ | ⏭️ | ⏭️ | ✅ | ⏭️ | 2025-12-24 연동 완료 - actions.ts 생성, GPS/허용반경 API 연동 |
2.5 Phase E: 인사/급여
2025-12-25 완료: API 연동 완료
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| E-1 | 법인카드 관리 | /hr/card-management |
✅ | ✅ | ✅ | ✅ | ✅ | 2025-12-25 완료 - actions.ts 생성, CRUD+토글+일괄삭제 API 연동, CardForm 직원목록 API 연동 |
| E-2 | 급여 관리 | /hr/salary |
✅ | ✅ | ⏭️ | ✅ | ⏭️ | 2025-12-25 완료 - Salary API 신규 생성, actions.ts 생성, 목록/상세/상태변경/일괄상태변경 API 연동 |
2.6 Phase F: 결재 시스템
2025-12-25 완료: 전체 API 연동 완료
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| F-1 | 기안함 | /approval/draft-box |
✅ | ⏭️ | ⏭️ | ⏭️ | ✅ | 2025-12-25 완료 - actions.ts 생성, 목록/삭제/일괄삭제 API 연동 |
| F-2 | 참조함 | /approval/reference-box |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 2025-12-25 완료 - actions.ts 생성, 목록/열람처리/일괄처리 API 연동 |
| F-3 | 결재함 | /approval/approval-box |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 2025-12-25 완료 - actions.ts 생성, 목록/승인/반려/일괄처리 API 연동 |
| F-4 | 비용견적서 양식 | /approval/create/expense-estimate |
⏭️ | ⏭️ | ✅ | ⏭️ | ⏭️ | 2025-12-25 완료 - actions.ts 생성, 비용견적서 항목조회/문서생성/상신 API 연동 |
2.7 Phase G: 생산 관리
2025-12-26 완료: 전체 API 연동 완료
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| G-1 | 작업지시 관리 | /production/work-orders |
✅ | ✅ | ✅ | ⏭️ | ⏭️ | 2025-12-26 완료 - actions.ts 생성, 목록/상세/등록/담당자선택/수주선택 API 연동 |
| G-2 | 작업실적 관리 | /production/work-results |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 2025-12-26 완료 - actions.ts 생성, 목록/통계 API 연동 |
| G-3 | 생산 대시보드 | /production/dashboard |
✅ | ⏭️ | ⏭️ | ⏭️ | ⏭️ | 2025-12-26 완료 - actions.ts 생성, 대시보드 데이터 API 연동 |
| G-4 | 작업자 화면 | /production/worker-screen |
✅ | ⏭️ | ✅ | ⏭️ | ⏭️ | 2025-12-26 완료 - actions.ts 생성, 작업목록/완료/자재투입/공정단계/검사요청 API 연동 |
| G-5 | 품질 검사 | /quality/inspection |
✅ | ✅ | ✅ | ✅ | ⏭️ | 2025-12-26 완료 - actions.ts 생성, 목록/상세/등록/수정 API 연동 |
2.8 Phase H: 자재/출하 관리
2025-12-24 분석 결과: 전체 Mock (mockData.ts 파일 사용)
| # | 페이지 | React 경로 | 리스트 | 상세 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|---|
| H-1 | 입고 관리 | /material/receiving |
✅ | ✅ | ✅ | ✅ | ✅ | 2025-12-26 연동 완료 - actions.ts 생성, 목록/상세/등록/수정/삭제/통계/옵션 API 연동 |
| H-2 | 재고 현황 | /material/stock-status |
✅ | ✅ | ⏭️ | ⏭️ | ⏭️ | 2025-12-26 연동 완료 - actions.ts 생성, 목록/상세/통계/옵션 API 연동 |
| H-3 | 출하 관리 | /outbound/shipment |
✅ | ✅ | ✅ | ✅ | ✅ | 2025-12-26 연동 완료 - actions.ts 생성, 목록/상세/등록/수정/삭제/통계/옵션 API 연동 |
2.9 Phase I: API 연동 및 UI 완성도 개선
2025-12-26 완료: 전체 항목 API 연동 및 UI CRUD 기능 보완 완료
| # | 페이지 | React 경로 | 조회 | 등록 | 수정 | 삭제 | 기타 | 비고 |
|---|---|---|---|---|---|---|---|---|
| I-1 | 미지급비용 관리 | /accounting/expected-expense |
✅ | ✅ | ✅ | ✅ | 예상지급일변경 ✅ | 2025-12-26 완료 - 등록/수정 폼 다이얼로그, 삭제/일괄삭제 구현 |
| I-2 | 거래처 원장 | /accounting/vendor-ledger |
✅ | ⏭️ | ⏭️ | ⏭️ | 상세이동 ✅, 엑셀/PDF ✅ | 조회전용 - exportVendorLedgerExcel, exportVendorLedgerDetailPdf API 연동 |
| I-3 | 카드 거래 조회 | /accounting/card-transaction |
✅ | ⏭️ | ✅ | ⏭️ | 계정과목 일괄수정 ✅ | 외부연동 데이터 (등록/삭제 불필요) |
| I-4 | 은행 거래 조회 | /accounting/bank-transaction |
✅ | ⏭️ | ✅ | ⏭️ | - | 2025-12-26 확인 - 수정은 상세 페이지 이동 방식 (deposits/{id}?mode=edit) |
| I-5 | 채권 현황 | /accounting/receivables-status |
✅ | ⏭️ | ✅ | ⏭️ | 연체토글 ✅, 엑셀 ✅ | 2025-12-26 완료 - updateOverdueStatus, exportReceivablesExcel API 연동 |
| I-6 | 일일 보고서 | /accounting/daily-report |
✅ | ⏭️ | ⏭️ | ⏭️ | 엑셀 ✅ | 조회전용 리포트 - exportDailyReportExcel API 연동 |
| I-7 | 종합 분석 보고서 | /reports/comprehensive-analysis |
✅ | ⏭️ | ⏭️ | ⏭️ | 이슈승인 ✅ | 2025-12-26 완료 - approveIssue/rejectIssue API 연동 |
| I-8 | 휴가 정책 관리 | /settings/leave-policy |
✅ | ⏭️ | ✅ | ⏭️ | - | ✅ 완료 (단일 레코드 설정 관리) |
Phase I 상세 분석 (2025-12-26)
I-1 미지급비용 관리 (ExpectedExpenseManagement)
- actions.ts:
getExpectedExpenseList,createExpectedExpense,updateExpectedExpense,deleteExpectedExpense,bulkDeleteExpectedExpenses,updateExpectedPaymentDate✅ - UI 현황: 목록 조회 ✅, 예상지급일 변경 ✅, 등록 폼/모달 ❌, 수정 폼/모달 ❌, 삭제 버튼 ❌, 일괄삭제 버튼 ❌
- 필요 작업: UI에 등록/수정/삭제 기능 연동 (API는 완료)
I-2 거래처 원장 (VendorLedger)
- actions.ts:
getVendorLedgerList,getVendorLedgerSummary,getVendorLedgerDetail✅ - 특성: 거래처별 매출/수금 집계 조회 기능 → CRUD 불필요 (읽기전용이 정상)
- 상태: ✅ 완료 (조회전용)
I-3 카드거래조회 (CardTransactionInquiry)
- actions.ts:
getCardTransactionList,getCardTransactionSummary,bulkUpdateAccountCode✅ - 특성: 외부 카드사 연동 데이터 → 등록/삭제 불필요, 계정과목 수정만 필요
- UI 현황: 조회 ✅, 체크박스 선택 ✅, 계정과목 일괄수정 Dialog ✅
- 상태: ✅ 완료
I-4 은행거래조회 (BankTransactionInquiry)
- actions.ts:
getBankTransactionList,getBankTransactionSummary,getBankAccountOptions✅ - 특성: 외부 은행 연동 데이터 → 등록/삭제 불필요
- UI 현황: 조회 ✅, 수정 아이콘(Pencil) 있으나 수정 API 없음
- 필요 작업: 은행거래 수정 API 개발 또는 수정 기능 제거 결정 필요
I-5 채권현황 (ReceivablesStatus)
- actions.ts:
getReceivablesList,getReceivablesSummary✅ - 특성: 거래처별 월별 채권 집계 데이터 → CRUD 불필요
- UI 현황: 조회 ✅, 연체 토글 Switch (UI만, API 미연동), 저장/엑셀 버튼 (placeholder)
- 필요 작업: 연체 토글 저장 API 개발 및 연동
I-6 일일보고서 (DailyReport)
- actions.ts:
getNoteReceivables,getDailyAccounts,getDailyReportSummary✅ - 특성: 일별 어음/계좌 현황 집계 리포트 → CRUD 불필요
- 상태: ✅ 완료 (조회전용)
I-7 종합분석 (ComprehensiveAnalysis)
- actions.ts:
getComprehensiveAnalysis✅ (reports/actions.ts) - 특성: 경영 대시보드 → CRUD 불필요
- UI 현황: 대시보드 카드/체크포인트 ✅, 오늘 이슈 승인/거절 버튼 (UI만, API 미연동)
- 필요 작업: 이슈 승인/거절 API 개발 및 연동 (선택사항)
I-8 휴가 정책 관리 (LeavePolicyManagement)
- actions.ts:
getLeavePolicy,updateLeavePolicy✅ - 특성: 단일 레코드 설정 관리 → 등록/삭제 불필요
- 상태: ✅ 완료
Phase J (게시판), Phase K (고객센터):
react-mock-remaining-tasks.md로 분리됨
2.10 Phase L: 기타 모듈
2025-12-26 전수 조사 결과: TODO + console.log 사용
| # | 페이지 | React 경로 | 조회 | 등록 | 수정 | 삭제 | 비고 |
|---|---|---|---|---|---|---|---|
| L-1 | 공정 관리 | /master-data/process-management |
✅ | ✅ | ✅ | ✅ | 2025-12-26 완료 - Backend API + React 연동 |
| L-2 | 견적 관리 | /sales/quote-management |
✅ | ✅ | ✅ | ✅ | 2025-12-26 완료 |
| L-3 | 종합 분석 | /reports/comprehensive-analysis |
✅ | ⏭️ | ⏭️ | ⏭️ | ✅ 완료 - approveIssue/rejectIssue API 연동 (I-7에서 완료) |
L-1 공정 관리: ✅ 2025-12-26 완료
- Backend API 신규 개발 (ProcessController, ProcessService, Process 모델)
ProcessListClient.tsx- API 연동 완료 (삭제 확인 모달, 일괄삭제, 상태토글)ProcessForm.tsx- API 연동 완료 (등록/수정)actions.ts- Server Actions 신규 생성
L-2 견적 관리: ✅ 2025-12-26 완료
quotes/types.ts- Quote, QuoteItem, QuoteStatus, ProductCategory 타입 정의, QuoteFormData 변환 함수quotes/actions.ts- 전체 CRUD + finalize/cancel/convert/PDF/email/kakao API (14개 Server Action)quotes/index.ts- 모듈 통합 exportpage.tsx- 목록 Server Component (SSR 초기 데이터)QuoteManagementClient.tsx- 목록 Client Component[id]/page.tsx- 상세 페이지 (getQuoteById, finalizeQuote, convertQuoteToOrder, sendQuoteEmail, sendQuoteKakao)[id]/edit/page.tsx- 수정 페이지 (getQuoteById, updateQuote)new/page.tsx- 등록 페이지 (createQuote)
L-3 종합 분석:
ComprehensiveAnalysis/index.tsx- ✅ 완료 - approveIssue/rejectIssue API 연동 (I-7에서 완료)
2.11 Phase M: 잔여 작업 (Phase A-F 보완)
2025-12-26 완료: 모든 잔여 Mock/TODO 제거 완료
| # | 페이지 | 문제 유형 | 상세 | 상태 |
|---|---|---|---|---|
| M-1 | 매입 상세 모달 | MOCK 상수 | MOCK_ACCOUNTS, MOCK_VENDORS → getBankAccounts, getVendors API |
✅ |
| M-2 | 직원 관리 | TODO | 파일 업로드 → uploadProfileImage API (Invite API 백엔드 미구현) | ✅ |
| M-3 | 근태 설정 | MOCK 상수 | MOCK_DEPARTMENTS → 이전 Phase에서 완료 |
✅ |
| M-4 | 결재 문서 생성 | MOCK 상수 | MOCK_EMPLOYEES → getEmployees API |
✅ |
| M-5 | 결재함/기안함 | console.log | 승인/반려 → API 연동, 수정/복제 → 백엔드 API 필요 | ✅ |
| M-6 | 구독 관리 | TODO | 자료 내보내기 → requestDataExport, 서비스 해지 → cancelSubscription | ✅ |
| M-7 | 계정 정보 | TODO | 탈퇴 → withdrawAccount, 사용중지 → suspendTenant | ✅ |
잔여 백엔드 API 개발 필요 항목:
- 직원 관리: Invite user API (POST /api/v1/employees/invite)
- 결재함: 수정(edit)/복제(copy) API
2.12 상세 페이지 Mock 현황
2025-12-26 완료: 모든 상세 페이지 API 연동 완료
| # | 컴포넌트 | 파일 위치 | 상태 | 완료 Phase |
|---|---|---|---|---|
| S-1 | SalesDetail | SalesManagement/SalesDetail.tsx |
✅ | B-1 매출 관리 |
| S-2 | PurchaseDetail | PurchaseManagement/PurchaseDetail.tsx |
✅ | B-2 매입 관리 |
| S-3 | DepositDetail | DepositManagement/DepositDetail.tsx |
✅ | B-3 입금 관리 |
| S-4 | WithdrawalDetail | WithdrawalManagement/WithdrawalDetail.tsx |
✅ | B-4 출금 관리 |
| S-5 | VendorDetail | VendorManagement/VendorDetail.tsx |
✅ | B-5 거래처 관리 |
| S-6 | BadDebtDetail | BadDebtCollection/BadDebtDetail.tsx |
✅ | A-1 악성채권 관리 |
| S-7 | StockStatusDetail | StockStatus/StockStatusDetail.tsx |
✅ | H-2 재고 현황 |
| S-8 | ShipmentDetail | ShipmentManagement/ShipmentDetail.tsx |
✅ | H-3 출하 관리 |
| S-9 | ReceivingDetail | ReceivingManagement/ReceivingDetail.tsx |
✅ | H-1 입고 관리 |
| S-10 | WorkOrderDetail | WorkOrders/WorkOrderDetail.tsx |
✅ | G-1 작업지시 관리 |
참고:
PurchaseDetailModal.tsx의 MOCK_ACCOUNTS, MOCK_VENDORS는 Phase M-1에서 완료 (2025-12-26)
3. 연동 작업 가이드
3.1 표준 연동 절차
Step 1: 현재 상태 분석
├── 목업 데이터 구조 확인 (types.ts)
├── 클라이언트 컴포넌트 props 확인 (*Client.tsx)
└── API 스펙 확인 (Swagger: sam.kr/api-docs)
Step 2: 타입 정의 정비
├── API 응답 타입 추가 (xxxApiData)
├── 변환 함수 타입 정의
└── 기존 프론트엔드 타입 유지
Step 3: 서버 컴포넌트 수정 (page.tsx)
├── API 호출 함수 구현
├── 데이터 변환 함수 구현
└── initialData prop 전달
Step 4: 서버 액션 구현 (actions.ts)
├── CRUD 함수 구현 (create, update, delete)
├── transformApiToFrontend() 함수
└── transformFrontendToApi() 함수
Step 5: 클라이언트 컴포넌트 연동
├── Server Actions import
├── 핸들러 함수에서 Server Actions 호출
└── 로딩/에러 상태 처리
3.2 체크리스트
□ API 엔드포인트 확인 (Swagger)
□ 응답 데이터 구조 확인
□ 타입 정의 (API 응답 타입 + 프론트엔드 타입)
□ 변환 함수 구현 (API ↔ Frontend)
□ 서버 컴포넌트에서 API 호출
□ 클라이언트 컴포넌트에 initialData 전달
□ Server Actions 구현 (CRUD)
□ 에러 처리 (try-catch, 사용자 알림)
□ 로딩 상태 처리
□ 브라우저 테스트
4. 상세 구현 가이드
4.1 page.tsx 패턴
// app/[locale]/(protected)/[feature]/page.tsx
import { cookies } from 'next/headers';
import { FeatureListClient } from '@/components/feature';
// API 응답 타입
interface ApiData {
id: number;
// ... API 필드
}
// API 헤더 생성
async function getApiHeaders(): Promise<HeadersInit> {
const cookieStore = await cookies();
const token = cookieStore.get('access_token')?.value;
return {
'Accept': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
'X-API-KEY': process.env.NEXT_PUBLIC_API_KEY || '',
};
}
// API 호출
async function getList(): Promise<ApiData[]> {
try {
const headers = await getApiHeaders();
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/feature`,
{ method: 'GET', headers, cache: 'no-store' }
);
if (!response.ok) return [];
const result = await response.json();
return result.success ? result.data.data : [];
} catch (error) {
console.error('[FeaturePage] Fetch error:', error);
return [];
}
}
// 데이터 변환
function transformToFrontend(apiData: ApiData[]): FeatureListItem[] {
return apiData.map(item => ({
id: String(item.id),
// ... 필드 매핑
}));
}
// 페이지 컴포넌트
export default async function FeaturePage() {
const apiData = await getList();
const data = transformToFrontend(apiData);
return <FeatureListClient initialData={data} />;
}
4.2 actions.ts 패턴
// components/feature/actions.ts
'use server';
import { cookies } from 'next/headers';
import type { FeatureData } from './types';
async function getApiHeaders(): Promise<HeadersInit> {
const cookieStore = await cookies();
const token = cookieStore.get('access_token')?.value;
return {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
'X-API-KEY': process.env.API_KEY || '',
};
}
// API → Frontend 변환
function transformApiToFrontend(apiData: ApiData): FeatureData {
return {
id: String(apiData.id),
// ... 필드 매핑
};
}
// Frontend → API 변환
function transformFrontendToApi(data: FeatureData): Record<string, unknown> {
return {
// ... 필드 매핑 (snake_case)
};
}
// 등록
export async function createFeature(
data: FeatureData
): Promise<{ success: boolean; data?: FeatureData; error?: string }> {
try {
const headers = await getApiHeaders();
const apiData = transformFrontendToApi(data);
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/feature`,
{
method: 'POST',
headers,
body: JSON.stringify(apiData),
}
);
const result = await response.json();
if (!response.ok || !result.success) {
return { success: false, error: result.message };
}
return { success: true, data: transformApiToFrontend(result.data) };
} catch (error) {
return { success: false, error: '서버 오류가 발생했습니다.' };
}
}
// 수정
export async function updateFeature(
id: string,
data: FeatureData
): Promise<{ success: boolean; data?: FeatureData; error?: string }> {
// ... 유사 패턴
}
// 삭제
export async function deleteFeature(
id: string
): Promise<{ success: boolean; error?: string }> {
// ... 유사 패턴
}
4.3 ListClient.tsx 연동 패턴
// components/feature/FeatureListClient.tsx
'use client';
import { useState } from 'react';
import { createFeature, updateFeature, deleteFeature } from './actions';
import { toast } from 'sonner';
interface FeatureListClientProps {
initialData: FeatureListItem[];
}
export function FeatureListClient({ initialData }: FeatureListClientProps) {
const [data, setData] = useState<FeatureListItem[]>(initialData);
const [isLoading, setIsLoading] = useState(false);
const handleCreate = async (formData: FeatureData) => {
setIsLoading(true);
const result = await createFeature(formData);
if (result.success && result.data) {
setData(prev => [...prev, result.data!]);
toast.success('등록되었습니다.');
} else {
toast.error(result.error || '등록에 실패했습니다.');
}
setIsLoading(false);
};
const handleUpdate = async (id: string, formData: FeatureData) => {
setIsLoading(true);
const result = await updateFeature(id, formData);
if (result.success && result.data) {
setData(prev => prev.map(item =>
item.id === id ? result.data! : item
));
toast.success('수정되었습니다.');
} else {
toast.error(result.error || '수정에 실패했습니다.');
}
setIsLoading(false);
};
const handleDelete = async (id: string) => {
setIsLoading(true);
const result = await deleteFeature(id);
if (result.success) {
setData(prev => prev.filter(item => item.id !== id));
toast.success('삭제되었습니다.');
} else {
toast.error(result.error || '삭제에 실패했습니다.');
}
setIsLoading(false);
};
// ... 나머지 UI 렌더링
}
5. 필드 매핑 규칙
5.1 네이밍 컨벤션
| API (snake_case) | Frontend (camelCase) |
|---|---|
created_at |
createdAt |
updated_at |
updatedAt |
item_type |
itemType |
purchase_price |
purchasePrice |
sales_price |
salesPrice |
is_active |
isActive |
5.2 타입 변환
| API 타입 | Frontend 타입 | 변환 |
|---|---|---|
number (id) |
string |
String(id) |
string (decimal) |
number |
parseFloat(value) |
string (date) |
string |
그대로 또는 포맷팅 |
null |
undefined |
value ?? undefined |
5.3 상태 매핑 예시
// API 상태 → Frontend 상태
function mapStatus(apiStatus: string): FrontendStatus {
switch (apiStatus) {
case 'draft': return 'draft';
case 'active': return 'active';
case 'finalized': return 'finalized';
default: return 'draft';
}
}
6. Phase B 상세 필드 매핑
이 섹션은 신규 세션에서 바로 개발 가능하도록 상세 스펙을 포함합니다.
6.1 매출 관리 (Sales)
API FormRequest 필드 (api/app/Http/Requests/V1/Sale/StoreSaleRequest.php):
'sale_date' => ['required', 'date'],
'client_id' => ['required', 'integer', 'exists:clients,id'],
'supply_amount' => ['required', 'numeric', 'min:0'],
'tax_amount' => ['required', 'numeric', 'min:0'],
'total_amount' => ['required', 'numeric', 'min:0'],
'description' => ['nullable', 'string', 'max:1000'],
'deposit_id' => ['nullable', 'integer', 'exists:deposits,id'],
React 인터페이스 (react/src/components/accounting/SalesManagement/types.ts):
interface SalesRecord {
id: string;
salesNo: string; // 매출번호
salesDate: string; // 매출일
vendorId: string; // 거래처 ID
vendorName: string; // 거래처명
salesType: SalesType; // 매출 유형
accountSubject: string; // 계정과목
items: SalesItem[]; // 품목 목록
totalSupplyAmount: number; // 공급가액 합계
totalVat: number; // 부가세 합계
totalAmount: number; // 총 금액
receivedAmount: number; // 입금액
outstandingAmount: number; // 미수금액
taxInvoiceIssued: boolean; // 세금계산서 발행 여부
transactionStatementIssued: boolean; // 거래명세서 발행 여부
note: string; // 비고
status: SalesStatus; // 상태
createdAt: string;
updatedAt: string;
}
필드 매핑 테이블:
| API 필드 (snake_case) | React 필드 (camelCase) | 타입 변환 | 비고 |
|---|---|---|---|
id |
id |
String(id) |
- |
sale_number |
salesNo |
그대로 | 시스템 자동 생성 |
sale_date |
salesDate |
그대로 | YYYY-MM-DD |
client_id |
vendorId |
String(client_id) |
FK |
client.name |
vendorName |
그대로 | 관계 조회 |
supply_amount |
totalSupplyAmount |
parseFloat() |
- |
tax_amount |
totalVat |
parseFloat() |
- |
total_amount |
totalAmount |
parseFloat() |
- |
description |
note |
?? '' |
- |
status |
status |
매핑 필요 | API: draft/confirmed/invoiced |
deposit_id |
receivedAmount |
관계 조회 | deposit.amount |
created_at |
createdAt |
그대로 | - |
updated_at |
updatedAt |
그대로 | - |
상태 매핑:
// API → React
const SALES_STATUS_MAP = {
'draft': 'outstanding', // 미수
'confirmed': 'monthlyClose', // 당월마감
'invoiced': 'agreed', // 합의
};
6.2 매입 관리 (Purchases)
API FormRequest 필드 (api/app/Http/Requests/V1/Purchase/StorePurchaseRequest.php):
'purchase_date' => ['required', 'date'],
'client_id' => ['required', 'integer', 'exists:clients,id'],
'supply_amount' => ['required', 'numeric', 'min:0'],
'tax_amount' => ['required', 'numeric', 'min:0'],
'total_amount' => ['required', 'numeric', 'min:0'],
'description' => ['nullable', 'string', 'max:1000'],
'withdrawal_id' => ['nullable', 'integer', 'exists:withdrawals,id'],
React 인터페이스 (react/src/components/accounting/PurchaseManagement/types.ts):
interface PurchaseRecord {
id: string;
purchaseNo: string; // 매입번호
purchaseDate: string; // 매입일자
vendorId: string; // 거래처 ID
vendorName: string; // 거래처명
supplyAmount: number; // 공급가액
vat: number; // 부가세
totalAmount: number; // 합계금액
purchaseType: PurchaseType; // 매입유형
evidenceType: EvidenceType; // 증빙유형
status: PurchaseStatus; // 상태
items: PurchaseItem[]; // 품목 정보
taxInvoiceReceived: boolean; // 세금계산서 수취 여부
createdAt: string;
updatedAt: string;
}
필드 매핑 테이블:
| API 필드 (snake_case) | React 필드 (camelCase) | 타입 변환 | 비고 |
|---|---|---|---|
id |
id |
String(id) |
- |
purchase_number |
purchaseNo |
그대로 | 시스템 자동 생성 |
purchase_date |
purchaseDate |
그대로 | YYYY-MM-DD |
client_id |
vendorId |
String(client_id) |
FK |
client.name |
vendorName |
그대로 | 관계 조회 |
supply_amount |
supplyAmount |
parseFloat() |
- |
tax_amount |
vat |
parseFloat() |
- |
total_amount |
totalAmount |
parseFloat() |
- |
description |
note |
?? '' |
품목 적요용 |
status |
status |
그대로 | pending/completed/cancelled |
withdrawal_id |
- | 관계 조회 | 출금 연결 |
created_at |
createdAt |
그대로 | - |
updated_at |
updatedAt |
그대로 | - |
매입유형 (purchaseType) 옵션:
raw_material: 원재료매입subsidiary_material: 부재료매입product: 상품매입outsourcing: 외주가공비consumables: 소모품비- 기타 15종 (types.ts 참조)
6.3 입금 관리 (Deposits)
API FormRequest 필드 (api/app/Http/Requests/V1/Deposit/StoreDepositRequest.php):
'deposit_date' => ['required', 'date'],
'client_id' => ['nullable', 'integer', 'exists:clients,id'],
'client_name' => ['nullable', 'string', 'max:100'],
'bank_account_id' => ['nullable', 'integer', 'exists:bank_accounts,id'],
'amount' => ['required', 'numeric', 'min:0'],
'payment_method' => ['required', 'string', 'in:cash,transfer,card,check'],
'account_code' => ['nullable', 'string', 'max:20'],
'description' => ['nullable', 'string', 'max:1000'],
'reference_type' => ['nullable', 'string', 'max:50'],
'reference_id' => ['nullable', 'integer'],
React 인터페이스 (react/src/components/accounting/DepositManagement/types.ts):
interface DepositRecord {
id: string;
depositDate: string; // 입금일
depositAmount: number; // 입금액
accountName: string; // 입금계좌명
depositorName: string; // 입금자명
note: string; // 적요
depositType: DepositType; // 입금유형
vendorId: string; // 거래처 ID
vendorName: string; // 거래처명
status: DepositStatus; // 상태
createdAt: string;
updatedAt: string;
}
필드 매핑 테이블:
| API 필드 (snake_case) | React 필드 (camelCase) | 타입 변환 | 비고 |
|---|---|---|---|
id |
id |
String(id) |
- |
deposit_date |
depositDate |
그대로 | YYYY-MM-DD |
amount |
depositAmount |
parseFloat() |
- |
bank_account.name |
accountName |
그대로 | 관계 조회 |
client_name |
depositorName |
그대로 | 입금자명 |
description |
note |
?? '' |
적요 |
account_code |
depositType |
매핑 필요 | 유형 코드 |
client_id |
vendorId |
String(client_id) |
FK |
client.name |
vendorName |
그대로 | 관계 조회 |
payment_method |
- | 참조 | cash/transfer/card/check |
created_at |
createdAt |
그대로 | - |
updated_at |
updatedAt |
그대로 | - |
입금유형 (depositType) 옵션:
salesRevenue: 매출대금advance: 선수금suspense: 가수금rentalIncome: 임대수익interestIncome: 이자수익- 기타 6종 (types.ts 참조)
입금상태 (status) 옵션:
inputWaiting: 입력대기requesting: 신청중rejected: 반려pending: 보류incomplete: 미완error: 오류confirmed: 확정완료
6.4 출금 관리 (Withdrawals)
API FormRequest 필드 (api/app/Http/Requests/V1/Withdrawal/StoreWithdrawalRequest.php):
'withdrawal_date' => ['required', 'date'],
'client_id' => ['nullable', 'integer', 'exists:clients,id'],
'client_name' => ['nullable', 'string', 'max:100'],
'bank_account_id' => ['nullable', 'integer', 'exists:bank_accounts,id'],
'amount' => ['required', 'numeric', 'min:0'],
'payment_method' => ['required', 'string', 'in:cash,transfer,card,check'],
'account_code' => ['nullable', 'string', 'max:20'],
'description' => ['nullable', 'string', 'max:1000'],
'reference_type' => ['nullable', 'string', 'max:50'],
'reference_id' => ['nullable', 'integer'],
React 인터페이스 (react/src/components/accounting/WithdrawalManagement/types.ts):
interface WithdrawalRecord {
id: string;
withdrawalDate: string; // 출금일
withdrawalAmount: number; // 출금액
accountName: string; // 출금계좌명
recipientName: string; // 수취인명
note: string; // 적요
withdrawalType: WithdrawalType; // 출금유형
vendorId: string; // 거래처 ID
vendorName: string; // 거래처명
createdAt: string;
updatedAt: string;
}
필드 매핑 테이블:
| API 필드 (snake_case) | React 필드 (camelCase) | 타입 변환 | 비고 |
|---|---|---|---|
id |
id |
String(id) |
- |
withdrawal_date |
withdrawalDate |
그대로 | YYYY-MM-DD |
amount |
withdrawalAmount |
parseFloat() |
- |
bank_account.name |
accountName |
그대로 | 관계 조회 |
client_name |
recipientName |
그대로 | 수취인명 |
description |
note |
?? '' |
적요 |
account_code |
withdrawalType |
매핑 필요 | 유형 코드 |
client_id |
vendorId |
String(client_id) |
FK |
client.name |
vendorName |
그대로 | 관계 조회 |
payment_method |
- | 참조 | cash/transfer/card/check |
created_at |
createdAt |
그대로 | - |
updated_at |
updatedAt |
그대로 | - |
출금유형 (withdrawalType) 옵션:
purchasePayment: 매입대금advance: 선급금suspense: 가지급금rent: 임대료salary: 급여- 기타 11종 (types.ts 참조)
6.5 거래처 관리 (Clients)
API FormRequest 필드 (api/app/Http/Requests/Client/ClientStoreRequest.php):
'client_group_id' => 'nullable|integer',
'client_code' => 'nullable|string|max:50',
'name' => 'required|string|max:100',
'client_type' => ['nullable', Rule::exists('common_codes', 'code')...],
'contact_person' => 'nullable|string|max:100',
'phone' => 'nullable|string|max:20',
'mobile' => 'nullable|string|max:20',
'fax' => 'nullable|string|max:20',
'email' => 'nullable|email|max:100',
'address' => 'nullable|string|max:255',
'manager_name' => 'nullable|string|max:50',
'manager_tel' => 'nullable|string|max:20',
'system_manager' => 'nullable|string|max:50',
'account_id' => 'nullable|string|max:50',
'account_password' => 'nullable|string|max:255',
'purchase_payment_day' => 'nullable|string|max:20',
'sales_payment_day' => 'nullable|string|max:20',
'business_no' => 'nullable|string|max:20',
'business_type' => 'nullable|string|max:50',
'business_item' => 'nullable|string|max:100',
'tax_agreement' => 'nullable|boolean',
'tax_amount' => 'nullable|numeric|min:0',
'tax_start_date' => 'nullable|date',
'tax_end_date' => 'nullable|date',
'bad_debt' => 'nullable|boolean',
'bad_debt_amount' => 'nullable|numeric|min:0',
'bad_debt_receive_date' => 'nullable|date',
'bad_debt_end_date' => 'nullable|date',
'bad_debt_progress' => ['nullable', Rule::exists('common_codes', 'code')...],
'memo' => 'nullable|string',
'is_active' => 'nullable|boolean',
필드 매핑 테이블 (주요 필드):
| API 필드 (snake_case) | React 필드 (camelCase) | 타입 변환 | 비고 |
|---|---|---|---|
id |
id |
String(id) |
- |
client_code |
clientCode |
그대로 | 자동 생성 |
name |
name |
그대로 | 거래처명 |
client_type |
clientType |
common_codes 참조 | - |
contact_person |
contactPerson |
그대로 | 담당자 |
phone |
phone |
그대로 | 전화번호 |
mobile |
mobile |
그대로 | 휴대폰 |
email |
email |
그대로 | 이메일 |
address |
address |
그대로 | 주소 |
business_no |
businessNo |
그대로 | 사업자번호 |
business_type |
businessType |
그대로 | 업종 |
business_item |
businessItem |
그대로 | 업태 |
bad_debt |
badDebt |
Boolean |
악성채권 여부 |
bad_debt_amount |
badDebtAmount |
parseFloat() |
악성채권 금액 |
is_active |
isActive |
Boolean |
활성 상태 |
created_at |
createdAt |
그대로 | - |
updated_at |
updatedAt |
그대로 | - |
6.6 공통 변환 함수 템플릿
// utils/apiTransform.ts
/** snake_case를 camelCase로 변환 */
export function snakeToCamel(str: string): string {
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}
/** camelCase를 snake_case로 변환 */
export function camelToSnake(str: string): string {
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
}
/** 객체 전체 키 변환 */
export function transformKeys<T>(obj: Record<string, any>, transformer: (key: string) => string): T {
const result: Record<string, any> = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = transformer(key);
result[newKey] = value !== null ? value : undefined;
}
return result as T;
}
/** API → Frontend 공통 변환 */
export function transformApiToFrontend<T>(apiData: Record<string, any>): T {
return transformKeys<T>(apiData, snakeToCamel);
}
/** Frontend → API 공통 변환 */
export function transformFrontendToApi(data: Record<string, any>): Record<string, any> {
return transformKeys(data, camelToSnake);
}
7. 작업 일정
Phase A: API 완료 기능 (1주)
| 일차 | 작업 내용 | 상태 |
|---|---|---|
| Day 1 | A-1 악성채권 관리 연동 | ✅ 완료 (2025-12-23) |
| Day 2 | A-2 팝업 관리 연동 | ✅ 완료 (2025-12-23) |
| Day 3 | A-3 결제 내역 연동 | ✅ 완료 (2025-12-23) |
| Day 4 | A-4 구독 관리 연동 | ✅ 완료 (2025-12-23) |
| Day 5 | A-5 알림 설정 연동 | ✅ 완료 (2025-12-23) |
Phase B: 핵심 업무 기능 (2주)
| 일차 | 작업 내용 |
|---|---|
| Day 1-2 | B-1 매출 관리 연동 |
| Day 3-4 | B-2 매입 관리 연동 |
| Day 5-6 | B-3 입금 관리, B-4 출금 관리 연동 |
| Day 7-8 | B-5 거래처 관리 연동 |
| Day 9-10 | B-6 어음 관리 연동 + 통합 테스트 |
8. 변경 이력
| 날짜 | 내용 | 작성자 |
|---|---|---|
| 2025-12-23 | 문서 초안 작성 | Claude |
| 2025-12-23 | Phase B 상세 필드 매핑 추가 (6.1~6.6) | Claude |
| 2025-12-23 | A-1 악성채권 관리 API 연동 완료 (actions.ts, page.tsx, index.tsx) |
Claude |
| 2025-12-23 | A-2 팝업 관리 API 연동 완료 (actions.ts, page.tsx, PopupList.tsx, [id]/page.tsx, [id]/edit/page.tsx) |
Claude |
| 2025-12-23 | A-3 결제 내역 API 연동 완료 (types.ts, actions.ts, page.tsx, PaymentHistoryClient.tsx, index.ts) |
Claude |
| 2025-12-23 | A-4 구독 관리 API 연동 완료 (types.ts, utils.ts, actions.ts, page.tsx, SubscriptionClient.tsx, index.ts) |
Claude |
| 2025-12-23 | A-5 알림 설정 API 연동 완료 (types.ts, actions.ts, page.tsx, NotificationSettingsClient.tsx, index.ts) |
Claude |
| 2025-12-23 | A-6 거래처 원장 - API 미존재 확인, Phase A 완료 | Claude |
| 2025-12-23 | B-1 매출 관리 - 기존 API 연동 확인 (/api/proxy/sales 사용) |
Claude |
| 2025-12-23 | B-2 매입 관리 - 기존 API 연동 확인 (/api/proxy/purchases 사용) |
Claude |
| 2025-12-23 | B-3 입금 관리 API 연동 완료 (types.ts: API 타입 추가, index.tsx: Mock → API 호출 전환) |
Claude |
| 2025-12-23 | B-4 출금 관리 API 연동 완료 (types.ts: API 타입 추가, index.tsx: Mock → API 호출 전환) |
Claude |
| 2025-12-23 | B-5 거래처 관리 API 연동 완료 (types.ts: API 타입 추가, actions.ts: Server Actions, page.tsx: 서버 컴포넌트, VendorManagementClient.tsx: 클라이언트 컴포넌트) |
Claude |
| 2025-12-24 | 커밋 유실로 인한 API 연동 복원 (A-2actions.ts 재생성, page.tsx 서버 컴포넌트 전환, index.tsx mock 제거) |
Claude |
| 2025-12-24 | Mock 데이터 사용 파일 전수 조사 (MCP Serena 활용), 신규 Phase 추가 (D~H, S) | Claude |
| 2025-12-24 | B-1 매출관리, B-2 매입관리 상태 수정 (Mock 사용중으로 재분류) | Claude |
| 2025-12-24 | Phase E (설정/시스템), F (인사/급여), G (결재), H (API 개발 필요), S (상세 페이지) 신규 추가 | Claude |
| 2025-12-24 | 문서 전면 수정: 리스트/상세 분리 상태 표기, 상세 페이지 Mock 현황 섹션 추가, Phase 재구성 (A~I), 게시판 제외 | Claude |
| 2025-12-24 | 전수 조사 및 문서 업데이트: MCP Serena로 80개+ 파일 Mock 패턴 분석, Phase A~H CRUD별 상태 테이블 추가, 전수 조사 결과 요약(1.4) 추가, console.log 패턴 및 actions.ts 미연동 현황 문서화 | Claude |
| 2025-12-24 | 작업 진행 정책 추가 (1.5): 페이지 단위 작업 → 검수 → [승인] 문서 업데이트 → [승인] 커밋 순서 정의, A-1 다른 세션 처리, A-2부터 순차 진행 | Claude |
| 2025-12-24 | A-1 악성채권 관리 완전 연동: 상세 페이지([id]/page.tsx, [id]/edit/page.tsx) 서버 컴포넌트 전환, BadDebtDetail.tsx CRUD API 연동, 메모 API 연동(addBadDebtMemo, deleteBadDebtMemo) |
Claude |
| 2025-12-24 | A-2 팝업 관리 API 연동: [id]/page.tsx getPopupById+deletePopup 연동, [id]/edit/page.tsx getPopupById 연동, PopupForm.tsx createPopup+updatePopup 연동, 로딩/에러 상태 처리 |
Claude |
| 2025-12-24 | C-1 직원 관리 API 연동: actions.ts 생성 (CRUD+통계+일괄삭제), utils.ts 생성 (API↔Frontend 변환), index.tsx Mock 제거+API 연동, [id]/page.tsx 상세 API 연동, [id]/edit/page.tsx 수정 API 연동, new/page.tsx 등록 API 연동 |
Claude |
| 2025-12-24 | C-2 근태 관리 API 연동: actions.ts 생성 (checkIn/checkOut/getTodayAttendance), GoogleMap.tsx userLocation 콜백 추가, page.tsx Mock console.log 제거+API 연동, 처리중 상태 및 버튼 텍스트 추가 |
Claude |
| 2025-12-24 | C-3 휴가 관리 API 연동: actions.ts 생성 (getLeaves/createLeave/approveLeave/rejectLeave 등), index.tsx 신청현황 탭 Mock 제거+API 연동, 일괄승인/반려 API 연동 |
Claude |
| 2025-12-24 | C-4 부서 관리 API 연동: actions.ts 생성 (getDepartmentTree/createDepartment/updateDepartment/deleteDepartment/deleteDepartmentsMany), index.tsx Mock 제거+API 연동 |
Claude |
| 2025-12-24 | .env.local 환경변수 수정: API_URL=https://api.sam.kr/api 추가 - Server Actions 서버사이드 API URL |
Claude |
| 2025-12-24 | C-3 휴가 관리 사용현황/부여현황 API 연동: leave_grants 테이블 마이그레이션, LeaveGrant 모델 생성, GET/POST/DELETE /api/v1/leaves/grants API 추가, actions.ts getLeaveGrants/createLeaveGrant/deleteLeaveGrant 추가, index.tsx generateGrantData Mock 제거+API 연동, 연차/월차 부여 시 LeaveBalance.total_days 자동 갱신 |
Claude |
| 2025-12-24 | D-2 계정 관리(계좌) API 연동: actions.ts 생성 (CRUD+toggle+setPrimary+일괄삭제), types.ts API 필드 추가 (id:number, bankName, isPrimary, assignedUserId), index.tsx generateMockData 제거+API 연동, AccountDetail.tsx console.log 제거+API 연동 |
Claude |
| 2025-12-24 | D-3 근무 일정 관리 API 연동: actions.ts 생성 (getWorkSetting/updateWorkSetting), index.tsx console.log 제거+API 연동, 로딩/저장 상태 추가, HH:mm↔HH:mm:ss 시간 변환 |
Claude |
| 2025-12-24 | D-4 근태 설정 관리 API 연동: actions.ts 생성 (getAttendanceSetting/updateAttendanceSetting), index.tsx console.log 제거+API 연동, 로딩/저장 상태 추가 (API 지원 필드: useGps, allowedRadius만 연동) |
Claude |
| 2025-12-24 | B-6 어음 관리 중복번호 검증 추가: StoreBillRequest.php tenant scope unique 검증 규칙 추가 (Rule::unique), lang/ko/error.php 에러 메시지 추가 (bill.duplicate_number), SAM 표준 패턴 적용 (app('tenant_id')) |
Claude |
| 2025-12-25 | E-1 법인카드 관리 API 연동: actions.ts 생성 (CRUD+토글+일괄삭제), CardForm.tsx mockUsers 제거+API 연동 (getActiveEmployees), index.tsx Mock 제거+API 연동 |
Claude |
| 2025-12-25 | E-2 급여 관리 API 신규 개발+연동: Salary API 전체 신규 생성 (마이그레이션, 모델, 서비스, 컨트롤러, FormRequest), actions.ts 생성 (목록/상세/상태변경/일괄상태변경), index.tsx generateSalaryData/generateSalaryDetail Mock 함수 제거+API 연동, 로딩 상태 추가 |
Claude |
| 2025-12-25 | F-1 기안함 API 연동: DraftBox/actions.ts 생성 (목록/삭제/일괄삭제), index.tsx Mock 제거+API 연동, IntegratedListTemplateV2 props 수정 |
Claude |
| 2025-12-25 | F-2 참조함 API 연동: ReferenceBox/actions.ts 생성 (목록/열람처리/일괄처리), index.tsx Mock 제거+API 연동, IntegratedListTemplateV2 props 수정 |
Claude |
| 2025-12-25 | F-3 결재함 API 연동: ApprovalBox/actions.ts 생성 (목록/통계/승인/반려/일괄처리), index.tsx Mock 제거+API 연동, 반려 다이얼로그 사유 입력 Textarea 추가 |
Claude |
| 2025-12-25 | F-4 비용견적서 양식 API 연동: DocumentCreate/actions.ts 생성 (비용견적서 항목조회/문서생성/상신/직원목록), index.tsx console.log 제거+API 연동, ExpenseEstimateForm.tsx Mock 제거+로딩/빈상태 추가 |
Claude |
| 2025-12-26 | Phase I 상세 분석: I-1~I-8 전체 CRUD 현황 분석 - actions.ts 함수별 상태, UI 구현 현황, 페이지 특성(조회전용/외부연동/대시보드) 분류, 필요 작업 정리. I-2/I-3/I-6/I-8 완료 확인, I-1/I-4/I-5/I-7 추가 작업 필요 | Claude |
| 2025-12-26 | H-1 입고 관리 React 연동: actions.ts 생성 (목록/상세/등록/수정/삭제/통계/옵션 API), types.ts 타입 정의, ReceivingList.tsx Mock 제거+API 연동, ReceivingDetail.tsx Mock 제거+API 연동, ReceivingCreate.tsx Mock 제거+API 연동, ReceivingEdit.tsx Mock 제거+API 연동 |
Claude |
| 2025-12-26 | H-2 재고 현황 React 연동: actions.ts 생성 (목록/상세/통계/옵션 API), types.ts 타입 정의, StockStatusList.tsx Mock 제거+API 연동, StockStatusDetail.tsx Mock 제거+API 연동 (등록/수정/삭제 해당없음) |
Claude |
| 2025-12-26 | H-3 출하 관리 React 연동: actions.ts 생성 (목록/상세/등록/수정/삭제/통계/옵션 API), types.ts 타입 정의, ShipmentList.tsx Mock 제거+API 연동, ShipmentDetail.tsx Mock 제거+API 연동, ShipmentCreate.tsx Mock 제거+API 연동, ShipmentEdit.tsx Mock 제거+API 연동 |
Claude |
| 2025-12-26 | Phase I 완료: I-1 미지급비용관리 CRUD UI 구현 (등록/수정 폼 다이얼로그, 삭제/일괄삭제), I-4 은행거래조회 상세페이지 이동방식 확인, I-5 채권현황 updateOverdueStatus API 연동+변경감지, I-7 종합분석 approveIssue/rejectIssue API 연동 | Claude |
| 2025-12-26 | Phase I Excel/PDF 다운로드 API 연동: I-5 채권현황 exportReceivablesExcel, I-2 거래처원장 exportVendorLedgerExcel/exportVendorLedgerDetailPdf, I-6 일일보고서 exportDailyReportExcel - console.log 제거+Blob 다운로드 패턴 적용 | Claude |
| 2025-12-26 | Phase G 생산관리 API 연동 완료: G-1 작업지시관리 (목록/상세/등록/담당자선택/수주선택), G-2 작업실적관리 (목록/통계), G-3 생산대시보드, G-4 작업자화면 (목록/완료/자재투입/공정단계/검사요청), G-5 품질검사 (목록/상세/등록/수정) - 전체 Mock → API 전환 완료, mockData.ts 내 유틸리티(색상매핑/판정함수)만 유지 | Claude |
| 2025-12-26 | Phase S (2.14) 상세 페이지 완료 확인: S-1~S-10 전체 상세 페이지 API 연동 완료 확인, 문서 상태 업데이트 | Claude |
| 2025-12-26 | L-3 종합분석 완료 확인: approveIssue/rejectIssue API 연동 확인 (I-7에서 완료), 문서 상태 업데이트 | Claude |
9. 참고 문서
- API 스펙: http://sam.kr/api-docs
- 기존 연동 계획:
react-api-integration-plan.md - API 개발 계획:
erp-api-development-plan-d1.0-changes.md - 표준 구현 참조:
/sales/pricing-management