--- source: Phase 0 분석 기반 아키텍처 옵션 상세 분석 section: 백엔드-프론트엔드 협업 논의 자료 (상세 버전) created: 2025-11-13 audience: 백엔드 개발자 + 프론트엔드 개발자 purpose: 아키텍처 결정을 위한 상세 분석 자료 related: ARCHITECTURE_OPTIONS_CORE.md tags: [architecture, detailed-analysis, collaboration, discussion] --- # 품목 관리 시스템 아키텍처 옵션 상세 분석 **목적:** 아키텍처 옵션별 상세 분석 및 실제 시나리오 기반 비교 **대상:** 백엔드 개발자 + 프론트엔드 개발자 협업 논의용 **범위:** 개념적 분석 (구현 상세 제외) > **Note:** 이 문서는 개념적 분석에 집중합니다. DB 스키마, API 스펙, 소스 코드 등 구현 상세는 옵션 결정 후 별도 설계합니다. --- ## 📊 현재 시스템 상세 분석 ### 1. 품목 유형별 필드 상세 #### 1.1 FG (제품) - 13개 필드 **주요 필드 그룹:** - 기본 정보: 상품명, 품목명, 규격 - 분류: 카테고리, 태그 - 사양: 폭, 높이, 깊이, 무게 - 관리: 안전재고, 리드타임 - 가격: 표준가, 최소가 **특징:** - 대부분 필수 필드 - 타입 안전성 높음 (숫자, 텍스트 명확) - 검증 규칙 단순 --- #### 1.2 PT-ASSEMBLY (조립 부품) - 12개 카테고리 **카테고리별 핵심 필드:** **guide_rail (가이드레일):** ``` 필수 필드: ├─ 설치유형 (wall/stand) ├─ 조립유형 (M/T/P/B/S - 5가지) ├─ 사이드규격 (width) └─ 조립길이 (length) 코드 생성 로직: 설치유형 + 조립유형 + 사이즈코드 예: R + M + 53 → RM53 ``` **case (케이스):** ``` 필수 필드: └─ 조립유형 (frame/body - 2가지) 코드 생성 로직: C + 조립유형 예: C + F → CF (프레임형 케이스) ``` **bottom_finish (하단마감재):** ``` 필수 필드: ├─ 재질 (steel/aluminum) └─ 형상 (square/round) 코드 생성 로직: 재질코드 + 형상코드 예: BS (Steel + Square) ``` **rod (봉):** ``` 필수 필드: ├─ 직경 (diameter) └─ 길이 (length) 코드 생성 로직: ROD + 직경 + 길이 예: ROD-25-3500 (25mm, 3500mm) ``` **공통 패턴:** - 각 카테고리마다 **고유한 필드 조합** - 필드 조합에 따라 **코드 자동 생성** - 일부 필드는 **선택값 제한** (드롭다운) - 일부 필드는 **자유 입력** (숫자, 텍스트) --- #### 1.3 PT-BENDING (절곡 부품) - 가변 필드 **필수 필드:** ``` ├─ 재질 (material) ├─ 두께 (thickness) ├─ 절곡도면 (bending_diagram) - 이미지/파일 └─ 절곡상세 (bending_details) - JSON 구조 ``` **특징:** - 절곡도면: 파일 업로드 필요 - 절곡상세: 복잡한 데이터 구조 (각도, 위치, 순서 등) - 코드 생성: 2가지 패턴 (카테고리 기반 / 재질 기반) --- #### 1.4 PT-PURCHASED (구매 부품) - 단순 **필수 필드:** ``` ├─ 카테고리 ├─ 구매처 └─ 규격 ``` **특징:** - 상대적으로 단순 - 외부 공급사 정보 연계 --- #### 1.5 RM/SM/CS (자재) - 동일 구조 **필수 필드:** ``` ├─ 재질 ├─ 규격 ├─ 단위 ├─ 구매단가 └─ 공급사 ``` **특징:** - 3개 유형 구조 동일 - 재고 관리 중심 - 가격 변동 이력 필요 --- ### 2. 현재 화면 동작 흐름 분석 #### 2.1 품목 생성 플로우 ``` Step 1: 품목 유형 선택 사용자: "품목 유형 선택" 드롭다운 클릭 ↓ 5개 옵션 표시: FG, PT, RM, SM, CS ↓ 사용자: "PT (부품)" 선택 ↓ 화면: PT 전용 필드 표시 시작 Step 2: 부품 유형 선택 (PT만) 화면: "부품 유형" 드롭다운 활성화 ↓ 3개 옵션: ASSEMBLY, BENDING, PURCHASED ↓ 사용자: "ASSEMBLY" 선택 ↓ 화면: ASSEMBLY 전용 필드 표시 Step 3: 카테고리 선택 (ASSEMBLY만) 화면: "카테고리" 드롭다운 활성화 ↓ 12개 옵션: guide_rail, case, rod, ... ↓ 사용자: "guide_rail" 선택 ↓ 화면: guide_rail 전용 필드 표시 - 설치유형 - 조립유형 - 사이드규격 - 조립길이 Step 4: 필드 입력 사용자: 각 필드 입력 ↓ 화면: 실시간 검증 ↓ 품목코드 자동 생성 (예: RM53) ↓ 화면: 미리보기 표시 Step 5: 저장 사용자: "저장" 버튼 클릭 ↓ 100줄 검증 로직 실행 ↓ 362줄 저장 로직 실행 ↓ API 호출 ``` **문제:** - 조건부 렌더링 깊이: 3-4단계 - 검증 시점: 저장 시 (즉시 피드백 제한) - 코드 중복: 각 단계마다 if-else 반복 --- #### 2.2 품목 조회 플로우 ``` List View 구조: 7개 탭 (Desktop): ├─ 전체 (All) - 모든 품목 ├─ FG - 제품만 ├─ PT - 부품 (3개 서브탭) │ ├─ ASSEMBLY │ ├─ BENDING │ └─ PURCHASED ├─ SM - 부자재 ├─ RM - 원자재 └─ CS - 소모품 각 탭마다: ├─ 필터링 로직 (품목 유형별) ├─ 테이블 헤더 (컬럼 구성) ├─ 테이블 바디 (데이터 표시) ├─ 페이지네이션 └─ 액션 버튼 (보기/수정/삭제) ``` **문제:** - 테이블 구조 10회 복사-붙여넣기 - 필터링 로직 7회 반복 - 페이지네이션 7회 반복 - DataTable 컴포넌트 존재하지만 미사용 --- ### 3. 코드 복잡도 분석 #### 3.1 조건부 렌더링 복잡도 **현재 구조:** ``` if (itemType === "FG") { // FG 전용 필드 (50줄) } else if (itemType === "PT") { if (partType === "ASSEMBLY") { if (category1 === "guide_rail") { // guide_rail 필드 (80줄) } else if (category1 === "case") { // case 필드 (60줄) } else if (category1 === "rod") { // rod 필드 (70줄) } // ... 12개 카테고리 반복 } else if (partType === "BENDING") { // BENDING 필드 (100줄) } else if (partType === "PURCHASED") { // PURCHASED 필드 (50줄) } } else if (itemType === "RM") { // RM 필드 (40줄) } // ... 5개 품목 유형 반복 총 복잡도: 5 × (1 + 3 × 12) ≈ 185개 조건 분기 ``` **Cyclomatic Complexity:** - generateItemCode(): 25+ - handleSaveItem(): 30+ - 전체 컴포넌트: 100+ (추정) **영향:** - 테스트 케이스: 185개 필요 - 유지보수: 새 카테고리 추가 시 5-10곳 수정 - 버그 위험: 높음 (조건 누락 가능성) --- ## 🎯 아키텍처 옵션 상세 비교 ### Option A: 고정 화면 리팩토링 상세 #### A.1 컴포넌트 분리 전략 **현재 → 개선:** ``` Before: ItemManagement.tsx (6,521줄) └─ 모든 로직 포함 After: Pages/ └─ ItemManagement.tsx (100줄) └─ 페이지 레이아웃만 Organisms/ ├─ ItemListView.tsx (200줄) │ └─ DataTable 재사용 ├─ ItemFormDialog.tsx (300줄) │ └─ 품목 유형별 폼 라우팅 └─ BOMEditor.tsx (300줄) - 기존 유지 Molecules/ ├─ FGFormFields.tsx (150줄) ├─ PTAssemblyFormFields.tsx (200줄) │ ├─ GuideRailFields.tsx (80줄) │ ├─ CaseFields.tsx (60줄) │ ├─ RodFields.tsx (70줄) │ └─ ... (12개 컴포넌트) ├─ PTBendingFormFields.tsx (100줄) ├─ PTPurchasedFormFields.tsx (50줄) ├─ RMFormFields.tsx (40줄) ├─ SMFormFields.tsx (40줄) └─ CSFormFields.tsx (40줄) Hooks/ ├─ useItemForm.ts (200줄) │ └─ useState 통합 관리 ├─ useItemValidation.ts (150줄) │ └─ 검증 로직 분리 └─ useItemCodeGenerator.ts (177줄 → 200줄) └─ 코드 생성 로직 분리 총계: 6,521줄 → 약 2,000줄 (68% 감소) ``` **감소 메커니즘:** - 테이블 중복 제거: 1,911줄 → 200줄 (DataTable 재사용) - 로직 분리: 상태/검증/생성 hooks 분리 - 컴포넌트 재사용: 공통 필드 컴포넌트화 --- #### A.2 상태 관리 개선 **현재 문제:** ``` 40개 useState: - 모든 필드를 개별 state로 관리 - 연관된 필드 간 동기화 어려움 - 리렌더링 과다 예: guide_rail 입력 시 → 8개 state 업데이트 → 컴포넌트 8회 리렌더링 ``` **개선 방향:** ``` useItemForm hook: - 단일 reducer로 통합 - 필드 간 종속성 관리 - 최적화된 리렌더링 예: guide_rail 입력 시 → 1회 dispatch → 필요한 부분만 리렌더링 ``` --- #### A.3 신규 카테고리 추가 시나리오 **예: "hinge (경첩)" 카테고리 추가** ``` Step 1: 필드 정의 백엔드 회의: hinge에 필요한 필드는? - 힌지타입 (left/right/center) - 힌지사이즈 (small/medium/large) - 재질 (steel/aluminum) Step 2: 백엔드 작업 - DB 스키마 변경 없음 (기존 컬럼 재사용) - API 수정 없음 Step 3: 프론트엔드 작업 (4-6시간) 1. HingeFields.tsx 컴포넌트 생성 (80줄) 2. useItemCodeGenerator.ts 수정 (10줄 추가) 3. useItemValidation.ts 수정 (15줄 추가) 4. 카테고리 드롭다운 옵션 추가 (1줄) Step 4: 테스트 - HingeFields 단위 테스트 - 통합 테스트 Step 5: 배포 - 프론트엔드 빌드 및 배포 - 백엔드 변경 없음 총 작업시간: 4-6시간 ``` **장점:** - 명확한 작업 범위 - 타입 안전성 유지 - 단계별 테스트 가능 **단점:** - 프론트엔드 배포 필요 - 소스 코드 수정 필수 --- ### Option B: 메타데이터 기반 동적 UI 상세 #### B.1 메타데이터 구조 개념 **필드 메타데이터 개념:** ``` 각 필드의 정보를 데이터로 저장: 예: guide_rail의 "설치유형" 필드 메타데이터 구성: ├─ 필드 식별: fieldName: "installationType" ├─ 표시 정보: label: "설치유형" ├─ 필드 타입: type: "select" ├─ 옵션 목록: options: ["wall", "stand"] ├─ 검증 규칙: required: true ├─ 표시 조건: showWhen: "category1 === 'guide_rail'" └─ 코드 생성: codePattern: "{installationType}" ``` **동작 원리:** ``` 프론트엔드 로딩 시: 1. API 호출: GET /api/items/metadata?category=guide_rail 2. 메타데이터 수신 (JSON) 3. 메타데이터 기반 폼 생성 4. 사용자 입력 처리 5. 메타데이터 기반 검증 6. 메타데이터 기반 코드 생성 7. API 호출: POST /api/items ``` --- #### B.2 동적 렌더링 메커니즘 **MetaFormBuilder 컴포넌트 개념:** ``` 입력: ├─ metadata (필드 정의 목록) └─ formData (현재 입력값) 처리: 1. metadata 순회 2. 각 필드의 type에 따라 적절한 컴포넌트 선택 - type: "text" → - type: "number" → - type: "select" →