# 절곡품 관리 기능 개발 계획서 > **시작일**: 2026-03-16 > **위치**: MNG 생산관리 > 절곡품 관리 (신규 메뉴) > **목표**: 경동기업(5130) 수준의 절곡품 마스터 관리 + 전개도 데이터 + 이미지 관리 > **원칙**: 기존 BendingInfoBuilder/PrefixResolver 보존, **전용 테이블 분리 방식** > **최종수정**: 2026-03-19 (테이블 분리 완료, 데이터 이관 완료) --- ## 배경 SAM은 절곡품의 "계산과 조합"(BendingInfoBuilder/PrefixResolver)은 잘 되어 있지만, "관리와 시각화"가 빠져 있다. 경동기업(5130) `guiderail/list.php` 수준의 관리 화면을 MNG에 구현한다. **갭 분석**: `docs/dev/dev_plans/bending-parts-analysis.md` 참조 --- ## ⚠️ 아키텍처 변경: items → 전용 테이블 분리 (2026-03-19) ### 변경 결정 배경 기존에는 `items` 테이블(`item_category='BENDING'`)에 `options` JSON으로 절곡 속성을 저장했으나, 다음 문제로 **전용 테이블 분리**로 방향 전환: | 문제 | 설명 | |------|------| | **검색 불가** | 레거시 5130에서 "하장바" 검색 시 5건+ 나오지만 MNG2 기초관리에서 0건 | | **options 누락** | BD-LEGACY-* 210건 중 상당수가 `options.item_name` 미채워짐 → 검색 불가 | | **JSON 비정규화** | 20+개 절곡 속성이 options JSON 안에 있어 인덱싱/검색/정렬 불가 | | **코드 체계 불일치** | BD-LEGACY-*, BD-{품명}-* 혼재, LOT 코드 체계 적용 불가 | | **스키마 불명확** | options 키가 코드에만 정의(OPTION_KEYS), DB 레벨 제약 없음 | ### 하장바 검색 문제 — ✅ 해결됨 ``` [레거시 5130] chandj.bending WHERE item_name LIKE '%하장바%' → 13건 (삭제 3건 제외 = 유효 10건) [이전 MNG2 — items 방식] items WHERE item_category='BENDING' AND name LIKE '%하장바%' → 2건만 (options.item_name 누락 → 검색 불가) [현재 MNG2 — bending_items 전용 테이블] bending_items WHERE item_name LIKE '%하장바%' → 10건 ✅ (정규 컬럼 item_name에 인덱스, chandj 유효건과 일치) [해결 방법] 테이블 분리(bending_items) + bending:clean-reimport로 chandj.bending 직접 이관 → item_name이 정규 컬럼으로 승격되어 검색 정상 동작 ``` ### 새 테이블 구조: `bending_items` ```sql CREATE TABLE bending_items ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, tenant_id BIGINT UNSIGNED NOT NULL, -- 코드 체계 (LOT 코드 = 제품Code + 종류Code + YYMMDD) code VARCHAR(50) NOT NULL, -- LOT: {제품}{종류}{YYMMDD} (예: CP260319 = 케이스 점검구) legacy_code VARCHAR(50) NULL, -- 이전 BD-LEGACY-* / BD-{품명}-* 코드 legacy_bending_id INT UNSIGNED NULL, -- chandj.bending.id 참조 -- 기본 정보 (기존 options에서 정규 컬럼으로 승격) item_name VARCHAR(100) NOT NULL, -- 품명 (검색 가능!) item_sep VARCHAR(20) NULL, -- 대분류: 스크린/철재 item_bending VARCHAR(50) NULL, -- 중분류: 가이드레일/케이스/하단마감재/... material VARCHAR(50) NULL, -- 재질: SUS 1.2T / EGI 1.55T item_spec VARCHAR(100) NULL, -- 규격: 120*70 model_name VARCHAR(50) NULL, -- 소속 모델: KSS01 model_UA VARCHAR(20) NULL, -- 인정여부: 인정/비인정 -- 절곡 전용 속성 rail_width DECIMAL(10,2) NULL, -- 레일폭 exit_direction VARCHAR(20) NULL, -- 출구방향 (케이스 전용) box_width DECIMAL(10,2) NULL, -- 박스폭 (케이스 전용) box_height DECIMAL(10,2) NULL, -- 박스높이 (케이스 전용) front_bottom DECIMAL(10,2) NULL, -- 전면밑 (케이스 전용) inspection_door VARCHAR(20) NULL, -- 점검구 (케이스 전용) -- 메타 (비정형 속성만 — 검색/필터 대상 아닌 것) options JSON NULL, -- memo, author, search_keyword, modified_by 등 is_active BOOLEAN NOT NULL DEFAULT TRUE, created_by BIGINT UNSIGNED NULL, updated_by BIGINT UNSIGNED NULL, deleted_by BIGINT UNSIGNED NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, deleted_at TIMESTAMP NULL, -- 인덱스 INDEX idx_tenant (tenant_id), INDEX idx_item_name (item_name), INDEX idx_item_sep (item_sep), INDEX idx_item_bending (item_bending), INDEX idx_material (material), INDEX idx_model_name (model_name), INDEX idx_code (code), INDEX idx_legacy_code (legacy_code), UNIQUE KEY uk_tenant_code (tenant_id, code, deleted_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ### 전개도 데이터: `bending_items.bending_data` (JSON 컬럼) > **변경 이력**: 초기 설계는 별도 `bending_data` 테이블이었으나, JSON 통합으로 최종 결정. > 마이그레이션 `100007_move_bending_data_back_to_json`으로 `bending_data` 테이블 DROP 완료. ```json // bending_items.bending_data JSON 구조 [ { "no": 1, "input": 10, "rate": "", "sum": 10, "color": true, "aAngle": false }, { "no": 2, "input": 11, "rate": "", "sum": 21, "color": false, "aAngle": false }, { "no": 3, "input": 110, "rate": "-1", "sum": 130, "color": false, "aAngle": false } ] ``` ### 테이블 관계도 (최종) ``` ┌──────────────────────────┐ ┌──────────────────────┐ │ bending_items (266건) │ │ bending_models (62건) │ │ ──────────────────────── │ │ ──────────────────── │ │ 기초관리 마스터 │ │ 가이드레일/케이스/ │ │ 품명/재질/규격 (정규컬럼) │◄···│ 하단마감재 모델 │ │ bending_data: JSON (내장) │ │ components JSON │ │ code: RM260319 등 │ │ (sam_item_id 참조) │ └──────────┬───────────────┘ └──────────────────────┘ │ │ 코드 매핑 (FK 없음) │ code 앞 2자리로 items.code 패턴 매칭 ▼ ┌──────────────────────┐ │ items (기존 무변경) │ │ ──────────────────── │ │ BD-{PREFIX}-{LENGTH} │ │ 재고/BOM/작업지시서 │ │ BendingInfoBuilder │ └──────────────────────┘ ``` ### items 테이블과의 관계 — FK 없음, 코드 매핑 ``` ┌──────────────────────────┐ ┌──────────────────────────┐ │ bending_items (신규) │ │ items (기존 유지) │ │ ──────────────────────── │ │ ──────────────────────── │ │ 기초관리 마스터 전용 │ 코드 │ BD-{prod}{spec}-{length} │ │ 품명/재질/규격 정규 컬럼 │ ·····→ │ 재고/BOM/작업지시서 연결 │ │ 전개도 데이터 │ 매핑 │ item_category='BENDING' │ │ code: CP260319 등 │ │ 재고관리용 (무변경) │ │ bending_item_mappings 흡수│ │ │ └──────────────────────────┘ └──────────────────────────┘ 연결 방식: FK 없음 - 재고 조회 필요 시: code 앞 2자리(제품+종류)로 items.code 패턴 매칭 - items 테이블의 재고/BOM 기능은 완전히 독립 유지 - BendingInfoBuilder는 items 테이블 계속 참조 (무변경) - bending_item_mappings 테이블 → 제거 (code에 흡수) ``` ### 영향도 분석 — 변경 / 무변경 구분 | 컴포넌트 | 변경 여부 | 설명 | |----------|----------|------| | `bending_items` 테이블 | **신규 생성** | 전용 테이블 + mappings 흡수 | | `bending_item_mappings` 테이블 | **제거** | bending_items에 컬럼 흡수 | | `BendingItemService` | **수정** | Item::where(BENDING) → BendingItem 모델 | | `BendingItemResource` | **수정** | getOption() → 정규 컬럼 직접 참조 | | `BendingItemController` (API) | 최소 수정 | 서비스만 바뀜, 라우트 동일 | | `BendingItemMapping` 모델 | **제거** | | | `BendingBaseController` (MNG) | 무변경 | API 클라이언트, URL 동일 | | `BendingProductController` (MNG) | 무변경 | API 클라이언트 | | `BendingInfoBuilder` | **무변경** | items 테이블 기반 (재고/BOM용) | | `Migrate5130BendingStock` | **무변경** | items 테이블 재고 생성용 | | `ValidateBendingItems` | **무변경** | items의 BD-* 재고 검증용 | | `files` (이미지) | **수정** | fileable_type='BendingItem' | | `work_order_items` | 무변경 | items.id 참조 유지 | ### 수정 대상 파일 및 완료 상태 (2026-03-19) ``` [API 프로젝트] /home/kkk/sam/api/ ✅ 기초관리 (bending_items): app/Models/BendingItem.php ← Eloquent (bending_data JSON, files) app/Services/BendingItemService.php ← BendingItem 모델, JSON 직접 저장 app/Services/BendingCodeService.php ← BendingItem 조회 (LOT 코드) app/Http/Resources/Api/V1/BendingItemResource.php ← 정규 컬럼 + bending_data JSON + 수치 int 캐스팅 app/Http/Requests/Api/V1/BendingItemStoreRequest.php ← unique → bending_items app/Swagger/v1/BendingItemApi.php ← Swagger 스키마 ✅ 절곡품 모델 (bending_models): app/Models/BendingModel.php ← Eloquent (components JSON, files) app/Services/GuiderailModelService.php ← BendingModel + component 이미지 자동 복사 app/Http/Resources/Api/V1/GuiderailModelResource.php ← 정규 컬럼 + 수치 int 캐스팅 ✅ 파일 처리: app/Http/Controllers/Api/V1/ItemsFileController.php ← items → bending_items → bending_models 폴백 ✅ 이관 커맨드: app/Console/Commands/BendingCleanReimport.php ← 기초관리 클린 재이관 + 이미지 (1커맨드) app/Console/Commands/BendingModelImport.php ← 모델 이관 + 조립도 JSON 업로드 + component 이미지 복사 (1커맨드) ✅ 마이그레이션: 2026_03_19_100000_create_bending_items_table.php 2026_03_19_100001~100003 (bending_data 테이블 → JSON 통합 과정) 2026_03_19_100004_drop_bending_item_mappings_table.php 2026_03_19_100005_add_length_columns_to_bending_items.php 2026_03_19_100006_create_bending_models_table.php 2026_03_19_100007_move_bending_data_back_to_json.php ✅ 제거: app/Models/Production/BendingItemMapping.php ← 삭제됨 app/Models/BendingDataRow.php ← 삭제됨 (JSON 통합) bending_item_mappings 테이블 ← DROP bending_data 테이블 ← DROP (JSON 통합) 무변경: app/Http/Controllers/Api/V1/BendingItemController.php ← 서비스 주입 (변경 불필요) app/Http/Controllers/Api/V1/GuiderailModelController.php ← 서비스 주입 app/Services/Production/BendingInfoBuilder.php ← items 직접 사용 (재고/BOM) app/Console/Commands/Migrate5130BendingStock.php ← items 재고용 app/Console/Commands/ValidateBendingItems.php ← items 재고 검증용 ``` ### 전체 복원 커맨드 ```bash # Step 1: 기초관리 (265건 + bending_data JSON + 이미지 265건) php artisan bending:clean-reimport --legacy-img-path=/tmp/bending_img # Step 2: 절곡품 모델 (61건 + 조립도 61건 + 부품이미지 276건 + sam_item_id) php artisan bending:model-import --legacy-path=/tmp/legacy_5130 # 사전 준비 (docker 컨테이너에 레거시 파일 복사): docker cp /home/kkk/sam/5130/bending/img docker-api-1:/tmp/bending_img docker compose exec -T api mkdir -p /tmp/legacy_5130 docker cp /home/kkk/sam/5130/guiderail docker-api-1:/tmp/legacy_5130/guiderail docker cp /home/kkk/sam/5130/shutterbox docker-api-1:/tmp/legacy_5130/shutterbox docker cp /home/kkk/sam/5130/bottombar docker-api-1:/tmp/legacy_5130/bottombar ``` ### 데이터 현황 (2026-03-19 DB 검증 완료) | 테이블 | 건수 | 소스 | 상태 | |--------|------|------|------| | bending_items | **266건** | chandj.bending 직접 (bending_data JSON 포함) | ✅ 이관 완료 | | bending_models | **62건** | chandj guiderail 21 + shutterbox 30 + bottombar 11 | ✅ 이관 완료 | | bending_item_mappings | 0건 | **DROP 완료** | ✅ 제거됨 | | items (BENDING) | 215건 | 기존 재고/BOM용 — **무변경 유지** | ✅ 독립 | | 파일 (R2 업로드) | 예정 건수 | 현재 | 비고 | |------------------|----------|------|------| | bending_item / bending_diagram | 266건 | ⬜ 미업로드 | `bending:clean-reimport --legacy-img-path` 필요 | | bending_model / assembly_image | 62건 | ⬜ 미업로드 | `bending:model-import --legacy-path` 필요 | | bending_model / component_image | ~280건 | ⬜ 미업로드 | 부품별 독립 복사본 (스냅샷) | | 레거시 대비 | chandj | bending_models | 상태 | |-------------|--------|----------------|------| | 가이드레일 | 20건 | 21건 | ✅ | | 케이스 | 30건 | 30건 | ✅ | | 하단마감재(스크린) | 8건 | 8건 | ✅ | | 하단마감재(철재) | 3건 | 3건 | ✅ | | 검색 검증 | 이전(items) | 현재(bending_items) | 상태 | |----------|------------|-------------------|------| | 하장바 | 2건 | **10건** (chandj 유효건 일치) | ✅ 해결 | > **이미지 업로드 안내**: 레거시 이미지 파일을 docker 컨테이너에 복사 후 artisan 커맨드 실행 필요 (위 "전체 복원 커맨드" 참조) ### 이미지 접근 방식 — MNG2 프록시 (Bearer 인증) ``` 브라우저 → FileViewController (MNG2 서버) → API KEY + Bearer 토큰 자동 첨부 (resolveApiToken) → api.sam.kr/api/v1/files/{id}/view → R2 이미지 반환 인증 흐름: 1. MNG2 로그인 시 ApiTokenService.exchangeToken() → 세션에 Bearer 토큰 저장 2. FileViewController에서 resolveApiToken() → 만료 시 자동 재발급 3. API KEY (.env FLOW_TESTER_API_KEY) + Bearer 토큰으로 API 호출 4. SSL 자체서명 인증서 → withoutVerifying() 적용 필수 .env 설정 (MNG2): API_BASE_URL=https://api.sam.kr FLOW_TESTER_API_KEY={api_keys 테이블의 key} INTERNAL_EXCHANGE_SECRET={API 서버와 동일한 값} ``` ### 이미지 스냅샷 정책 ``` 기초관리 이미지 수정 → 모델 component에 영향 없음 (독립 복사본) 구조: bending_items → files (bending_diagram) ← 원본 (수정 가능) bending_models → components[].image_file_id ← 복사본 (독립) → files (assembly_image) ← 조립도 (별도) 신규 부품 추가 시: API(GuiderailModelService)에서 image_file_id 자동 복사 예정 MNG2 editPartOriginal() → sam_item_id로 기초관리 편집 페이지 연결 ``` ### LOT 코드 체계 ``` 형식: {제품Code}{종류Code}{YYMMDD} 유니크: (tenant_id, code, length_code, deleted_at) 예시: RS260319 + length_code=30 → 가이드레일(벽면) SUS마감 3000mm CF260319 → 케이스 전면부 BS260319 + length_code=40 → 하단마감재(스크린) SUS 4000mm 변환 완료: BD-PREFIX-LEN 112건 → LOT 코드 미변환: BD-한글 58건, BD-LEGACY 40건 (legacy_code 유지, 향후 변환) ``` ### LOT 코드 체계 (레거시 형태 유지) ``` 형식: {제품Code}{종류Code}{YYMMDD} 예시: RM260319 → 가이드레일(벽면형) 본체, 2026-03-19 RS260319 → 가이드레일(벽면형) SUS마감재, 2026-03-19 CF260319 → 케이스 전면부, 2026-03-19 BS260319 → 하단마감재(스크린) SUS, 2026-03-19 ``` **LOT 코드 테이블 (정본)**: | 제품 | 제품Code | 종류명 | 종류Code | |------|----------|--------|----------| | 가이드레일(벽면형) | R | 본체 | M | | | | 본체(철재) | T | | | | C형 | C | | | | D형 | D | | | | SUS 마감재 | S | | 가이드레일(측면형) | S | 본체디딤 | M | | | | 본체(철재) | T | | | | C형 | C | | | | D형 | D | | | | SUS 마감재1 | S | | | | SUS 마감재2 | U | | 케이스 | C | 전면부 | F | | | | 점검구 | P | | | | 린텔부 | L | | | | 후면코너부 | B | | 하단마감재(스크린) | B | SUS | S | | | | EGI | E | | 하단마감재(철재) | T | SUS | S | | | | EGI | E | | L-Bar | L | 스크린용 | A | | 연기차단재 | G | 화이바원단(W50) | I | | | | 화이바원단(W80) | I | ### 데이터 현황 (2026-03-19 DB 검증 완료) | 항목 | 건수 | 비고 | |------|------|------| | **bending_items** (전용 테이블) | **266건** | ✅ 전건 bending_data JSON 포함 | | **bending_models** (전용 테이블) | **62건** | ✅ guiderail 21 + shutterbox 30 + bottombar 11 | | items BENDING (기존, 무변경) | 215건 | 재고/BOM용 독립 유지 | | bending_item_mappings | **DROP 완료** | bending_items.code에 흡수 | | 하장바 (bending_items) | **10건** | ✅ chandj 유효건과 일치 | | 이미지 (R2) | **미업로드** | 레거시 파일 docker 복사 후 커맨드 실행 필요 | --- ## MNG 현재 구조 ### 생산관리 메뉴 (sidebar-static.blade.php) ``` 생산 관리 (production-group) ├─ 품목기준 필드 관리 ✅ (구현됨) ├─ 견적수식 관리 ✅ (구현됨) ├─ 제품 관리 (준비중) ├─ 자재 관리 (준비중) ├─ BOM 관리 (준비중) ├─ 카테고리 관리 (준비중) └─ 절곡품 관리 ← 🆕 추가 대상 ├─ 기초관리 (개별 부품 CRUD) └─ 절곡품 (모델별 조합 관리) ``` ### 기존 절곡 관련 코드 (MNG) | 파일 | 역할 | 변경 여부 | |------|------|----------| | `views/documents/partials/bending-worklog.blade.php` | 절곡 작업일지 렌더링 | 무변경 | | `views/documents/partials/bending-inspection-data.blade.php` | 절곡 중간검사 | 무변경 | --- ## 작업 순서 및 진행 상태 ``` Step 1 (DB분석) → Step 2 (API) → Step 3 (MNG 화면) → Step 4 (React 연동) ✅ 완료 ✅ 완료 ✅ 완료 (샘플용) ⬜ 미착수 테이블 분리: ✅ 완료 (bending_items + bending_models 전용 테이블) 데이터 이관: ✅ 완료 (266건 기초관리 + 62건 모델) 이미지 업로드: ⬜ 미완료 (레거시 파일 docker 복사 후 커맨드 실행 필요) ``` | 문서 | 내용 | 상태 | |------|------|:---:| | `step1-데이터분석.md` | 레거시 매핑 + options 확장 | ✅ 완료 | | `step2-API.md` | API 엔드포인트 + 컨트롤러 설계 | ✅ 완료 | | `step3-MNG화면.md` | Blade 뷰 + HTMX + 메뉴 등록 | ✅ 완료 | | `step4-React연동.md` | React 운영 화면 구현 | ⬜ 미착수 | | `legacy-guiderail-analysis.md` | 레거시 guiderail 모듈 상세 분석 | ✅ 완료 | ### 완료된 작업 (2026-03-16~19) **Step 1 완료 (DB 분석 + 테이블 분리):** - `bending_items` 전용 테이블 생성 — 정규 컬럼 승격 (item_name, item_sep, material 등 인덱스) - `bending_models` 전용 테이블 생성 — 가이드레일/케이스/하단마감재 3개 타입 통합 - `bending_data` 테이블 → JSON 통합 → `bending_items.bending_data` 컬럼 - `bending_item_mappings` 테이블 DROP — `bending_items.code`에 흡수 - `bending:clean-reimport` — chandj.bending 266건 직접 이관 (bending_data JSON 포함) - `bending:model-import` — chandj guiderail 21 + shutterbox 30 + bottombar 11 = 62건 이관 - ~~`bending:fill-options`~~ / ~~`bending:import-legacy`~~ — 구 items 방식 커맨드 (대체됨) **Step 2 완료 (API):** - `BendingItemController` — CRUD + filters + pagination (6 엔드포인트) - `GuiderailModelController` — CRUD + filters (6 엔드포인트, 3개 카테고리 통합) - `BendingItemResource` / `GuiderailModelResource` — API 응답 포맷 (정규 컬럼 직접 참조) - `FormRequest` — Index/Store/Update 유효성 검증 - `ApiKeyMiddleware` — bending/guiderail/files 화이트리스트 **Step 3 완료 (MNG 샘플용):** - 기초관리: 목록(13컬럼) + 폼(기본정보12필드 + 케이스전용5필드 + 절곡테이블 + 이미지업로드) - 절곡품: 가이드레일/케이스/하단마감재 별도 메뉴 + 타입별 헤더 분기 - 절곡품 폼: 부품 추가(기초관리 검색 모달) + 삭제 + 수량/품명/재질 편집 + 절곡테이블 inline 편집 - 작업지시서: 레거시 포맷 인쇄 페이지 (`/print`) - 파일: FileViewController (API R2 프록시) + 이미지 업로드/표시 - DB 메뉴: 기초관리 + 절곡품 + 케이스 + 하단마감재 (4개) **미완료:** - ⬜ 이미지 R2 업로드 — 레거시 파일 docker 복사 후 커맨드 재실행 필요 - ⬜ Step 4 React 연동 — 미착수 --- ## 참조 문서 | 문서 | 경로 | 용도 | |------|------|------| | 갭 분석 | `dev_plans/bending-parts-analysis.md` | 요구사항 기준 | | API 규칙 | `standards/api-rules.md` | API 네이밍/응답 | | options 정책 | `standards/options-column-policy.md` | JSON 컬럼 설계 | | 품목 정책 | `rules/item-policy.md` | BD 코드 체계 | | Phase 2 | `dev_plans/integrated-phase-2.md` | 절곡 설계 | | Phase 3 | `dev_plans/integrated-phase-3.md` | 절곡 검사 | ## 프로토타입 | 위치 | 설명 | |------|------| | `SAM/work/절곡/index.html` | 사이드바 + iframe 전체 구조 | | `SAM/work/절곡/base.html` | 기초관리 목록 (참고용) | | `SAM/work/절곡/base-form.html` | 등록/수정 폼 + 절곡 테이블 (참고용) | | `SAM/work/절곡/products.html` | 절곡품 탭 목록 (참고용) | | `SAM/work/절곡/product-form.html` | 절곡품 등록/수정 (참고용) | # 절곡품 관리 — 전체 흐름도 --- ## 1. 시스템 전체 구조 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ SAM 절곡품 관리 시스템 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ MNG │ │ API │ │ React │ │ │ │ (샘플용) │────→│ (핵심) │←────│ (운영용) │ │ │ │ Blade │ │ Laravel │ │ Next.js │ │ │ └──────────┘ └─────┬────┘ └──────────┘ │ │ │ │ │ ┌─────────────┐ │ │ │ samdb │ │ │ │bending_items│ ← 기초관리 마스터 (전용, bending_data JSON 포함) │ │ │bending_models│ ← 절곡품 모델 (가이드레일/케이스/하단마감재) │ │ │ items │ ← 재고/BOM용 (기존 무변경) │ │ │ files │ ← bending_diagram 이미지 │ │ └─────────────┘ │ │ │ │ │ ┌────┴────┐ │ │ │ R2 │ ← Cloudflare (이미지 저장) │ │ └─────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘ ``` --- ## 2. 데이터 구조 (2계층 — 전용 테이블 + JSON) ``` ┌─────────────────────────────────────────────────────────────────┐ │ │ │ [1계층] 기초관리 — 개별 부품 (bending_items 전용 테이블) │ │ ══════════════════════════════════════════════ │ │ │ │ bending_items (266건) │ │ ┌──────────────────────────────────────────────────┐ │ │ │ id: 100 │ │ │ │ code: RM260319 ← LOT 코드 (제품+종류+날짜)│ │ │ │ legacy_code: BD-LEGACY-042 ← 이전 코드 보존 │ │ │ │ item_name: "마감재" ← 정규 컬럼 (인덱스) │ │ │ │ item_sep: "스크린" ← 정규 컬럼 (인덱스) │ │ │ │ item_bending: "가이드레일" ← 정규 컬럼 (인덱스) │ │ │ │ material: "SUS 1.2T" ← 정규 컬럼 (인덱스) │ │ │ │ model_name: "KSS01" ← 정규 컬럼 │ │ │ │ model_UA: "인정" ← 정규 컬럼 │ │ │ │ item_spec: "120*70" ← 정규 컬럼 │ │ │ │ rail_width: 70 ← 정규 컬럼 │ │ │ │ + 케이스전용: exit_direction, box_width... 정규 │ │ │ │ bending_data: JSON 배열 ← 전개도 데이터 (내장) │ │ │ │ [{no:1, input:10, rate:"", sum:10, color:true}, │ │ │ │ {no:2, input:11, rate:"", sum:21, color:false}, │ │ │ │ {no:3, input:110, rate:"-1", sum:130}, ...] │ │ │ └──────────────────────────────────────────────────┘ │ │ ↑ 266건 (전건 bending_data JSON 포함) │ │ │ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │ │ │ [2계층] 절곡품 — 모델별 부품 조합 │ │ ════════════════════════════════ │ │ │ │ ┌────────────────────────────────────────────────────────┐ │ │ │ 가이드레일 모델: KSS01 벽면형 SUS마감 │ │ │ │ │ │ │ │ components (부품 조합): │ │ │ │ ┌─────┬───────────┬──────────┬────┬────────┐ │ │ │ │ │순서 │ 부품명 │ 재질 │수량│전개폭합│ │ │ │ │ ├─────┼───────────┼──────────┼────┼────────┤ │ │ │ │ │ 1 │ 마감재 │ SUS 1.2T│ 2 │ 203 │ ──→ item:100│ │ │ │ 2 │ 본체 │ EGI 1.55│ 1 │ 296 │ ──→ item:101│ │ │ │ 3 │ 벽면형-C │ EGI 1.55│ 1 │ 144 │ ──→ item:102│ │ │ │ 4 │ 벽면형-D │ EGI 1.55│ 1 │ 144 │ ──→ item:103│ │ │ └─────┴───────────┴──────────┴────┴────────┘ │ │ │ │ │ │ │ │ 재질별 폭합: SUS 1.2T → 406 | EGI 1.55T → 398 │ │ │ └────────────────────────────────────────────────────────┘ │ │ ↑ 가이드레일 21건 + 케이스 30건 + 하단마감재 11건 = 62건 │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 3. 3가지 타입 비교 ``` ┌─────────────────┬─────────────────┬─────────────────┐ │ 가이드레일 │ 케이스 │ 하단마감재 │ ├─────────────────┼─────────────────┼─────────────────┤ │ │ │ │ │ 모델: KSS01 │ 모델: ❌ 없음 │ 모델: KSS01 │ │ 마감: SUS/EGI │ 마감: ❌ 없음 │ 마감: SUS/EGI │ │ 형상: 벽면/측면 │ 형상: ❌ 없음 │ 형상: ❌ 없음 │ │ 대분류: 스크린/철재│ 대분류: ❌ │ 대분류: 스크린/철재│ │ 인정: 인정/비인정 │ 인정: ❌ │ 인정: 인정/비인정 │ │ │ │ │ │ 규격: 120×70 │ 규격: 650×550 │ 규격: 60×40 │ │ 레일폭: 70 │ 전면밑: 50 │ │ │ │ 레일폭: 75 │ │ │ │ 점검구: 후면 │ │ │ │ │ │ │ 파트: 3~5개 │ 파트: 5개 │ 파트: 1개 │ │ ┌─────────────┐│ ┌─────────────┐│ ┌─────────────┐│ │ │본체상부 ││ │상부덮개 ││ │하단마감 ││ │ │본체하부 ││ │전면 ││ │(단일 파트) ││ │ │마감재 ││ │점검구 ││ └─────────────┘│ │ │(+C형,D형) ││ │린텔 ││ │ │ └─────────────┘│ │후면코너 ││ │ │ │ └─────────────┘│ │ ├─────────────────┼─────────────────┼─────────────────┤ │ 재질별 폭합 │ 재질별 폭합 │ 재질별 폭합 │ │ SUS: 406 │ EGI: 2652 │ SUS: 193 │ │ EGI: 398 │ │ │ └─────────────────┴─────────────────┴─────────────────┘ ``` --- ## 4. 전개도 테이블 구조 (1개 부품) ``` 레거시 5130 화면과 동일한 구조: ┌────────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ 번호 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ 입력 │ 10 │ 11 │ 110 │ 30 │ 15 │ 15 │ 15 │ ← 치수 입력 │ │[색상]│ │ │ │ │[색상]│ │ ← 파란 배경 ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ 연신율 │ │ │ -1 │ -1 │ -1 │ │ │ ← 절곡 방향 ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │연신율후 │ 10 │ 11 │ 109 │ 29 │ 14 │ 15 │ 15 │ ← input + rate │ │ │ │(-1) │(-1) │(-1) │ │ │ (rate=-1 → -1mm) ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ 합계 │ 10 │ 21 │ 130 │ 159 │ 173 │ 188 │ 203 │ ← 보정후 누적합 │ │[색상]│ │ │ │ │[색상]│ │ ← 노란 배경 ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ 음영 │ ■■ │ │ │ │ │ ■■ │ │ ← 색상 마킹 ├────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │ A각 │ │ │ │ A각 │ │ │ │ ← A각 표시 └────────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ 연신율 보정 규칙: rate = "" → 보정 없음 (input 그대로) rate = "-1" → input - 1mm (하향 절곡) rate = "1" → input + 1mm (상향 절곡) 합계 = 보정후 값의 누적합 폭합계 = 마지막 합계값 (이 예시: 203) ``` --- ## 5. JSON 저장 구조 (options.bendingData) ``` 레거시 (별도 배열 5개) SAM (객체 배열 1개) ──────────────────── ──────────────────── inputList: [10,11,110...] bendingData: [ bendingrateList: ["","","-1"...] { no:1, input:10, rate:"", sumList: [10,21,130...] sum:10, color:true, aAngle:false }, colorList: [true,false,false...] { no:2, input:11, rate:"", AList: [false,false,false...] sum:21, color:false, aAngle:false }, { no:3, input:110, rate:"-1", → 5개 배열 동기화 필요 sum:130, color:false, aAngle:false }, → 열 추가/삭제 시 5개 다 조작 ... ] → 1개 배열만 관리 → 열 추가 = 객체 1개 push ``` --- ## 6. 화면 흐름도 ``` ┌──────────────────────────────────────────────────────────────┐ │ MNG │ │ │ │ 생산 관리 │ │ ├─ 품목기준 필드 관리 │ │ ├─ 견적수식 관리 │ │ └─ 🆕 절곡품 관리 │ │ ├─ 기초관리 ─────────────────┐ │ │ └─ 절곡품 ──────────────┐ │ │ │ │ │ │ └─────────────────────────────┼────┼───────────────────────────┘ │ │ ┌───────────────────┘ └───────────────────┐ ▼ ▼ ┌──────────────────────┐ ┌──────────────────────┐ │ 절곡품 목록 │ │ 기초관리 목록 │ │ │ │ │ │ [가이드레일] [케이스] │ │ 265건 테이블 │ │ [하단마감재] │ │ 필터: 대분류/인정/ │ │ │ │ 그룹/품명/검색 │ │ 필터 + 테이블 │ │ │ │ │ │ 행 클릭 ──→ 상세 │ │ 행 클릭 ──→ 상세 │ │ [+등록] ──→ 등록 │ │ [+등록] ──→ 등록 │ └───────────┬──────────┘ └───────────┬──────────┘ │ │ │ ▼ ▼ ┌──────────────────────┐ ┌──────────────────────┐ │ 절곡품 등록/수정 │ │ 기초관리 등록/수정 │ │ │ │ │ │ ┌──────────┬───────┐ │ │ ┌──────────┬───────┐ │ │ │ 기본정보 │ 이미지 │ │ │ │ 기본정보 │ 이미지 │ │ │ │ (타입별) │ 업로드 │ │ │ │ 대분류 │ 업로드 │ │ │ ├──────────┤ 검색어 │ │ │ │ 그룹/품명 │ 검색어 │ │ │ │ 파트 탭 │ │ │ │ │ 재질/규격 │ │ │ │ │ [1][2][3] │ │ │ │ ├──────────┤ │ │ │ │ │ │ │ │ │ 절곡 테이블│ │ │ │ │ 절곡테이블│ │ │ │ │ (단일) │ │ │ │ │ (파트별) │ │ │ │ ├──────────┤ │ │ │ ├──────────┤ │ │ │ │ 재질별폭합│ │ │ │ │ 재질별폭합│ │ │ │ └──────────┴───────┘ │ │ └──────────┴───────┘ │ └──────────────────────┘ └──────────────────────┘ ``` --- ## 7. API 엔드포인트 흐름 ``` MNG / React │ ├── GET /api/v1/bending-items ← 기초관리 목록 ├── GET /api/v1/bending-items/filters ← 필터 옵션 ├── GET /api/v1/bending-items/{id} ← 상세 ├── POST /api/v1/bending-items ← 등록 ├── PUT /api/v1/bending-items/{id} ← 수정 ├── DELETE /api/v1/bending-items/{id} ← 삭제 │ ├── GET /api/v1/guiderail-models ← 절곡품 모델 목록 ├── GET /api/v1/guiderail-models/{id} ← 모델 상세 (부품조합) ├── POST /api/v1/guiderail-models ← 모델 등록 ├── PUT /api/v1/guiderail-models/{id} ← 모델 수정 ├── DELETE /api/v1/guiderail-models/{id} ← 모델 삭제 │ ├── POST /api/v1/items/{id}/files ← 이미지 업로드 (기존) ├── GET /api/v1/items/{id}/files ← 이미지 목록 (기존) └── GET /api/v1/files/{id}/view ← 이미지 표시 (기존) ※ 이미지는 기존 ItemsFileController 재사용 ※ field_key: 'bending_diagram' ``` --- ## 8. 작업 순서 ``` Step 1 Step 2 Step 3 Step 4 데이터 분석 API 구현 MNG 화면 React 화면 ━━━━━━━━ ━━━━━━━━ ━━━━━━━━ ━━━━━━━━ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │레거시 265건│ │Controller│ │기초관리 │ │견적 이미지│ │SAM 170건 │──→ │Service │──→ │ 목록/등록 │──→ │GuiderailP│ │매핑 테이블 │ │FormReq │ │절곡품 │ │review │ │ │ │Resource │ │ 목록/등록 │ │ │ │options 확장│ │ │ │ │ │절곡품 │ │artisan cmd│ │이미지: │ │메뉴 등록 │ │관리 화면 │ │ │ │기존 재사용│ │(tinker) │ │(본 화면) │ │회귀 테스트 │ │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ API 프로젝트 API 프로젝트 MNG 프로젝트 React 프로젝트 (샘플 확인용) (운영용) ``` --- ## 9. 레거시 → SAM 대응표 ``` 레거시 (5130) SAM (테이블 분리 완료) ━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━ chandj.bending (265건) → bending_items (266건, 전용 테이블, 정규 컬럼) chandj.bending.전개도 배열 → bending_items.bending_data (JSON 컬럼, 내장) chandj.guiderail (20건) → bending_models (62건, guiderail+shutterbox+bottombar) guiderail/list.php → MNG /bending/products (절곡품 목록) bending CRUD → MNG /bending/base (기초관리) put_guiderail_image.php → 기존 FileController (R2) — ⬜ 이미지 업로드 미완료 fetch_guiderail_detail.php → React GuiderailPreview drawingTool.js (Canvas) → 2차 구현 (1차는 이미지 업로드만) inputList[] (별도 배열 5개) → bending_data JSON [{no, input, rate, sum, color, aAngle}] items (BENDING) + options → items 유지 (재고/BOM용, BendingInfoBuilder 무변경) bending_item_mappings → DROP 완료 (bending_items.code에 흡수) ``` --- ## 10. 레거시 guiderail 모듈 상세 분석 > 별도 문서로 분리: [`legacy-guiderail-analysis.md`](./legacy-guiderail-analysis.md) > > 포함 내용: 파일 구성(21개), DB 스키마(guiderail/bending), CRUD 흐름, > 전개도 생성, 구성요소(벽면형/측면형), 검색/필터, guidebook