Files
sam-react-prod/claudedocs/item-master/[PLAN-2025-12-08] dynamic-form-separation-plan.md
byeongcheolryu ded0bc2439 fix: TypeScript 타입 오류 수정 및 설정 페이지 추가
- BOMItem Omit 타입 시그니처 통일 (useTemplateManagement, SectionsTab, ItemMasterContext)
- HeadersInit → Record<string, string> 타입 변경
- Zustand useShallow 마이그레이션 (zustand/react/shallow)
- DataTable, ListPageTemplate 제네릭 타입 제약 추가
- 설정 관리 페이지 추가 (직급, 직책, 휴가정책, 근무일정, 권한)
- HR 관리 페이지 추가 (급여, 휴가)
- 단가관리 페이지 리팩토링

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 18:07:47 +09:00

11 KiB

DynamicItemForm 품목별 분리 계획

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


🎉 2025-12-09 업데이트

백엔드 작업 완료!

항목 상태
field_key 저장 방식 변경 (98_unitunit) 완료
시스템 예약어 검증 (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 위반
테스트 어려움 🟡 품질 이슈

품목 유형별 특수 로직

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 리팩토링

// 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/ - 현재 동적 폼