# DynamicItemForm 품목별 분리 계획

> 작성일: 2025-12-08
> 수정일: 2025-12-09
> 상태: 🚀 Phase 1 진행 중

---

## 🎉 2025-12-09 업데이트

### 백엔드 작업 완료!

| 항목 | 상태 |
|------|------|
| field_key 저장 방식 변경 (`98_unit` → `unit`) | ✅ 완료 |
| 시스템 예약어 검증 (SystemFields.php) | ✅ 완료 |
| 중복 검증 로직 | ✅ 완료 |
| 에러 메시지 | ✅ 완료 |

### Phase 1 완료! ✅

제거된 레거시 코드:
- ✅ `fieldAliases` (영문 → 한글 매핑) - 25줄
- ✅ `extractFieldName()` 함수 - 7줄
- ✅ `fieldKeyMap` 생성 로직 - 25줄
- ✅ 대소문자 무시 매핑 - 15줄
- ✅ 별칭 fallback 매핑 - 10줄
- ✅ `98_` prefix 파싱 로직 - 8줄
- ✅ `fieldKeyToBackendKey` 변환 테이블 - 30줄
- ✅ 복잡한 변환 로직 - 40줄

**실제 결과**: **~200줄 코드 삭제!** 🎉

### 변경 요약

| 변경 내용 | Before | After |
|-----------|--------|-------|
| Edit 모드 매핑 | 155줄 복잡한 로직 | 15줄 직접 로드 |
| 저장 시 변환 | 75줄 변환 테이블 | 15줄 is_active만 처리 |
| 총 코드량 | ~230줄 | ~30줄 |

---

## 📊 현재 상태 분석

### 현재 구조

```
src/components/items/
├── DynamicItemForm/              # 현재: 모든 품목 처리 (1350+ lines)
│   ├── index.tsx                 # 메인 컴포넌트 (거대)
│   ├── fields/                   # 필드 렌더러
│   ├── hooks/                    # 상태 관리 훅
│   ├── sections/                 # BOM 섹션
│   ├── types.ts
│   └── utils/
│
├── ItemForm/                     # 기존: 하드코딩된 폼 (참고용)
│   ├── forms/
│   │   ├── ProductForm.tsx       # FG(제품) 전용
│   │   ├── MaterialForm.tsx      # RM(원자재) 전용
│   │   └── PartForm.tsx          # PT(부품) → 하위 분기
│   │       └── parts/
│   │           ├── AssemblyPartForm.tsx   # 조립부품
│   │           ├── BendingPartForm.tsx    # 절곡부품
│   │           └── PurchasedPartForm.tsx  # 구매부품
```

### 문제점

| 문제 | 영향도 | field_key 통일로 해결? |
|------|--------|----------------------|
| DynamicItemForm 1350+ lines | 🔴 유지보수 어려움 | ❌ |
| 품목별 특수 로직 혼재 | 🔴 버그 발생 원인 | ❌ |
| 조건부 렌더링 복잡도 | 🟡 코드 가독성 | ⚠️ 부분 해결 |
| 파일 업로드 로직 중복 | 🟡 DRY 위반 | ❌ |
| 테스트 어려움 | 🟡 품질 이슈 | ❌ |

### 품목 유형별 특수 로직

```yaml
FG (제품):
  - 시방서/인정서 파일 업로드
  - 인정번호, 유효기간
  - BOM 구성 (선택)

PT (부품):
  - 부품 유형 선택 (ASSEMBLY/BENDING/PURCHASED)
  - 조립부품: 측면규격, 길이, 설치유형, BOM
  - 절곡부품: 전개도(바라시), 재질, 폭합계
  - 구매부품: 전기개폐기, 모터, 체인 규격

SM (반제품):
  - 규격 정보
  - BOM 구성 (선택)

RM (원자재):
  - 재질, 두께, 폭, 단위
  - 단가 정보

CS (소모품):
  - 기본 정보만
```

---

## 🎯 목표 구조 (2단계 분리)

### Phase 1: field_key 통일 (백엔드 작업 대기)
- 품목기준관리 API와 품목 CRUD API 간 field_key 일치
- 데이터 일관성 확보 → 버그 60% 감소 예상

### Phase 2: 컴포넌트 분리 (field_key 통일 후)

```
src/components/items/
├── DynamicItemForm/
│   ├── index.tsx                    # 컨테이너 (라우팅만)
│   ├── DynamicFormCore.tsx          # 공통 폼 프레임워크
│   │
│   ├── itemTypes/                   # 🆕 품목 유형별 컴포넌트
│   │   ├── index.ts                 # 내보내기
│   │   ├── FGFormFields.tsx         # 제품 전용 (인정정보, 파일업로드)
│   │   ├── PTFormFields.tsx         # 부품 라우터
│   │   │   ├── AssemblyFields.tsx   # 조립부품 전용
│   │   │   ├── BendingFields.tsx    # 절곡부품 전용 (전개도)
│   │   │   └── PurchasedFields.tsx  # 구매부품 전용
│   │   ├── SMFormFields.tsx         # 반제품 전용
│   │   ├── RMFormFields.tsx         # 원자재 전용
│   │   └── CSFormFields.tsx         # 소모품 전용
│   │
│   ├── shared/                      # 🆕 공유 컴포넌트
│   │   ├── FileUploadSection.tsx    # 파일 업로드 (FG, PT-절곡)
│   │   ├── BOMSection.tsx           # BOM 관리 (FG, PT-조립, SM)
│   │   ├── StatusField.tsx          # 활성/비활성
│   │   └── AutoItemCode.tsx         # 품목코드 자동생성
│   │
│   ├── fields/                      # 기존 유지
│   ├── hooks/                       # 기존 유지 + 개선
│   ├── sections/                    # → shared/로 이동
│   └── types.ts
```

---

## 📋 세부 작업 계획

### Phase 2-1: 공통 컴포넌트 추출

| 작업 | 파일 | 예상 LOC |
|------|------|----------|
| 파일 업로드 섹션 추출 | `shared/FileUploadSection.tsx` | ~150 |
| BOM 섹션 정리 | `shared/BOMSection.tsx` | ~100 |
| 품목코드 자동생성 | `shared/AutoItemCode.tsx` | ~50 |
| 상태 필드 | `shared/StatusField.tsx` | ~30 |

### Phase 2-2: 품목 유형별 컴포넌트 생성

| 작업 | 파일 | 특수 로직 |
|------|------|-----------|
| FG 전용 | `itemTypes/FGFormFields.tsx` | 인정정보, 시방서/인정서 |
| PT 라우터 | `itemTypes/PTFormFields.tsx` | 부품유형 선택 후 분기 |
| PT-조립 | `itemTypes/AssemblyFields.tsx` | 측면규격, 설치유형, BOM |
| PT-절곡 | `itemTypes/BendingFields.tsx` | 전개도, 폭합계 |
| PT-구매 | `itemTypes/PurchasedFields.tsx` | 전기개폐기, 모터 규격 |
| SM 전용 | `itemTypes/SMFormFields.tsx` | 규격, BOM (선택) |
| RM 전용 | `itemTypes/RMFormFields.tsx` | 재질, 두께, 단가 |
| CS 전용 | `itemTypes/CSFormFields.tsx` | 기본 정보만 |

### Phase 2-3: DynamicFormCore 리팩토링

```typescript
// DynamicFormCore.tsx - 공통 프레임워크
interface DynamicFormCoreProps {
  structure: FormStructure;
  formData: DynamicFormData;
  onChange: (key: string, value: any) => void;
  renderCustomFields?: () => ReactNode;  // 품목별 특수 필드
  renderCustomSections?: () => ReactNode; // 품목별 특수 섹션
}

// index.tsx - 라우팅만
const ItemTypeComponents = {
  FG: FGFormFields,
  PT: PTFormFields,
  SM: SMFormFields,
  RM: RMFormFields,
  CS: CSFormFields,
};

<DynamicFormCore
  structure={structure}
  formData={formData}
  onChange={setFieldValue}
  renderCustomFields={() => {
    const Component = ItemTypeComponents[selectedItemType];
    return Component ? <Component {...props} /> : null;
  }}
/>
```

---

## 📊 예상 효과

### Before (현재)
- `DynamicItemForm/index.tsx`: **1350+ lines**
- 모든 품목 로직 혼재
- 수정 시 다른 품목 영향 우려

### After (분리 후)
- `DynamicItemForm/index.tsx`: **~200 lines** (라우팅만)
- `DynamicFormCore.tsx`: **~400 lines** (공통 프레임워크)
- 품목별 컴포넌트: **각 100-200 lines**
- **총 코드량 비슷하지만 책임 분리됨**

### 장점
1. **버그 격리**: 조립부품 수정 → 절곡부품 영향 없음
2. **유지보수 용이**: 품목별 로직 파악 쉬움
3. **테스트 가능**: 품목별 단위 테스트 작성 가능
4. **확장성**: 새 품목 유형 추가 시 파일만 추가
5. **협업**: 여러 개발자가 다른 품목 동시 작업 가능

---

## ⏰ 작업 순서 및 의존성

```
┌─────────────────────────────────────────┐
│  Phase 1: field_key 통일 (백엔드)       │  ← 현재 대기 중
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  Phase 2-1: 공통 컴포넌트 추출          │
│  - FileUploadSection                    │
│  - BOMSection                           │
│  - AutoItemCode                         │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  Phase 2-2: 품목별 컴포넌트 생성        │
│  - FG, PT(Assembly/Bending/Purchased)   │
│  - SM, RM, CS                           │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  Phase 2-3: DynamicFormCore 리팩토링    │
│  - index.tsx 슬림화                     │
│  - 품목별 라우팅                        │
└─────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────┐
│  Phase 3: 테스트 및 검증                │
│  - 품목별 CRUD 테스트                   │
│  - 회귀 테스트                          │
└─────────────────────────────────────────┘
```

---

## ❓ 결정 필요 사항

### Q1. 기존 ItemForm 컴포넌트 처리

| 옵션 | 장점 | 단점 |
|------|------|------|
| A. 삭제 | 중복 제거, 혼란 방지 | 참고 코드 소실 |
| B. 유지 (참고용) | 마이그레이션 시 참고 가능 | 중복 유지보수 |
| C. archive 폴더로 이동 | 참고 가능 + 혼란 방지 | 폴더 추가 |

**권장**: C. archive 폴더로 이동

### Q2. 분리 전략

| 옵션 | 설명 |
|------|------|
| A. 점진적 분리 | 한 품목씩 분리, 기존 코드 유지 |
| B. 전면 분리 | 한 번에 모든 품목 분리 |

**권장**: A. 점진적 분리 (PT-조립부품부터 시작)

### Q3. 품목별 hooks 분리 여부

| 옵션 | 설명 |
|------|------|
| A. 공통 hooks 유지 | useDynamicFormState 그대로 사용 |
| B. 품목별 hooks 추가 | useAssemblyFormState 등 추가 |

**권장**: A. 공통 hooks 유지 (복잡도 관리)

---

## 📝 다음 단계

1. ⏳ **백엔드 field_key 통일 답변 대기**
2. 📋 **결정 필요 사항 확인** (Q1, Q2, Q3)
3. 🚀 **Phase 2-1 시작** (공통 컴포넌트 추출)

---

## 참고 문서

- `claudedocs/item-master/[API-2025-12-06] item-crud-backend-requests.md` - field_key 통일 요청
- `src/components/items/ItemForm/` - 기존 하드코딩 폼 참고
- `src/components/items/DynamicItemForm/` - 현재 동적 폼