# 품목관리 페이지 동적 렌더링 구현 계획

## 작업 일자: 2025-11-28

## 문서 버전
| 버전 | 날짜 | 작성자 | 내용 |
|------|------|--------|------|
| 1.0 | 2025-11-28 | Claude | 초안 작성 |

---

## 🎯 목표

**현재**: 하드코딩된 품목 유형별 폼 (ProductForm, PartForm, MaterialForm 등)
**목표**: API 기반 동적 폼 렌더링 (품목기준관리에서 설정한 구조대로 자동 생성)

### 기대 효과
- 코드 수정 없이 폼 구조 변경 가능
- 품목 유형별 필드 추가/삭제가 관리자 UI에서 가능
- 새로운 품목 유형 추가 시 개발 공수 대폭 감소
- 일관된 폼 렌더링 로직으로 유지보수 용이

---

## 📊 현재 구조 분석

### 현재 파일 구조
```
src/components/items/ItemForm/
├── index.tsx (415줄) ← 메인 컴포넌트
├── constants.ts
├── types.ts
├── ValidationAlert.tsx
├── FormHeader.tsx
├── BendingDiagramSection.tsx
├── BOMSection.tsx
├── context/
├── hooks/
│   └── useItemFormState.ts (364줄) ← 25+ useState 통합
└── forms/
    ├── ProductForm.tsx (FG)
    ├── MaterialForm.tsx (RM/SM/CS)
    ├── PartForm.tsx (PT)
    └── parts/
        ├── AssemblyPartForm.tsx
        ├── BendingPartForm.tsx
        └── PurchasedPartForm.tsx
```

### 현재 렌더링 방식 (하드코딩)
```typescript
// index.tsx:234-321
{selectedItemType === 'FG' && <ProductForm ... />}
{selectedItemType === 'PT' && <PartForm ... />}
{(selectedItemType === 'RM' || selectedItemType === 'SM' || selectedItemType === 'CS') &&
  <MaterialForm ... />}
```

### 문제점
1. **품목 유형별 하드코딩**: 새 유형 추가 시 코드 수정 필요
2. **필드 변경 시 개발 필요**: 관리자가 직접 변경 불가
3. **조건부 렌더링 복잡**: PT의 ASSEMBLY/BENDING/PURCHASED 분기가 복잡
4. **상태 관리 복잡**: 25+ useState가 하드코딩된 필드에 종속

---

## 🏗️ 동적 렌더링 아키텍처

### 목표 파일 구조
```
src/components/items/
├── DynamicItemForm/                    # 🆕 신규 생성
│   ├── index.tsx                       # 메인 동적 폼
│   ├── DynamicFormRenderer.tsx         # 섹션/필드 렌더러
│   ├── DynamicSection.tsx              # 동적 섹션 컴포넌트
│   ├── DynamicField.tsx                # 동적 필드 컴포넌트
│   ├── fields/                         # 필드 타입별 컴포넌트
│   │   ├── TextField.tsx
│   │   ├── DropdownField.tsx
│   │   ├── NumberField.tsx
│   │   ├── DateField.tsx
│   │   ├── FileField.tsx
│   │   ├── CheckboxField.tsx
│   │   └── CustomField.tsx             # 특수 컴포넌트 (BOM, 전개도 등)
│   ├── hooks/
│   │   ├── useFormStructure.ts         # API에서 폼 구조 로드
│   │   ├── useDynamicFormState.ts      # 동적 상태 관리
│   │   └── useConditionalFields.ts     # 조건부 필드 로직
│   └── types.ts                        # 타입 정의
├── ItemForm/                           # 기존 (백업/하이브리드용)
└── ItemFormLegacy/                     # 마이그레이션 완료 후 이동
```

### 데이터 흐름
```
┌─────────────────────────────────────────────────────────────────┐
│                        품목기준관리                               │
│  (Pages → Sections → Fields 구조 정의)                          │
└───────────────────────────┬─────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│  GET /api/v1/item-master/form-structure/{item_type}             │
│  - page 정보                                                    │
│  - sections[] (순서, 접기 가능 여부)                              │
│    - fields[] (타입, 필수 여부, 옵션)                             │
│    - bom_config (BOM 섹션인 경우)                                │
│  - conditional_sections (조건부 렌더링)                          │
└───────────────────────────┬─────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                    DynamicItemForm                              │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ useFormStructure(itemType)                               │  │
│  │ - formStructure: { page, sections, conditionalSections } │  │
│  └──────────────────────────────────────────────────────────┘  │
│                            │                                    │
│                            ▼                                    │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ DynamicFormRenderer                                      │  │
│  │ - sections.map(section => <DynamicSection />)            │  │
│  └──────────────────────────────────────────────────────────┘  │
│                            │                                    │
│                            ▼                                    │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ DynamicSection                                           │  │
│  │ - Card 렌더링 (collapsible, default_open)                │  │
│  │ - fields.map(field => <DynamicField />)                  │  │
│  │ - BOM 섹션인 경우 → <BOMSection />                       │  │
│  └──────────────────────────────────────────────────────────┘  │
│                            │                                    │
│                            ▼                                    │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ DynamicField                                             │  │
│  │ - field_type에 따라 적절한 컴포넌트 렌더링               │  │
│  │ - textbox → <TextField />                                │  │
│  │ - dropdown → <DropdownField />                           │  │
│  │ - file → <FileField />                                   │  │
│  │ - custom → <CustomField /> (전개도, BOM 등)              │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
```

---

## ✅ 구현 체크리스트

### Phase 1: 기반 작업 (API 프록시 + 타입) ✅ 완료 (2025-11-28)
- [x] Next.js API 프록시 라우트 → 기존 catch-all 프록시 활용 (`/api/proxy/[...path]/route.ts`)
- [x] 동적 폼 구조 타입 정의 → `DynamicItemForm/types.ts`
  - [x] `FormStructure`, `DynamicSection`, `DynamicField`, `ConditionalSection` 등

### Phase 2: 폼 구조 로딩 훅 ✅ 완료 (2025-11-28)
- [x] `useFormStructure.ts` 구현
  - [x] API 호출 로직 + Mock 데이터 폴백
  - [x] 로딩/에러 상태 관리
  - [x] 캐싱 전략 (5분 TTL)
- [x] `useConditionalFields.ts` 구현
  - [x] 조건부 섹션/필드 표시 로직
  - [x] 의존성 필드 값 변경 감지

### Phase 3: 동적 필드 컴포넌트 ✅ 완료 (2025-11-28)
- [x] 기본 필드 컴포넌트
  - [x] `TextField.tsx` (textbox, textarea)
  - [x] `DropdownField.tsx` (dropdown, searchable-dropdown)
  - [x] `NumberField.tsx` (number, currency)
  - [x] `DateField.tsx` (date)
  - [x] `CheckboxField.tsx` (checkbox, switch)
  - [x] `FileField.tsx` (file upload)
- [x] 특수 필드 컴포넌트
  - [x] `CustomField.tsx` (플레이스홀더 - 기존 컴포넌트 통합 예정)

### Phase 4: 동적 폼 렌더러 ✅ 완료 (2025-11-28)
- [x] `DynamicField.tsx` 구현 (field_type → 컴포넌트 매핑)
- [x] `DynamicSection.tsx` 구현 (Card, Collapsible, 그리드 레이아웃)
- [x] `DynamicFormRenderer.tsx` 구현 (섹션 렌더링, 조건부 처리)

### Phase 5: 메인 폼 컴포넌트 ✅ 완료 (2025-11-28)
- [x] `DynamicItemForm/index.tsx` 구현
  - [x] 커스텀 상태 관리 (react-hook-form 대신 useDynamicFormState)
  - [x] 동적 유효성 검증
  - [x] 폼 제출 로직
- [x] `useDynamicFormState.ts` 구현
  - [x] 동적 상태 관리
  - [x] 필드 값 변경 핸들러
  - [x] 유효성 검증 로직

### Phase 6: 기존 폼 통합/마이그레이션 ✅ 완료 (2025-11-28)
- [x] 기존 ItemForm과 DynamicItemForm 하이브리드 전환
  - [x] Feature flag로 전환 가능하게 (`ItemFormWrapper.tsx`)
  - [x] 품목 유형별 점진적 마이그레이션 (`ENABLED_ITEM_TYPES`)
  - [x] 개발 모드 토글 UI (localStorage 오버라이드)
- [x] 기존 특수 컴포넌트 재사용 (CustomField.tsx에 통합)
  - [x] DrawingCanvasSimple (파일 업로드 기반)
  - [x] BOMTable (품목 구성 관리)
  - [x] BendingDetailTable (전개도 상세 입력 + 자동 계산)
- [x] 페이지 라우트 업데이트 ✅ 완료 (2025-12-01)
  - [x] `/items/create/page.tsx` → DynamicItemForm 연동
  - [x] `/items/[id]/edit/page.tsx` → DynamicItemForm + 실제 API 연동

### Phase 7: 테스트 및 검증
- [ ] 품목 유형별 테스트
  - [ ] FG (제품) 등록/수정 테스트
  - [ ] PT (부품) 등록/수정 테스트
  - [ ] RM/SM/CS 등록/수정 테스트
- [ ] 조건부 필드 테스트
  - [ ] PT → ASSEMBLY/BENDING/PURCHASED 분기
  - [ ] BOM 섹션 조건부 표시
- [ ] 에러 처리 테스트
  - [ ] API 실패 시 폴백
  - [ ] 유효성 검증 에러 표시

---

## 📋 API 응답 구조 (참조용)

### GET /api/v1/item-master/form-structure/{item_type}
```json
{
  "success": true,
  "data": {
    "page": {
      "id": 1,
      "page_name": "제품 등록",
      "item_type": "FG"
    },
    "sections": [
      {
        "id": 101,
        "title": "기본 정보",
        "section_type": "BASIC",
        "order_no": 1,
        "is_collapsible": false,
        "is_default_open": true,
        "fields": [
          {
            "id": 1001,
            "field_name": "품목명",
            "field_key": "item_name",
            "field_type": "textbox",
            "order_no": 1,
            "is_required": true,
            "placeholder": "품목명을 입력하세요",
            "validation_rules": { "maxLength": 100 },
            "grid_row": 1,
            "grid_col": 1,
            "grid_span": 2
          }
        ]
      },
      {
        "id": 103,
        "title": "부품 구성 (BOM)",
        "section_type": "BOM",
        "order_no": 3,
        "bom_config": {
          "columns": [...],
          "allow_search": true,
          "search_endpoint": "/api/v1/items/search"
        }
      }
    ],
    "conditional_sections": [
      {
        "condition": {
          "field_key": "needs_bom",
          "operator": "equals",
          "value": true
        },
        "show_sections": [103]
      }
    ]
  }
}
```

---

## 🔧 필드 타입 → 컴포넌트 매핑

| field_type | 컴포넌트 | 설명 |
|------------|----------|------|
| `textbox` | TextField | 단일 텍스트 입력 |
| `textarea` | TextField (multiline) | 여러 줄 텍스트 |
| `dropdown` | DropdownField | 선택 목록 |
| `searchable-dropdown` | DropdownField (searchable) | 검색 가능 선택 |
| `number` | NumberField | 숫자 입력 |
| `currency` | NumberField (currency) | 통화 입력 |
| `date` | DateField | 날짜 선택 |
| `date-range` | DateField (range) | 기간 선택 |
| `checkbox` | CheckboxField | 체크박스 |
| `switch` | CheckboxField (switch) | 토글 스위치 |
| `file` | FileField | 파일 업로드 |
| `custom:drawing-canvas` | DrawingCanvas | 전개도 그리기 |
| `custom:bending-detail-table` | BendingDetailTable | 전개도 상세 입력 |
| `custom:bom-table` | BOMSection | BOM 관리 테이블 |

---

## ⚠️ 주의사항

### 1. 기존 기능 보존
- 품목코드 자동 생성 로직 유지
- 전개도 폭 합계 자동 계산 유지
- BOM 검색/추가 기능 유지

### 2. 점진적 마이그레이션
- Feature flag로 신/구 폼 전환 가능하게
- 문제 발생 시 즉시 롤백 가능
- 품목 유형별로 순차 적용 (FG → PT → RM/SM/CS)

### 3. 성능 고려
- 폼 구조 캐싱 (5분 TTL)
- 동적 스키마 생성 최적화
- 불필요한 리렌더링 방지

### 4. 백엔드 의존성
- API 미구현 시 Mock 데이터로 개발
- API 응답 형식 변경 시 transformer 레이어에서 처리

---

## 📅 예상 일정

| Phase | 작업 | 예상 작업량 |
|-------|------|------------|
| Phase 1 | API 프록시 + 타입 | 작음 |
| Phase 2 | 폼 구조 로딩 훅 | 중간 |
| Phase 3 | 동적 필드 컴포넌트 | 중간 |
| Phase 4 | 동적 폼 렌더러 | 중간 |
| Phase 5 | 메인 폼 컴포넌트 | 큼 |
| Phase 6 | 마이그레이션 | 큼 |
| Phase 7 | 테스트 | 중간 |

---

## 관련 문서

- `[API-REQUEST-2025-11-28] dynamic-page-rendering-api.md` - API 명세
- `[PLAN-2025-11-27] item-form-component-separation.md` - 기존 컴포넌트 분리
- `src/contexts/ItemMasterContext.tsx` - 품목기준관리 Context

---

## 변경 이력

| 날짜 | 버전 | 변경 내용 |
|------|------|----------|
| 2025-11-28 | 1.0 | 초안 작성 |
| 2025-12-01 | 1.1 | Phase 6 페이지 라우트 업데이트 완료 (API 연동) |