Files
sam-docs/dev/dev_plans/bending-management/step4-React연동.md
강영보 fbd0510cc1 docs: [bending] 절곡품 관리 개발 완료 상태 업데이트
- step1: 데이터 임포트 완료 (170+60건), artisan 커맨드 7개 실행 결과
- step2: API 12개 엔드포인트 완료, item_category 필수 필터 추가
- step3: MNG 샘플 완료 (4개 메뉴, 이미지 473건)
- step4: React 구현 가이드 전면 작성 (API 응답 구조, 컴포넌트 설계, 실무 노트)
- 코드 체계 변경 불가 사유, 265vs170 차이 설명, 운영 전 정리 항목 추가
2026-03-17 11:33:47 +09:00

16 KiB
Raw Blame History

Step 4: React 절곡품 관리 화면 + 견적 이미지 연동 미착수

프로젝트: React (sam/react) 선행 조건: Step 2 (API ), Step 3 (MNG 샘플 ) 상태: 미착수 참조: MNG 샘플 화면, 기존 GuideRailSection 컴포넌트


1. 개요

MNG에서 샘플로 구현/검증한 절곡품 관리 기능을 React 운영 화면으로 이관한다. 모든 API 엔드포인트는 Step 2에서 완료되어 있으므로, 프론트엔드 구현만 필요.


2. API 엔드포인트 (Step 2 완료 — 그대로 사용)

2-1. 기초관리 (절곡 부품)

GET    /api/v1/bending-items              ← 목록 (필터/검색/페이지네이션)
GET    /api/v1/bending-items/filters      ← 필터 옵션 (분류/재질/모델 distinct)
GET    /api/v1/bending-items/{id}         ← 상세 (options 전체)
POST   /api/v1/bending-items              ← 등록
PUT    /api/v1/bending-items/{id}         ← 수정
DELETE /api/v1/bending-items/{id}         ← 삭제 (soft delete)

응답 구조 (목록):

{
  "success": true,
  "data": {
    "data": [
      {
        "id": 15862, "code": "BD-BE-30",
        "name": "하단마감재(스크린) EGI 3000mm",
        "item_type": "PT", "item_category": "BENDING",
        "item_name": "하단마감재", "item_sep": "스크린",
        "item_bending": "하단마감재", "item_spec": "60*40",
        "material": "EGI 1.55T", "model_name": null,
        "model_UA": "인정", "search_keyword": null,
        "rail_width": null, "registration_date": "2025-07-21",
        "author": "개발자", "memo": null,
        "exit_direction": null, "front_bottom_width": null,
        "box_width": null, "box_height": null,
        "bendingData": [
          {"no":1,"input":15,"rate":"","sum":15,"color":false,"aAngle":false},
          {"no":2,"input":14,"rate":"-1","sum":28,"color":false,"aAngle":false}
        ],
        "prefix": "BE", "length_code": "30", "length_mm": 3000,
        "legacy_bending_num": 288,
        "width_sum": 193, "bend_count": 5,
        "created_at": "2026-02-21 19:47:01"
      }
    ],
    "current_page": 1, "total": 170, "last_page": 6, "per_page": 30
  }
}

2-2. 절곡품 모델 (가이드레일/케이스/하단마감재 통합)

GET    /api/v1/guiderail-models                      ← 모델 목록
GET    /api/v1/guiderail-models/filters              ← 필터 옵션
GET    /api/v1/guiderail-models/{id}                 ← 모델 상세 (부품 조합)
POST   /api/v1/guiderail-models                      ← 모델 등록
PUT    /api/v1/guiderail-models/{id}                 ← 모델 수정
DELETE /api/v1/guiderail-models/{id}                 ← 모델 삭제

카테고리 필터: ?item_category=GUIDERAIL_MODEL|SHUTTERBOX_MODEL|BOTTOMBAR_MODEL

응답 구조 (상세):

{
  "success": true,
  "data": {
    "id": 15914, "code": "GR-KDSS01-벽면형-SUS",
    "name": "KDSS01 벽면형 SUS마감",
    "item_category": "GUIDERAIL_MODEL",
    "model_name": "KDSS01", "check_type": "벽면형",
    "rail_width": 150, "rail_length": 150,
    "finishing_type": "SUS마감",
    "item_sep": "스크린", "model_UA": "인정",
    "components": [
      {
        "orderNumber": 1,
        "itemName": "1번(마감제)", "material": "SUS 1.2T",
        "quantity": 2, "width_sum": 227,
        "bendingData": [
          {"no":1,"input":15,"rate":"0","sum":15,"color":true,"aAngle":false},
          {"no":2,"input":13,"rate":"0","sum":28,"color":false,"aAngle":false}
        ],
        "legacy_bending_num": "170"
      }
    ],
    "material_summary": {"SUS 1.2T": 599, "EGI 1.55T": 894},
    "component_count": 4
  }
}

2-3. 이미지 (기존 API 재사용)

POST   /api/v1/items/{id}/files           ← 업로드 (field_key: 'bending_diagram')
GET    /api/v1/items/{id}/files           ← 목록 조회
GET    /api/v1/files/{id}/view            ← 인라인 표시
DELETE /api/v1/items/{id}/files/{fileId}  ← 삭제

3. React 화면 구성

3-1. 메뉴 구조 (사이드바)

생산 관리
├─ ... (기존)
└─ 절곡품 관리
   ├─ 기초관리         /bending/base
   ├─ 절곡품 (가이드레일) /bending/products
   ├─ 케이스           /bending/cases
   └─ 하단마감재       /bending/bottombars

3-2. 기초관리 화면

목록 (/bending/base):

컬럼 API 필드
NO id
코드 code
대분류 item_sep (스크린=파란배지, 철재=주황배지)
인정 model_UA
분류 item_bending
품명 item_name
규격 item_spec
재질 material
모델 model_name
폭합 width_sum
절곡수 bend_count
등록일 created_at

필터: item_sep, item_bending, material, search (HTMX 실시간 검색)

폼 (/bending/base/{id}/edit):

기본 정보 (4열 그리드):

  • 코드*, 이름*, 품명*, 대분류*(select)
  • 분류*(datalist), 재질*(datalist), 규격, 모델(datalist)
  • 인정여부(select), 등록일(date), 작성자, 검색어

케이스 전용 (분류=케이스 시 표시):

  • 점검구 방향(select), 전면밑(mm), 레일폭(mm), 케이스 너비(mm), 케이스 높이(mm)

절곡 입력 테이블:

  • 동적 열 추가/삭제
  • 행: 입력(number) → 연신율(text) → 연신율후(자동) → 합계(자동) → 음영(checkbox) → A각(checkbox)
  • 연신율 규칙: -1 → input-1mm, 1 → input+1mm, 빈값 → 그대로
  • 폭합계 + 절곡횟수 자동 표시
  • bendingData JSON으로 직렬화하여 API 전송

이미지: 파일 업로드 + Ctrl+V 클립보드 + 미리보기

3-3. 절곡품 화면 (3가지 타입)

목록 (공통 테이블):

컬럼 API 필드
NO id
모델명 model_name
대분류 item_sep
인정 model_UA
형상 check_type
레일폭×높이 rail_width × rail_length
마감 finishing_type
부품수 component_count
소요자재량 material_summary

필터: item_category(필수!), item_sep, model_UA, check_type, model_name, search

⚠️ item_category 없이 호출하면 3개 카테고리 60건이 섞여서 나옴

폼 — 타입별 헤더 차이:

필드 가이드레일 케이스 하단마감재
등록일/작성자/비고
외형치수 (가로×세로) 너비×폭 폭×높이+전면밑+레일폭 폭×높이
대분류 라디오
인정/비인정 라디오
형태 라디오 (벽면/측면)
점검구 방향 라디오
모델 select
마감 select
품목검색어

절곡 부품 조립 섹션:

  • 부품별 절곡 테이블 (inline 편집)
  • 부품 추가: 기초관리 검색 모달 (필터+체크박스+선택적용)
  • 부품 삭제: DOM 즉시 제거
  • 품명/재질/수량 inline 편집
  • 순서 변경 (위로/아래로)
  • components JSON으로 직렬화하여 API 전송

재질별 폭합: components에서 자동 계산 (material_summary)

작업지시서 PDF: 별도 인쇄 페이지 (/{type}/{id}/print)

  • 레거시 포맷: 번호 | 재질 | 절곡치수(합계+음영) | 폭합 | 수량
  • A각 표시 행
  • A4 가로 인쇄 최적화

4. React 컴포넌트 구조 (설계안)

src/pages/bending/
├─ base/
│  ├─ BendingBaseList.tsx          ← 기초관리 목록
│  └─ BendingBaseForm.tsx          ← 등록/수정/조회 (mode 분기)
├─ products/
│  ├─ BendingProductList.tsx       ← 절곡품 목록 (category prop으로 3타입 공용)
│  ├─ BendingProductForm.tsx       ← 등록/수정/조회 (타입별 헤더 분기)
│  └─ BendingProductPrint.tsx      ← 작업지시서 인쇄
├─ components/
│  ├─ BendingTable.tsx             ← 절곡 입력 테이블 (공용 컴포넌트)
│  ├─ BendingSearchModal.tsx       ← 기초관리 부품 검색 모달
│  ├─ PartListEditor.tsx           ← 부품 조립 편집기
│  ├─ MaterialSummary.tsx          ← 재질별 폭합 표시
│  └─ GuiderailPreview.tsx         ← 견적 페이지용 미리보기
└─ hooks/
   ├─ useBendingItems.ts           ← API 호출 훅
   └─ useGuiderailModels.ts        ← API 호출 훅

4-1. BendingTable 컴포넌트 (핵심)

interface BendingData {
  no: number;
  input: number;
  rate: string;    // '' | '-1' | '1'
  sum: number;     // 자동 계산
  color: boolean;  // 음영 마킹
  aAngle: boolean; // A각 표시
}

interface BendingTableProps {
  data: BendingData[];
  onChange: (data: BendingData[]) => void;
  readOnly?: boolean;
}

4-2. BendingSearchModal 컴포넌트

interface BendingSearchModalProps {
  open: boolean;
  onClose: () => void;
  onSelect: (items: BendingItem[]) => void;
  filters?: { item_sep?: string; item_bending?: string; };
}

4-3. GuiderailPreview 컴포넌트 (견적 페이지 연동)

┌─────────────────────────────────────────────────────┐
│ 가이드레일: KSS01 벽면형 | 인정 | SUS마감 | 70×120  │
├──────────────────────┬──────────────────────────────┤
│  전개도 이미지        │  부품 조합                    │
│  ┌────────────────┐  │  # │ 부품    │ 재질  │ 수량  │
│  │                │  │  1 │ 마감재  │ SUS  │ 2    │
│  │  (R2 이미지)   │  │  2 │ 본체   │ EGI  │ 1    │
│  │                │  │  3 │ C형   │ EGI  │ 1    │
│  └────────────────┘  │  4 │ D형   │ EGI  │ 1    │
│                      │  재질별 폭합               │
│                      │  SUS: 406 | EGI: 398      │
└──────────────────────┴──────────────────────────────┘

5. 데이터 현황 (Step 1~3 완료 시점)

항목 건수 상태
기초관리 (BENDING) 170건
├ 전개도 임포트 139/170건 (31건 chandj 원본 없음)
가이드레일 모델 (GUIDERAIL_MODEL) 20건
케이스 모델 (SHUTTERBOX_MODEL) 30건
하단마감재 모델 (BOTTOMBAR_MODEL) 10건
DB 메뉴 4개

6. 주의사항

  • 기존 GuideRailSection (작업지시서용) 무변경 — 별도 컴포넌트
  • 기존 BendingInfoBuilder / PrefixResolver 무변경
  • 이미지 없는 모델: 텍스트만 표시 (graceful degradation)
  • MNG는 샘플 확인용 — React가 운영용
  • MNG/React 모두 동일한 API 엔드포인트 호출
  • ⚠️ tenant_id 287 하드코딩 → React에서는 Sanctum Bearer 토큰으로 자동 해결
  • ⚠️ 인증 전환: React 작업 시 ApiKeyMiddleware.phpallowWithoutAuth에서 bending 관련 4줄 제거 → 다른 API와 동일한 2중 인증 (API Key + Bearer) 적용
  • ⚠️ 재고 데이터 (stocks 153건) 이미 존재 — React에서 재고 연동 시 기존 Stock API 사용
  • ⚠️ 운영 배포 전 정리 필요 (options 불필요 키 삭제):
    • source (5130_migration 등) — 마이그레이션 추적용, 운영 불필요
    • legacy_prod, legacy_spec, legacy_slength — PREFIX 생성 완료, 삭제 가능
    • legacy_bending_num, legacy_num, legacy_guiderail_num — 이미지 매핑 완료, 삭제 가능
    • lot_managed, consumption_method, production_source, input_tracking — 재고 시스템 별도 관리
    • author = '개발자' — 실제 담당자로 변경 필요
    • ⚠️ 레거시 키 삭제 후 bending:import-* 커맨드 재실행 불가 — 운영 확정 후 정리
  • ⚠️ 운영 안정화 후 마이그레이션 커맨드 삭제 가능 (1회성 도구):
    • BendingFillOptions.php, BendingImportLegacy.php, BendingImportImages.php
    • GuiderailImportLegacy.php, BendingProductImportLegacy.php
    • BendingModelImportImages.php, BendingModelImportAssemblyImages.php
    • ⚠️ R2 이미지 + files 레코드는 운영 데이터 — 삭제 불가

7. MNG 샘플에서 발견된 실무 구현 노트

React 구현 시 참고할 MNG 작업 중 발견된 이슈 및 해결 방법

7-1. API 호출 주의사항

이슈 원인 해결
PUT/POST JSON body 파싱 안 됨 Laravel API가 form-data만 파싱 React axios는 JSON 자동 처리되므로 문제 없음
bendingData 전송 MNG form은 hidden input JSON 문자열 React는 객체 배열 그대로 전송 가능
pagination 메타 누락 ResourceCollection 감싸면 메타 사라짐 paginator.transform() 방식으로 수정 완료
unique:items,code Store 시 코드 중복 체크 React form에서 에러 메시지 표시 필요

7-2. 절곡 테이블 구현 핵심 로직

연신율 보정 규칙:
  rate = ""   → 보정 없음 (input 그대로)
  rate = "-1" → input - 1mm (절곡 시 1mm 줄어듦)
  rate = "1"  → input + 1mm

합계 = 보정 후 값의 누적합
폭합계 = 마지막 합계값

절곡횟수 = rate가 빈 문자열이 아닌 열의 수

7-3. 부품 추가 모달 동작

1. [+ 부품 추가] 클릭 → 모달 열기
2. GET /api/v1/bending-items?item_sep=&item_bending=&material=&search=&size=100
3. 체크박스로 복수 선택
4. [선택 적용] → 선택된 아이템의 bendingData를 components에 push
5. components JSON 직렬화 → hidden input → form submit

7-4. 타입별 라우트 매핑

React 라우트 API 파라미터 MNG 참고
/bending/base/* /api/v1/bending-items BendingBaseController
/bending/products/* /api/v1/guiderail-models?item_category=GUIDERAIL_MODEL (20건) BendingProductController
/bending/cases/* /api/v1/guiderail-models?item_category=SHUTTERBOX_MODEL (30건) 동일 컨트롤러
/bending/bottombars/* /api/v1/guiderail-models?item_category=BOTTOMBAR_MODEL (10건) 동일 컨트롤러

⚠️ item_category 파라미터 누락 시 60건 전부 반환됨 — React에서 반드시 포함할 것

7-5. 작업지시서 PDF

MNG에서는 window.print() 기반 별도 인쇄 페이지(/print)로 구현. React에서는 동일 방식 또는 html2pdf.js / react-to-print 라이브러리 사용 가능.

인쇄 포맷 (레거시 동일):

  • 헤더: 모델명, 형태, 규격, 마감
  • 테이블: 번호 | 재질 | 절곡치수(합계+음영) | A각 | 폭합 | 수량
  • 재질별 폭합 요약
  • A4 가로

7-6. 이미지 업로드 흐름

React:
1. <input type="file"> 또는 Ctrl+V 클립보드
2. POST /api/v1/items/{itemId}/files  (FormData: file + field_key=bending_diagram)
3. 응답: { file_id, file_url }
4. 표시: GET /api/v1/files/{fileId}/view (inline 이미지)

7-7. 메뉴 구조 (사이드바)

절곡품 관리
├─ 기초관리      /bending/base         (170건)
├─ 가이드레일    /bending/products     (20건, GUIDERAIL_MODEL)
├─ 케이스        /bending/cases        (30건, SHUTTERBOX_MODEL)
└─ 하단마감재    /bending/bottombars   (10건, BOTTOMBAR_MODEL)

React 사이드바 메뉴는 DB menus 테이블 기반 동적 렌더링 — 이미 등록 완료.

7-8. 재고 연동 (향후)

절곡 부품 재고는 SAM 기존 재고 시스템에 통합:

  • stocks 테이블: item_type = 'bent_part' (153건)
  • stock_lots 테이블: LOT 기반 FIFO 재고
  • 기존 Stock API 사용 가능 — 별도 재고 API 불필요