# React Mock → API 마이그레이션 - 잔여 작업 > **작성일**: 2025-12-27 > **목적**: 미완료 Mock → API 연동 작업 추적 > **원본 문서**: `react-mock-to-api-migration-plan.md` > **참조 구현**: 단가관리 (`/sales/pricing-management`) --- ## 0. 로컬 개발 환경 ### 도메인 구성 | 서비스 | 도메인 | 설명 | |--------|--------|------| | React (프론트엔드) | `http://dev.sam.kr` | 사용자 화면 | | API (백엔드) | `http://api.sam.kr` | REST API 서버 | | MNG (운영관리자) | `http://mng.sam.kr` | 관리자 패널 | ### 테스트 URL 예시 ``` # 종합분석 페이지 http://dev.sam.kr/reports/comprehensive-analysis # API 직접 호출 http://api.sam.kr/api/v1/comprehensive-analysis ``` ### 테스트 대상 테넌트 | 항목 | 값 | 비고 | |------|-----|------| | **Tenant ID** | 287 | 프론트_테스트회사 | | **테스트 User ID** | 33 | 홍킬동 (hhhhhh@example.com) | | **보조 User ID** | 12 | Ops Admin (결재함/참조함 테스트용 기안자) | > ⚠️ **주의**: Seeder 및 테스트 데이터 생성 시 반드시 `tenant_id = 287`, `user_id = 33` 사용 ### 로그인 정보 | 사용자 | Email | 비밀번호 | Tenant | |--------|-------|---------|--------| | 홍킬동 | hhhhhh@example.com | (확인 필요) | 287 (기본) | ### 종합분석 페이지 작업 시 주의사항 > ⚠️ **필수**: 종합분석은 여러 모듈의 데이터를 통합 표시하므로, 데이터 수정 시 관련 페이지 점검 필수 | 종합분석 섹션 | 원본 데이터 | 관련 페이지 (점검 대상) | |--------------|------------|----------------------| | 오늘의 이슈 (결재 대기) | `approvals`, `approval_steps` | `/approval/draft` (기안함), `/approval/pending` (결재함), `/approval/reference` (참조함) | | 월간 예상 지출 | `expected_expenses` | `/accounting/expected-expenses` | | 입금 현황 | `deposits` | `/accounting/deposits` | | 채권추심 | `bad_debts` | `/accounting/bad-debts` | | 미수금/여신한도 | `clients` | `/sales/clients` | **작업 흐름:** ``` 종합분석 데이터 수정 → 종합분석 페이지 확인 → 관련 원본 페이지 점검 ``` --- ## 1. 작업 규칙 ### 1.0 아키텍처 원칙 (필수) > **React는 오직 `api.sam.kr` (api 프로젝트)만 호출한다** ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ react/ │ ───► │ api/ │ │ mng/ │ │ dev.sam.kr │ │ api.sam.kr │ │ mng.sam.kr │ │ (프론트엔드) │ │ (REST API) │ │ (관리자패널) │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ✅ 호출 허용 │ │ └────────────────────┘ │ │ ❌ 절대 호출 금지 ─────────────────────────┘ ``` **규칙:** - React에서 mng API 직접 호출 **절대 금지** - 필요한 API가 api 프로젝트에 없으면 **api에 새로 개발** - mng의 모델/로직은 **참조만** (코드 복사 또는 재구현) ### 1.1 작업 진행 정책 > **단위 작업 → 검수 → 승인 → 문서 업데이트 → 커밋** 순서로 진행 ### 1.2 세션 규칙 및 Serena 메모리 관리 > **세션 간 일관성 보장을 위한 필수 규칙** #### 세션 시작 프로토콜 (필수) ``` 1. Serena 메모리 로드 read_memory("mock-to-api-state") → 현재 Phase/작업 확인 read_memory("mock-to-api-snapshot") → 마지막 작업 내용 확인 2. 현재 상태 확인 - 이 문서 읽기 - 현재 Phase의 기능별 상태 확인 - "다음 작업은 [Phase]-[번호]의 [기능] 입니다" 명시 3. 작업 범위 명확화 - 사용자에게 작업 범위 확인 - "[Phase] 전체를 진행할까요, 특정 기능만 진행할까요?" ``` #### Serena 메모리 구조 ```javascript // mock-to-api-state { "current_phase": "J", "current_item": "J-1", "current_feature": "게시판 목록", "progress": { "J-1": { "목록": "대기", "상세": "대기" } }, "last_update": "2025-12-27" } // mock-to-api-snapshot "Phase J 게시판 시스템 시작 예정" ``` #### 작업 완료 시 (필수) ``` 1. 문서 업데이트 - 해당 기능 상태 변경 (🔄 → ✅) - 변경 이력 추가 2. Serena 메모리 저장 write_memory("mock-to-api-state", 현재 상태) write_memory("mock-to-api-snapshot", 작업 내용 요약) 3. 커밋 feat: [Phase]-[번호] [페이지명] Mock → API 연동 ``` ### 1.3 작업 템플릿 (표준) ```markdown ## [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️⃣ 다음 페이지로 이동 │ └─────────────────────────────────────────────────────────────────┘ ``` **⚠️ 중요 규칙:** - 각 단계에서 `[승인]` 표시된 작업은 **사용자 승인 후** 진행 --- ## 2. 잔여 작업 목록 ### 2.1 Phase J: 게시판 시스템 > **상태**: ✅ api 프로젝트에 게시판/게시글 API 완비 → React 연동 작업 가능 #### ✅ api 프로젝트 게시판 API 아키텍처 > **핵심 설계**: 시스템 게시판과 테넌트 게시판을 **별도 엔드포인트**로 분리하고, **code 기반 URL** 사용 ``` 시스템 게시판 (본사 운영) 테넌트 게시판 (테넌트 내부) ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ /api/v1/system-boards/{code}│ │ /api/v1/boards/{code} │ │ - is_system = true │ │ - is_system = false │ │ - tenant_id = null │ │ - tenant_id = {current} │ │ - 메뉴 → global_menus │ │ - 메뉴 → menus │ └─────────────────────────────┘ └─────────────────────────────┘ ``` **장점:** - 동일한 `board_code`도 시스템/테넌트에서 독립 사용 가능 - API 호출 시 `is_system` 플래그 불필요 - URL만으로 게시판 유형 구분 가능 - RESTful 원칙 준수 #### 📌 시스템 게시판 API (System Boards) | 기능 | Method | Endpoint (api.sam.kr) | 상태 | |------|--------|----------------------|------| | 시스템 게시판 목록 | GET | `/api/v1/system-boards` | ✅ | | 시스템 게시판 상세 | GET | `/api/v1/system-boards/{code}` | ✅ | | 시스템 게시판 필드 | GET | `/api/v1/system-boards/{code}/fields` | ✅ | | 시스템 게시글 목록 | GET | `/api/v1/system-boards/{code}/posts` | ✅ | | 시스템 게시글 상세 | GET | `/api/v1/system-boards/{code}/posts/{id}` | ✅ | | 시스템 게시글 등록 | POST | `/api/v1/system-boards/{code}/posts` | ✅ | | 시스템 게시글 수정 | PUT | `/api/v1/system-boards/{code}/posts/{id}` | ✅ | | 시스템 게시글 삭제 | DELETE | `/api/v1/system-boards/{code}/posts/{id}` | ✅ | | 시스템 댓글 CRUD | * | `/api/v1/system-boards/{code}/posts/{id}/comments/*` | ✅ | #### 📌 테넌트 게시판 API (Tenant Boards) | 기능 | Method | Endpoint (api.sam.kr) | 상태 | |------|--------|----------------------|------| | 테넌트 게시판 목록 | GET | `/api/v1/boards` | ✅ | | 테넌트 게시판 상세 | GET | `/api/v1/boards/{code}` | 🔄 변경 필요 (ID→code) | | 테넌트 게시판 필드 | GET | `/api/v1/boards/{code}/fields` | ✅ | | 테넌트 게시글 목록 | GET | `/api/v1/boards/{code}/posts` | ✅ | | 테넌트 게시글 상세 | GET | `/api/v1/boards/{code}/posts/{id}` | ✅ | | 테넌트 게시글 등록 | POST | `/api/v1/boards/{code}/posts` | ✅ | | 테넌트 게시글 수정 | PUT | `/api/v1/boards/{code}/posts/{id}` | ✅ | | 테넌트 게시글 삭제 | DELETE | `/api/v1/boards/{code}/posts/{id}` | ✅ | | 테넌트 댓글 CRUD | * | `/api/v1/boards/{code}/posts/{id}/comments/*` | ✅ | #### 📌 관리자 게시판 API (Admin - mng.sam.kr) | 기능 | Method | Endpoint (mng.sam.kr) | 상태 | |------|--------|----------------------|------| | 전체 게시판 목록 | GET | `/boards` (Blade) | ✅ | | 게시판 등록 | POST | `/boards` | ✅ | | 게시판 수정 | PUT | `/boards/{id}` | ✅ | | 게시판 삭제 | DELETE | `/boards/{id}` | ✅ | | **🆕 게시판 생성 시 메뉴 자동 추가** | - | 연동 로직 | 🔄 구현 중 | #### 🏗️ 게시판 시스템 아키텍처 (참조용) **EAV (Entity-Attribute-Value) 패턴 기반 통합 게시판:** ``` boards (게시판 정의) ├── board_settings (EAV 필드 스키마) ├── posts (게시글) │ └── post_custom_field_values (EAV 값 저장) └── 첨부파일 (Polymorphic: files → fileable) ``` **게시판 모델 주요 필드:** ```typescript interface Board { id: number; tenant_id?: number; // null = 시스템 게시판 is_system: boolean; // 시스템/테넌트 구분 board_type: string; // notice, qna, faq, free, gallery, download board_code: string; // 고유 코드 name: string; description?: string; editor_type: 'wysiwyg' | 'markdown' | 'text'; allow_files: boolean; max_file_count: number; max_file_size: number; // KB extra_settings: { // JSON allow_comment?: boolean; allow_secret?: boolean; write_roles?: string[]; read_roles?: string[]; }; is_active: boolean; } interface BoardSetting { // EAV 필드 스키마 id: number; board_id: number; name: string; // 필드명 (예: 카테고리) field_key: string; // 필드 키 (예: category) field_type: 'text' | 'number' | 'select' | 'date' | 'textarea' | 'checkbox' | 'radio' | 'file'; field_meta?: { // JSON (select 옵션, 기본값 등) options?: string[]; default?: string; }; is_required: boolean; sort_order: number; } ``` **템플릿 시스템 (`config/board_templates.php`):** - **시스템 템플릿**: notice, qna, faq, popup (본사 ↔ 테넌트 소통용) - **테넌트 템플릿**: free, gallery, download, notice, qna (테넌트 내부용) #### 📋 React 연동 작업 현황 | # | 페이지 | React 경로 | 조회 | 등록 | 수정 | 삭제 | API 연동 전략 | |---|--------|-----------|------|------|------|------|--------------| | J-1 | 게시판 목록 | `/board` | 🔄 Mock | ⏭️ | ⏭️ | ⏭️ | `GET /boards` + 게시글 API 필요 | | J-2 | 게시글 상세 | `/board/[id]` | 🔄 Mock | ⏭️ | 🔄 | 🔄 | 게시글 API 필요 (posts CRUD) | | J-3 | 게시글 작성/수정 | `/board/[id]/edit` | 🔄 Mock | 🔄 | 🔄 | ⏭️ | 게시글 API + 커스텀필드 동적 렌더링 | | J-4 | 게시판 관리 | `/board/board-management` | ✅ | ✅ | ✅ | ✅ | ✅ 완료 (2025-12-27) | **파일 구조 → 연동 계획:** ``` components/board/ ├── types.ts ← 🔄 Board, Post, BoardSetting 타입으로 교체 ├── actions.ts ← 🆕 Server Actions (게시판/게시글 CRUD) ├── BoardForm/ ← 🔄 동적 폼 렌더링 (EAV 필드 기반) ├── BoardDetail/ ← 🔄 게시글 상세 + 커스텀필드 표시 ├── BoardList/ ← 🔄 게시판별 필터링 + 페이지네이션 └── BoardManagement/ ├── types.ts ← 🔄 Board 관리 타입으로 교체 ├── actions.ts ← 🆕 `/admin/boards/*` API 연동 └── BoardForm.tsx ← 🔄 템플릿 선택 + 필드 관리 UI ``` --- ### 2.2 Phase K: 고객센터 > **상태**: mng 게시판 시스템의 **템플릿 기반 게시판**으로 통합 운영 #### 🎯 통합 전략: 고객센터 = 게시판 템플릿 활용 각 고객센터 메뉴를 별도 `board_code`로 생성하여 통합 관리: | 메뉴 | board_code | board_type | 템플릿 | 커스텀 필드 | |------|------------|------------|--------|------------| | FAQ | `system-faq` | faq | system/faq | category (select) | | 공지사항 | `system-notice` | notice | system/notice | category (select) | | 이벤트 | `system-event` | notice | - | start_date, end_date, image_url | | 1:1 문의 | `system-qna` | qna | system/qna | inquiry_type, answer_status | **장점:** - 코드 중복 제거 (게시판 CRUD 재사용) - 커스텀 필드로 각 메뉴 특성 반영 - 관리자 UI 통합 (mng.sam.kr/boards에서 일괄 관리) #### 📋 React 연동 작업 현황 | # | 페이지 | React 경로 | 조회 | 등록 | 수정 | 삭제 | API 연동 전략 | |---|--------|-----------|------|------|------|------|--------------| | K-1 | FAQ 관리 | `/customer-center/faq` | 🔄 Mock | 🔄 | 🔄 | 🔄 | `board_code: system-faq` 게시글 API | | K-2 | 이벤트 관리 | `/customer-center/events` | 🔄 Mock | 🔄 | 🔄 | 🔄 | `board_code: system-event` 게시글 API | | K-3 | 공지사항 관리 | `/customer-center/notices` | 🔄 Mock | 🔄 | 🔄 | 🔄 | `board_code: system-notice` 게시글 API | | K-4 | 문의 관리 | `/customer-center/inquiries` | 🔄 Mock | 🔄 | 🔄 | 🔄 | `board_code: system-qna` 게시글 API + 답변 | **파일 구조 → 연동 계획:** ``` components/customer-center/ ├── shared/ │ ├── types.ts ← 🆕 공통 Post, BoardField 타입 │ ├── actions.ts ← 🆕 게시글 CRUD Server Actions (board_code 파라미터) │ └── PostForm.tsx ← 🆕 동적 폼 (커스텀필드 기반) ├── FAQManagement/ │ ├── types.ts ← 🔄 FAQ 특화 타입 (category 필드) │ ├── actions.ts ← 🆕 board_code='system-faq' 고정 │ └── FAQList.tsx ← 🔄 카테고리별 그룹핑 UI ├── EventManagement/ │ ├── types.ts ← 🔄 Event 특화 타입 (start_date, end_date) │ ├── actions.ts ← 🆕 board_code='system-event' 고정 │ └── EventList.tsx ← 🔄 진행중/예정/종료 필터 ├── NoticeManagement/ │ ├── types.ts ← 🔄 Notice 특화 타입 │ ├── actions.ts ← 🆕 board_code='system-notice' 고정 │ └── NoticeList.tsx ← 🔄 공지 목록 UI └── InquiryManagement/ ├── types.ts ← 🔄 Inquiry 특화 타입 (answer_status) ├── actions.ts ← 🆕 board_code='system-qna' 고정 ├── InquiryList.tsx ← 🔄 답변대기/완료 필터 ├── InquiryDetail.tsx ← 🔄 문의 상세 + 답변 작성 └── InquiryForm.tsx ← 🔄 문의 등록 폼 ``` #### 🛠️ 구현 순서 (권장) **Step 1: mng에서 시스템 게시판 생성** ``` mng.sam.kr/boards → 템플릿으로 생성: - system-faq (FAQ 템플릿) - system-notice (공지사항 템플릿) - system-event (커스텀: 이벤트) - system-qna (1:1문의 템플릿) ``` **Step 2: React 공통 모듈 개발** (✅ 게시판/게시글 API 이미 완비) ``` react/src/lib/board/ ├── types.ts ← API 타입 정의 ├── actions.ts ← 게시글 CRUD Server Actions └── utils.ts ← 커스텀필드 렌더링 유틸 ``` **Step 3: 각 메뉴별 연동** ``` K-3 공지사항 (가장 단순) → K-1 FAQ → K-2 이벤트 → K-4 문의 (가장 복잡) ``` #### 💡 커스텀 필드 동적 렌더링 전략 ```typescript // 게시판 필드 스키마 기반 동적 폼 생성 function renderCustomField(field: BoardSetting, value: string | null) { switch (field.field_type) { case 'text': return ; case 'select': return