Files
sam-react-prod/claudedocs/item-master/[PLAN-2025-11-28] dynamic-item-form-implementation.md
byeongcheolryu 3be5714805 refactor: 품목관리 시스템 리팩토링 및 Sales 페이지 추가
DynamicItemForm 개선:
- 품목코드 자동생성 기능 추가
- 조건부 표시 로직 개선
- 불필요한 컴포넌트 정리 (DynamicField, DynamicSection 등)
- 타입 시스템 단순화

새로운 기능:
- Sales 페이지 마이그레이션 (견적관리, 거래처관리)
- 공통 컴포넌트 추가 (atoms, molecules, organisms, templates)

문서화:
- 구현 문서 및 참조 문서 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 12:48:41 +09:00

15 KiB

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

작업 일자: 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

현재 렌더링 방식 (하드코딩)

// 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)

  • Next.js API 프록시 라우트 → 기존 catch-all 프록시 활용 (/api/proxy/[...path]/route.ts)
  • 동적 폼 구조 타입 정의 → DynamicItemForm/types.ts
    • FormStructure, DynamicSection, DynamicField, ConditionalSection

Phase 2: 폼 구조 로딩 훅 완료 (2025-11-28)

  • useFormStructure.ts 구현
    • API 호출 로직 + Mock 데이터 폴백
    • 로딩/에러 상태 관리
    • 캐싱 전략 (5분 TTL)
  • useConditionalFields.ts 구현
    • 조건부 섹션/필드 표시 로직
    • 의존성 필드 값 변경 감지

Phase 3: 동적 필드 컴포넌트 완료 (2025-11-28)

  • 기본 필드 컴포넌트
    • TextField.tsx (textbox, textarea)
    • DropdownField.tsx (dropdown, searchable-dropdown)
    • NumberField.tsx (number, currency)
    • DateField.tsx (date)
    • CheckboxField.tsx (checkbox, switch)
    • FileField.tsx (file upload)
  • 특수 필드 컴포넌트
    • CustomField.tsx (플레이스홀더 - 기존 컴포넌트 통합 예정)

Phase 4: 동적 폼 렌더러 완료 (2025-11-28)

  • DynamicField.tsx 구현 (field_type → 컴포넌트 매핑)
  • DynamicSection.tsx 구현 (Card, Collapsible, 그리드 레이아웃)
  • DynamicFormRenderer.tsx 구현 (섹션 렌더링, 조건부 처리)

Phase 5: 메인 폼 컴포넌트 완료 (2025-11-28)

  • DynamicItemForm/index.tsx 구현
    • 커스텀 상태 관리 (react-hook-form 대신 useDynamicFormState)
    • 동적 유효성 검증
    • 폼 제출 로직
  • useDynamicFormState.ts 구현
    • 동적 상태 관리
    • 필드 값 변경 핸들러
    • 유효성 검증 로직

Phase 6: 기존 폼 통합/마이그레이션 완료 (2025-11-28)

  • 기존 ItemForm과 DynamicItemForm 하이브리드 전환
    • Feature flag로 전환 가능하게 (ItemFormWrapper.tsx)
    • 품목 유형별 점진적 마이그레이션 (ENABLED_ITEM_TYPES)
    • 개발 모드 토글 UI (localStorage 오버라이드)
  • 기존 특수 컴포넌트 재사용 (CustomField.tsx에 통합)
    • DrawingCanvasSimple (파일 업로드 기반)
    • BOMTable (품목 구성 관리)
    • BendingDetailTable (전개도 상세 입력 + 자동 계산)
  • 페이지 라우트 업데이트 완료 (2025-12-01)
    • /items/create/page.tsx → DynamicItemForm 연동
    • /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}

{
  "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 연동)