diff --git a/dev/dev_plans/bending-management/README.md b/dev/dev_plans/bending-management/README.md
new file mode 100644
index 0000000..cab0be7
--- /dev/null
+++ b/dev/dev_plans/bending-management/README.md
@@ -0,0 +1,390 @@
+# 절곡품 관리 기능 개발 계획서
+
+> **시작일**: 2026-03-16
+> **위치**: MNG 생산관리 > 절곡품 관리 (신규 메뉴)
+> **목표**: 경동기업(5130) 수준의 절곡품 마스터 관리 + 전개도 데이터 + 이미지 관리
+> **원칙**: 기존 BendingInfoBuilder/PrefixResolver 보존, items.options 확장 방식
+
+---
+
+## 배경
+
+SAM은 절곡품의 "계산과 조합"(BendingInfoBuilder/PrefixResolver)은 잘 되어 있지만,
+"관리와 시각화"가 빠져 있다. 경동기업(5130) `guiderail/list.php` 수준의 관리 화면을 MNG에 구현한다.
+
+**갭 분석**: `docs/dev/dev_plans/bending-parts-analysis.md` 참조
+
+---
+
+## 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 연동)
+레거시 매핑 options 확장 Blade + HTMX 견적 이미지
++ 데이터 정리 + 엔드포인트 + 메뉴 등록
+```
+
+상세 계획: 아래 문서 참조
+
+| 문서 | 내용 |
+|------|------|
+| `step1-데이터분석.md` | 레거시 매핑 + options 확장 |
+| `step2-API.md` | API 엔드포인트 + 컨트롤러 설계 |
+| `step3-MNG화면.md` | Blade 뷰 + HTMX + 메뉴 등록 |
+| `step4-React연동.md` | 견적 페이지 이미지 컴포넌트 |
+
+---
+
+## 참조 문서
+
+| 문서 | 경로 | 용도 |
+|------|------|------|
+| 갭 분석 | `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 │ │
+│ │ items │ ← item_category = 'BENDING' │
+│ │ files │ ← field_key = 'bending_diagram' │
+│ └─────────┘ │
+│ │ │
+│ ┌────┴────┐ │
+│ │ R2 │ ← Cloudflare (이미지 저장) │
+│ └─────────┘ │
+│ │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 2. 데이터 구조 (2계층)
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ │
+│ [1계층] 기초관리 — 개별 부품 (items 테이블) │
+│ ════════════════════════════════════════ │
+│ │
+│ items (item_category = 'BENDING') │
+│ ┌──────────────────────────────────────────────────┐ │
+│ │ id: 100 │ │
+│ │ code: BD-가이드레일-KSS01-SUS-120*70 │ │
+│ │ name: 가이드레일 KSS01 SUS 120*70 │ │
+│ │ options: { │ │
+│ │ item_name: "마감재" ← 부품 품명 │ │
+│ │ item_sep: "스크린" ← 대분류 │ │
+│ │ item_bending: "가이드레일" ← 중분류 │ │
+│ │ material: "SUS 1.2T" ← 재질 │ │
+│ │ model_name: "KSS01" ← 소속 모델 │ │
+│ │ model_UA: "인정" ← 인정여부 │ │
+│ │ item_spec: "120*70" ← 규격 │ │
+│ │ rail_width: 70 ← 레일폭 │ │
+│ │ bendingData: [ ← 전개도 데이터 │ │
+│ │ {no:1, input:10, rate:"", sum:10, ...}, │ │
+│ │ {no:2, input:11, rate:"", sum:21, ...}, │ │
+│ │ ... │ │
+│ │ ] │ │
+│ │ + 케이스전용: exit_direction, box_width, ... │ │
+│ │ } │ │
+│ └──────────────────────────────────────────────────┘ │
+│ ↑ 265건 (레거시) + α │
+│ │
+│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
+│ │
+│ [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 │ │
+│ └────────────────────────────────────────────────────────┘ │
+│ ↑ 가이드레일 20건 + 케이스 + 하단마감재 │
+│ │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## 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건) → items (item_category='BENDING') + options
+chandj.guiderail (20건) → guiderail-models API (신규 저장 구조)
+guiderail/list.php → MNG /bending/products (절곡품 목록)
+bending CRUD → MNG /bending/base (기초관리)
+put_guiderail_image.php → 기존 ItemsFileController (R2)
+fetch_guiderail_detail.php → React GuiderailPreview
+drawingTool.js (Canvas) → 2차 구현 (1차는 이미지 업로드만)
+inputList[] (별도 배열) → bendingData[] (객체 배열)
+bendingrateList[] → bendingData[].rate
+sumList[] → bendingData[].sum
+colorList[] → bendingData[].color
+AList[] → bendingData[].aAngle
+```
+
+
diff --git a/dev/dev_plans/bending-management/step1-데이터분석.md b/dev/dev_plans/bending-management/step1-데이터분석.md
new file mode 100644
index 0000000..ae1104b
--- /dev/null
+++ b/dev/dev_plans/bending-management/step1-데이터분석.md
@@ -0,0 +1,282 @@
+# Step 1: 데이터 분석 + options 확장
+
+> **프로젝트**: API (`sam/api`)
+> **선행 조건**: 없음
+> **참조**: `standards/options-column-policy.md`, `rules/item-policy.md`
+
+---
+
+## 1. 레거시 데이터 매핑
+
+### 1-1. 레거시 데이터 현황 (chandj DB)
+
+**테이블별 건수**:
+
+| 테이블 | 건수 | 설명 |
+|--------|------|------|
+| `bending` | 265건 (활성) | 개별 절곡품 부품 |
+| `guiderail` | 20건 (활성) | 모델별 부품 조합 (7개 모델 + 비인정 1개) |
+| `bendingfee` | 82건 | 절곡 단가 |
+| `bendingmap` | 9건 | 절곡 매핑 |
+| `etcbending` | 2건 | 기타 절곡 |
+| `bending_work_log` | 8건 | 작업 로그 |
+
+**bending 분류 분포** (265건):
+
+| 대분류 | 중분류 | 건수 |
+|--------|--------|------|
+| 스크린 | 가이드레일 | 41 |
+| 스크린 | 케이스 | 24 |
+| 스크린 | 하단마감재 | 6 |
+| 스크린 | 마구리 | 4 |
+| 스크린 | L-BAR | 2 |
+| 철재 | 케이스 | 136 |
+| 철재 | 가이드레일 | 30 |
+| 철재 | (미분류) | 9 |
+| 철재 | 마구리 | 8 |
+| 철재 | 하단마감재 | 5 |
+
+**bending 테이블 전체 컬럼** (25개):
+
+| 컬럼 | 타입 | 설명 | options 키 |
+|------|------|------|-----------|
+| `num` | int PK | 번호 | `legacy_bending_num` |
+| `is_deleted` | tinyint | 삭제여부 | SAM 자체 관리 |
+| `item_sep` | varchar(14) | 대분류 (스크린/철재) | `item_sep` |
+| `model_UA` | varchar(15) | 인정여부 | `model_UA` |
+| `item_bending` | varchar(40) | 중분류 | `item_bending` |
+| `itemName` | varchar(50) | 품명 | `item_name` |
+| `material` | varchar(25) | 재질 | `material` |
+| `parentnum` | varchar(12) | 부모 참조 | `parent_num` |
+| `registration_date` | date | 등록일 | `registration_date` |
+| `imgdata` | text | 이미지 파일경로 | `image_path` |
+| `inputList` | text | 치수 JSON | `bendingData[].input` |
+| `bendingrateList` | text | 연신율 JSON | `bendingData[].rate` |
+| `sumList` | text | 합계 JSON | `bendingData[].sum` |
+| `colorList` | text | 색상마킹 JSON | `bendingData[].color` |
+| `AList` | text | A각 JSON | `bendingData[].aAngle` |
+| `memo` | text | 비고 | `memo` |
+| `update_log` | text | 수정 이력 | SAM 자체 관리 (updated_at) |
+| `item_spec` | varchar(50) | 규격 | `item_spec` |
+| `widthsum` | int | 폭합계 | 계산값 (bendingData 마지막 sum) |
+| `author` | varchar(20) | 작성자 | `author` |
+| `search_keyword` | varchar(50) | 검색어 | `search_keyword` |
+| `exit_direction` | varchar(20) | 점검구 방향 (케이스) | `exit_direction` |
+| `front_bottom_width` | varchar(5) | 전면부 밑 치수 (케이스) | `front_bottom_width` |
+| `rail_width` | varchar(5) | 레일폭 | `rail_width` |
+| `box_width` | varchar(5) | 케이스 너비 | `box_width` |
+| `box_height` | varchar(5) | 케이스 높이 | `box_height` |
+
+**전개도 JSON 현황**: 265건 전부 inputList/bendingrateList/sumList/colorList/imgdata 보유 (크기: 30~50 bytes/필드)
+
+**guiderail 모델 목록** (20건):
+
+| 모델 | 인정 | 형태 | 레일폭 | 레일길이 | 마감 | 제품 |
+|------|------|------|--------|---------|------|------|
+| KSS01 | 인정 | 벽면/측면 | 70/120 | 120 | SUS | 스크린 |
+| KSS02 | 인정 | 벽면/측면 | 70/120 | 120 | SUS | 스크린 |
+| KSE01 | 인정 | 벽면/측면 | 70/120 | 120 | EGI/SUS | 스크린 |
+| KWE01 | 인정 | 벽면/측면 | 70/120 | 120 | EGI/SUS | 스크린 |
+| KTE01 | 인정 | 벽면/측면 | 75/125 | 130 | EGI/SUS | 철재 |
+| KQTS01 | 인정 | 벽면/측면 | 75/125 | 130 | SUS | 철재 |
+| KDSS01 | 인정 | 벽면 | 150 | 150 | SUS | 스크린 |
+| 스크린비인정 | 비인정 | 벽면 | 70 | 130 | SUS | 스크린 |
+
+**guiderail 테이블 전체 컬럼** (15개):
+
+| 컬럼 | 타입 | 설명 |
+|------|------|------|
+| `num` | int PK | 번호 |
+| `is_deleted` | varchar(2) | 삭제여부 |
+| `registration_date` | date | 등록일 |
+| `model_UA` | varchar(10) | 인정여부 |
+| `check_type` | varchar(20) | 형상 (벽면형/측면형) |
+| `model_name` | varchar(15) | 모델명 |
+| `author` | varchar(50) | 작성자 |
+| `remark` | text | 비고 |
+| `update_log` | text | 수정 이력 |
+| `rail_width` | varchar(10) | 레일폭 |
+| `rail_length` | varchar(10) | 레일길이(높이) |
+| `finishing_type` | varchar(10) | 마감 (SUS마감/EGI마감) |
+| `bending_components` | mediumtext | 부품 조합 JSON |
+| `firstitem` | varchar(15) | 대분류 (스크린/철재) |
+| `search_keyword` | varchar(50) | 검색어 |
+| `material_summary` | text | 재질별 폭합 |
+
+### 1-1b. 추가 파악 필요
+
+| 작업 | 대상 | 비고 |
+|------|------|------|
+| BendingInfoBuilder.php 지원 모델 추출 | 코드 분석 | 기존 로직 파악 |
+| PrefixResolver.php PREFIX 규칙 추출 | 코드 분석 | 기존 로직 파악 |
+| bendingfee 82건 구조 | 절곡 단가 — SAM 연동 필요 여부 | |
+| bendingmap 9건 구조 | 매핑 용도 확인 | |
+
+### 1-2. SAM BD 품목 현황 (170건)
+
+**패턴별 분류**:
+
+| 패턴 | 건수 | 예시 | 파싱 |
+|------|------|------|------|
+| A) `BD-PREFIX-LEN` | 112 | BD-RS-30, BD-CF-35 | prefix/length 자동 추출 |
+| B) `BD-L-BAR-모델-규격` | 5 | BD-L-BAR-KSS01-17*60 | 모델+규격 추출 가능 |
+| C) `BD-가이드레일-모델-재질-규격` | 21 | BD-가이드레일-KSS01-SUS-120*70 | 모델+재질+규격 추출 가능 |
+| D) `BD-마구리-규격` | 10 | BD-마구리-655*505 | 규격 추출 가능 |
+| E) `BD-케이스-규격` | 11 | BD-케이스-650*550 | 규격 추출 가능 |
+| F) `BD-하단마감재-모델-재질-규격` | 10 | BD-하단마감재-KSS01-SUS-60*40 | 모델+재질+규격 추출 가능 |
+| G) `BD-보강평철-규격` | 1 | BD-보강평철-50 | 규격 추출 가능 |
+
+**A) PREFIX-LEN 112건 상세**:
+
+| PREFIX | 용도 | 길이 종류 | 건수 |
+|--------|------|----------|------|
+| RS | 가이드레일 마감재(벽면) SUS | 24,30,35,40,43 | 5 |
+| SS | 가이드레일 마감재(측면) SUS | 30,35,40,43 | 4 |
+| SU | 가이드레일 마감재(측면) SUS2 | 30,35,40,43 | 4 |
+| RM | 가이드레일 본체(벽면) | 12,24,30,35,40,42,43 | 7 |
+| SM | 가이드레일 본체(측면) | 02,24,30,35,40,43 | 6 |
+| RC | 가이드레일 C형(벽면) | 12,24,30,35,40,42,43 | 7 |
+| RD | 가이드레일 D형(벽면) | 12,24,30,35,40,42,43 | 7 |
+| SC | 가이드레일 C형(측면) | 24,30,35,40,43 | 5 |
+| SD | 가이드레일 D형(측면) | 24,30,35,40,43 | 5 |
+| RT | 가이드레일 본체(벽면/철재) | 30,43 | 2 |
+| ST | 가이드레일 본체(측면/철재) | 43 | 1 |
+| BS | 하단마감재(스크린) SUS | 12,24,30,35,40,42,43 | 7 |
+| BE | 하단마감재(스크린) EGI | 30,40 | 2 |
+| TS | 하단마감재(철재) SUS | 40,43 | 2 |
+| CF | 케이스 전면부 | 12,24,30,35,40,41 | 6 |
+| CL | 케이스 린텔부 | 12,24,30,35,40,41 | 6 |
+| CP | 케이스 점검구 | 12,24,30,35,40,41 | 6 |
+| CB | 케이스 후면코너부 | 12,24,30,35,40,41 | 6 |
+| GI | 연기차단재 | 24,30,35,40,43,53,54,83,84 | 9 |
+| HH | 보강평철 | 30,40 | 2 |
+| LA | L-Bar | 30,40 | 2 |
+| XX | 하부BASE/상부덮개/마구리(공용) | 12,24,30,35,40,41,43 | 7 |
+| YY | 별도마감 | 30,35,40,43 | 4 |
+
+**options 채워진 상태**:
+
+| 상태 | 건수 | 비고 |
+|------|------|------|
+| options 완전 (prefix+length) | 22 | 13% |
+| options 있지만 불완전 | 90 | PREFIX-LEN 중 일부 |
+| options 비어있음 (`{}`) | 58 | 한글 패턴 전부 |
+
+### 1-3. 매핑 테이블 작성
+
+```
+레거시 bending (부품 단위) SAM items (품목 단위)
+───────────────────────── ─────────────────────
+num:100 마감재 SUS 120*70 ↔ BD-가이드레일-KSS01-SUS-120*70 (한글 패턴)
+num:101 본체 EGI 120*70 ↔ BD-RM-30 (PREFIX-LEN — 길이 기준)
+ ※ 부품 단위 vs 길이 단위 구조 차이
+```
+
+**핵심 결정사항**:
+- BD-한글 패턴(58건)을 BD-PREFIX-LEN으로 통일할지
+- 레거시 265건 중 SAM에 없는 항목 → 신규 생성 범위
+- 매핑 애매한 항목 → 사업부 확인 목록
+
+---
+
+## 2. options 확장
+
+### 2-1. 확장 스키마
+
+**기존 키 (보존)**:
+```json
+{
+ "source": "bending_item_seeder",
+ "lot_managed": true,
+ "consumption_method": "auto",
+ "production_source": "self_produced",
+ "input_tracking": true,
+ "prefix": "RS",
+ "length_code": "30",
+ "length_mm": 3000
+}
+```
+
+**추가 키**:
+```json
+{
+ // --- 기본 속성 ---
+ "item_name": "마감재", // 품명 (레거시 itemName — items.name과 별도 보존)
+ "item_sep": "스크린", // 대분류 (스크린/철재)
+ "item_bending": "가이드레일", // 중분류 (가이드레일/케이스/하단마감재/마구리/L-BAR)
+ "item_spec": "120*70", // 규격
+ "material": "SUS 1.2T", // 재질
+ "model_name": "KSS01", // 모델명
+ "model_UA": "인정", // 인정여부
+ "search_keyword": "", // 검색 키워드
+ "rail_width": 70, // 레일폭
+ "registration_date": "2025-07-19", // 등록일
+ "author": "개발자", // 작성자
+ "memo": "", // 비고
+ "parent_num": null, // 부모 절곡품 참조 (조합 관계)
+
+ // --- 케이스 전용 ---
+ "exit_direction": "후면 점검구", // 점검구 방향 (후면/양면/밑면)
+ "front_bottom_width": 50, // 전면부 밑 치수 (mm)
+ "box_width": 650, // 케이스 너비 (mm)
+ "box_height": 550, // 케이스 높이 (mm)
+
+ // --- 전개도 데이터 (인덱스 기반 객체 배열) ---
+ "bendingData": [
+ { "no": 1, "input": 10, "rate": "", "sum": 10, "color": true, "aAngle": false },
+ { "no": 2, "input": 11, "rate": "", "sum": 21, "color": false, "aAngle": false }
+ // ... 열 단위로 모든 속성을 하나의 객체에 통합
+ ],
+
+ // --- 이미지/추적 ---
+ "image_path": "", // 전개도 이미지 경로
+ "legacy_bending_num": null // 레거시 추적용
+}
+```
+
+### 2-2. 마이그레이션 순서
+
+```
+1단계: 기존 148건 prefix/length 채우기
+ → BD-PREFIX-LEN 패턴에서 자동 추출
+
+2단계: 레거시 속성 입력
+ → 매핑 테이블 기반 item_sep/item_bending/material 등
+
+3단계: 전개도 JSON 입력
+ → 레거시 inputList/bendingrateList/sumList/colorList
+```
+
+### 2-3. artisan command
+
+```bash
+# 1단계
+php artisan bending:fill-options --dry-run # 미리보기
+php artisan bending:fill-options # 실행
+
+# 2단계
+php artisan bending:import-legacy --dry-run
+php artisan bending:import-legacy
+
+# 3단계 (2단계에 포함 가능)
+```
+
+---
+
+## 3. 회귀 테스트 (필수)
+
+| 테스트 | 확인 내용 | 판정 기준 |
+|--------|----------|----------|
+| BendingInfoBuilder | 견적 BOM 계산 결과 | 변경 전/후 동일 |
+| PrefixResolver | BD 코드 자동 결정 | 변경 전/후 동일 |
+| 작업지시서 절곡 섹션 | GuideRailSection 렌더링 | 정상 표시 |
+| 절곡 검사 | inspection-config API | 정상 응답 |
+| 견적→수주→작업지시 | 전체 흐름 1건 | 오류 없음 |
+
+---
+
+## 4. 산출물
+
+- [ ] 매핑 테이블 (레거시 num ↔ SAM item_id)
+- [ ] artisan command (bending:fill-options, bending:import-legacy)
+ - [ ] 회귀 테스트 결과
diff --git a/dev/dev_plans/bending-management/step2-API.md b/dev/dev_plans/bending-management/step2-API.md
new file mode 100644
index 0000000..30a6cbe
--- /dev/null
+++ b/dev/dev_plans/bending-management/step2-API.md
@@ -0,0 +1,525 @@
+# Step 2: API 엔드포인트
+
+> **프로젝트**: API (`sam/api`)
+> **선행 조건**: Step 1 완료
+> **참조**: `standards/api-rules.md`, `standards/options-column-policy.md`, `rules/item-policy.md`
+
+---
+
+## 1. 설계 방침
+
+### 기존 규칙 준수 사항
+
+| 규칙 | 적용 |
+|------|------|
+| URL prefix | `/api/v1/` |
+| 응답 형식 | `ApiResponse::handle()` → `{success, message, data}` |
+| Controller | FormRequest 타입힌트 → Service 호출만 |
+| Service | `extends Service`, `tenantId()`, `apiUserId()` 사용 |
+| i18n 메시지 | `__('message.bending_item.created')` 패턴 |
+| 멀티테넌시 | `BelongsToTenant` 글로벌 스코프 |
+| Audit 로그 | `audit_logs` 테이블 자동 기록 |
+| SoftDeletes | 기본 적용 |
+| options | `'array'` 캐스트, `getOption()`/`setOption()` 헬퍼 |
+| Validation | FormRequest 클래스, 컨트롤러에서 직접 validate() 금지 |
+
+### 기존 Item 구조와의 관계
+
+```
+기존 구조:
+ ItemsController → ItemsService → items 테이블
+ item_type: FG(완제품), PT(부품), SM(부자재), RM(원자재), CS(소모품)
+ item_category: 'BENDING' (절곡품 구분)
+
+절곡품 API 방향:
+ → 기존 ItemsController 무변경
+ → 별도 BendingItemController 생성 (items 테이블을 item_category='BENDING'으로 필터)
+ → 절곡품 전용 필터/검색/전개도 데이터 관리
+```
+
+---
+
+## 2. 엔드포인트 설계
+
+### 2-1. 절곡품 기초관리 (개별 부품)
+
+| Method | Path | 설명 | 비고 |
+|--------|------|------|------|
+| GET | `/api/v1/bending-items` | 목록 (필터/검색/페이지네이션) | |
+| GET | `/api/v1/bending-items/filters` | 필터 옵션 (분류/재질/모델 distinct) | 캐시 10분 |
+| 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) | |
+| ~~이미지~~ | 기존 `ItemsFileController` 사용 | `field_key: 'bending_diagram'` | 별도 엔드포인트 불필요 |
+
+**필터 파라미터** (GET /api/v1/bending-items):
+```
+?item_sep=스크린 # 대분류
+&item_bending=가이드레일 # 중분류
+&material=SUS # 재질 (부분 매칭)
+&model_UA=인정 # 인정여부
+&search=KSS01 # 통합 검색 (이름/검색어/규격)
+&page=1&size=50 # 페이지네이션 (size — api-rules 기준)
+```
+
+### 2-2. 절곡품 모델 관리 (조합)
+
+| Method | Path | 설명 | 비고 |
+|--------|------|------|------|
+| GET | `/api/v1/guiderail-models` | 모델 목록 (타입별) | ?type=가이드레일 |
+| GET | `/api/v1/guiderail-models/{id}` | 모델 상세 (부품 조합 + 재질별 폭합) | |
+| POST | `/api/v1/guiderail-models` | 모델 등록 | |
+| PUT | `/api/v1/guiderail-models/{id}` | 모델 수정 | |
+| DELETE | `/api/v1/guiderail-models/{id}` | 모델 삭제 (soft delete) | |
+
+---
+
+## 3. 구현 파일 구조
+
+### Controller
+
+```
+app/Http/Controllers/Api/V1/
+├─ BendingItemController.php ← 신규
+└─ GuiderailModelController.php ← 신규
+```
+
+```php
+// BendingItemController.php
+class BendingItemController extends Controller
+{
+ public function __construct(private BendingItemService $service) {}
+
+ public function index(BendingItemIndexRequest $request)
+ {
+ return ApiResponse::handle(fn() =>
+ $this->service->list($request->validated())
+ );
+ }
+
+ public function store(BendingItemStoreRequest $request)
+ {
+ return ApiResponse::handle(fn() =>
+ $this->service->create($request->validated()),
+ __('message.bending_item.created')
+ );
+ }
+
+ public function show(int $id)
+ {
+ return ApiResponse::handle(fn() =>
+ $this->service->find($id)
+ );
+ }
+
+ public function update(BendingItemUpdateRequest $request, int $id)
+ {
+ return ApiResponse::handle(fn() =>
+ $this->service->update($id, $request->validated()),
+ __('message.bending_item.updated')
+ );
+ }
+
+ public function destroy(int $id)
+ {
+ return ApiResponse::handle(fn() =>
+ $this->service->delete($id),
+ __('message.bending_item.deleted')
+ );
+ }
+}
+```
+
+### Service
+
+```
+app/Services/
+├─ BendingItemService.php ← 신규
+└─ GuiderailModelService.php ← 신규
+```
+
+```php
+// BendingItemService.php
+class BendingItemService extends Service
+{
+ public function list(array $params): LengthAwarePaginator
+ {
+ return Item::where('item_category', 'BENDING')
+ ->when($params['item_sep'] ?? null, fn($q, $v) =>
+ $q->where('options->item_sep', $v))
+ ->when($params['item_bending'] ?? null, fn($q, $v) =>
+ $q->where('options->item_bending', $v))
+ ->when($params['material'] ?? null, fn($q, $v) =>
+ $q->where('options->material', 'like', "%{$v}%"))
+ ->when($params['model_UA'] ?? null, fn($q, $v) =>
+ $q->where('options->model_UA', $v))
+ ->when($params['search'] ?? null, fn($q, $v) =>
+ $q->where(fn($q2) => $q2
+ ->where('name', 'like', "%{$v}%")
+ ->orWhere('options->search_keyword', 'like', "%{$v}%")
+ ->orWhere('options->item_spec', 'like', "%{$v}%")))
+ ->orderByDesc('id')
+ ->paginate($params['size'] ?? 50);
+ }
+
+ public function create(array $data): Item
+ {
+ $options = $this->buildOptions($data);
+ $item = Item::create([
+ 'tenant_id' => $this->tenantId(),
+ 'item_type' => 'PT',
+ 'item_category' => 'BENDING',
+ 'code' => $data['code'],
+ 'name' => $data['name'],
+ 'options' => $options,
+ 'created_by' => $this->apiUserId(),
+ ]);
+ // audit log 자동 기록
+ return $item;
+ }
+
+ public function update(int $id, array $data): Item
+ {
+ $item = Item::findOrFail($id);
+ // setOption()으로 개별 키 업데이트 (기존 키 보존)
+ foreach ($data as $key => $value) {
+ if (in_array($key, ['code', 'name'])) {
+ $item->$key = $value;
+ } else {
+ $item->setOption($key, $value);
+ }
+ }
+ $item->updated_by = $this->apiUserId();
+ $item->save();
+ return $item;
+ }
+
+ private function buildOptions(array $data): array
+ {
+ $options = [];
+ $optionKeys = [
+ 'item_name', 'item_sep', 'item_bending', 'item_spec',
+ 'material', 'model_name', 'model_UA', 'search_keyword',
+ 'rail_width', 'registration_date', 'author', 'memo',
+ 'parent_num', 'exit_direction', 'front_bottom_width',
+ 'box_width', 'box_height', 'bendingData', 'image_path',
+ ];
+ foreach ($optionKeys as $key) {
+ if (isset($data[$key])) {
+ $options[$key] = $data[$key];
+ }
+ }
+ return $options ?: null;
+ }
+}
+```
+
+### FormRequest
+
+```
+app/Http/Requests/Api/V1/
+├─ BendingItemIndexRequest.php ← 신규
+├─ BendingItemStoreRequest.php ← 신규
+├─ BendingItemUpdateRequest.php ← 신규
+├─ GuiderailModelStoreRequest.php ← 신규
+└─ GuiderailModelUpdateRequest.php← 신규
+```
+
+```php
+// BendingItemStoreRequest.php
+class BendingItemStoreRequest extends FormRequest
+{
+ public function rules(): array
+ {
+ return [
+ 'code' => 'required|string|max:100|unique:items,code',
+ 'name' => 'required|string|max:200',
+ 'item_name' => 'required|string|max:50',
+ 'item_sep' => 'required|in:스크린,철재',
+ 'item_bending' => 'required|string',
+ 'material' => 'required|string',
+ 'model_UA' => 'nullable|in:인정,비인정',
+ 'item_spec' => 'nullable|string',
+ 'model_name' => 'nullable|string',
+ 'search_keyword' => 'nullable|string',
+ 'rail_width' => 'nullable|integer',
+ 'memo' => 'nullable|string',
+ // 케이스 전용
+ 'exit_direction' => 'nullable|string',
+ 'front_bottom_width' => 'nullable|integer',
+ 'box_width' => 'nullable|integer',
+ 'box_height' => 'nullable|integer',
+ // 전개도 데이터
+ 'bendingData' => 'nullable|array',
+ 'bendingData.*.no' => 'required|integer',
+ 'bendingData.*.input' => 'required|numeric',
+ 'bendingData.*.rate' => 'nullable|string',
+ 'bendingData.*.sum' => 'required|numeric',
+ 'bendingData.*.color' => 'required|boolean',
+ 'bendingData.*.aAngle' => 'required|boolean',
+ ];
+ }
+}
+```
+
+### Resource
+
+```
+app/Http/Resources/Api/V1/
+├─ BendingItemResource.php ← 신규
+└─ GuiderailModelResource.php ← 신규
+```
+
+```php
+// BendingItemResource.php
+class BendingItemResource extends JsonResource
+{
+ public function toArray($request): array
+ {
+ return [
+ 'id' => $this->id,
+ 'code' => $this->code,
+ 'name' => $this->name,
+ // options → 최상위로 풀어서 노출
+ 'item_name' => $this->getOption('item_name'),
+ 'item_sep' => $this->getOption('item_sep'),
+ 'item_bending' => $this->getOption('item_bending'),
+ 'item_spec' => $this->getOption('item_spec'),
+ 'material' => $this->getOption('material'),
+ 'model_name' => $this->getOption('model_name'),
+ 'model_UA' => $this->getOption('model_UA'),
+ 'search_keyword' => $this->getOption('search_keyword'),
+ 'rail_width' => $this->getOption('rail_width'),
+ 'registration_date' => $this->getOption('registration_date'),
+ 'author' => $this->getOption('author'),
+ 'memo' => $this->getOption('memo'),
+ // 케이스 전용
+ 'exit_direction' => $this->getOption('exit_direction'),
+ 'front_bottom_width' => $this->getOption('front_bottom_width'),
+ 'box_width' => $this->getOption('box_width'),
+ 'box_height' => $this->getOption('box_height'),
+ // 전개도
+ 'bendingData' => $this->getOption('bendingData'),
+ 'image_path' => $this->getOption('image_path'),
+ // 계산값
+ 'width_sum' => $this->getWidthSum(),
+ 'bend_count' => $this->getBendCount(),
+ 'has_image' => !empty($this->getOption('image_path')),
+ // 메타
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ];
+ }
+
+ private function getWidthSum(): ?int
+ {
+ $data = $this->getOption('bendingData', []);
+ if (empty($data)) return null;
+ return (int) end($data)['sum'] ?? null;
+ }
+
+ private function getBendCount(): int
+ {
+ $data = $this->getOption('bendingData', []);
+ return count(array_filter($data, fn($d) => ($d['rate'] ?? '') !== ''));
+ }
+}
+```
+
+### 라우트
+
+```php
+// routes/api.php (v1 그룹 내부에 추가)
+Route::prefix('v1')->middleware(['auth:sanctum'])->group(function () {
+ // ... 기존 라우트 유지 ...
+
+ // 절곡품 기초관리
+ Route::apiResource('bending-items', BendingItemController::class);
+ Route::get('bending-items/filters', [BendingItemController::class, 'filters']);
+ Route::post('bending-items/{id}/image', [BendingItemController::class, 'uploadImage']);
+ Route::delete('bending-items/{id}/image', [BendingItemController::class, 'deleteImage']);
+
+ // 절곡품 모델 (가이드레일 조합)
+ Route::apiResource('guiderail-models', GuiderailModelController::class);
+});
+```
+
+---
+
+## 4. 응답 형식
+
+### 목록 응답 (GET /api/v1/bending-items)
+
+```json
+{
+ "success": true,
+ "message": null,
+ "data": {
+ "data": [
+ {
+ "id": 123,
+ "code": "BD-가이드레일-KSS01-SUS-120*70",
+ "name": "가이드레일 KSS01 SUS 120*70",
+ "item_name": "마감재",
+ "item_sep": "스크린",
+ "item_bending": "가이드레일",
+ "item_spec": "120*70",
+ "material": "SUS 1.2T",
+ "model_name": "KSS01",
+ "model_UA": "인정",
+ "width_sum": 203,
+ "bend_count": 3,
+ "has_image": true
+ }
+ ],
+ "current_page": 1,
+ "total": 170,
+ "per_page": 50
+ }
+}
+```
+
+### 모델 상세 응답 (GET /api/v1/guiderail-models/{id})
+
+```json
+{
+ "success": true,
+ "message": null,
+ "data": {
+ "id": 1,
+ "model_name": "KSS01",
+ "check_type": "벽면형",
+ "rail_width": 70,
+ "rail_length": 120,
+ "finishing_type": "SUS마감",
+ "item_sep": "스크린",
+ "model_UA": "인정",
+ "components": [
+ {
+ "order": 1,
+ "name": "1번(마감재)",
+ "material": "SUS 1.2T",
+ "qty": 2,
+ "bending_item_id": 100,
+ "sum_total": 203,
+ "bendingData": [...]
+ }
+ ],
+ "material_summary": {
+ "SUS 1.2T": 406,
+ "EGI 1.55T": 398
+ }
+ }
+}
+```
+
+---
+
+## 5. 이미지 처리 (Cloudflare R2)
+
+### 기존 파일 시스템 구조
+
+SAM API는 **Cloudflare R2** (S3 호환)로 파일을 관리한다. 절곡품 이미지도 동일한 구조를 따른다.
+
+```
+기존 구조:
+ FileStorageService.php → Storage::disk('r2')->put()
+ FileStorageController → POST /api/v1/files/upload (임시)
+ ItemsFileController → POST /api/v1/items/{id}/files (품목 전용)
+ File 모델 → files 테이블 (메타데이터)
+
+경로 패턴:
+ 임시: {tenant_id}/temp/{year}/{month}/{stored_name}
+ 확정: {tenant_id}/items/{year}/{month}/{stored_name}
+```
+
+### 절곡품 이미지 업로드 방안
+
+**기존 `ItemsFileController` 재사용** (별도 이미지 컨트롤러 불필요):
+
+```php
+// 이미 존재하는 엔드포인트 활용
+POST /api/v1/items/{id}/files ← 절곡품 이미지 업로드
+GET /api/v1/items/{id}/files ← 이미지 목록
+DELETE /api/v1/items/{id}/files/{fileId} ← 이미지 삭제
+
+// field_key로 절곡품 이미지 구분
+field_key: 'bending_diagram' ← 전개도 이미지
+```
+
+### R2 설정 (이미 구성됨)
+
+```php
+// config/filesystems.php
+'r2' => [
+ 'driver' => 's3',
+ 'key' => env('R2_ACCESS_KEY_ID'),
+ 'secret' => env('R2_SECRET_ACCESS_KEY'),
+ 'region' => 'auto',
+ 'bucket' => 'sam',
+ 'endpoint' => env('R2_ENDPOINT'),
+ 'use_path_style_endpoint' => true,
+],
+```
+
+### 이미지 조회
+
+```php
+// File 모델의 download() 메서드로 스트리밍
+GET /api/v1/files/{id}/view ← 인라인 표시 (브라우저)
+GET /api/v1/files/{id}/download ← 다운로드
+```
+
+### 주의사항
+
+- ❌ 별도 이미지 엔드포인트 생성 불필요 — `ItemsFileController` 재사용
+- ❌ 로컬 `storage/app/public/bending/` 직접 저장 금지 — R2 사용
+- ✅ `field_key: 'bending_diagram'`으로 전개도 이미지 식별
+- ✅ `files` 테이블에 메타데이터 자동 관리 (tenant_id, file_path, mime_type 등)
+- ✅ options에는 `image_path` 대신 `file_id` 참조 또는 `field_key`로 조회
+
+---
+
+## 6. options 상수 정의
+
+```php
+// Item 모델에 추가 (또는 별도 상수 클래스)
+class Item extends Model
+{
+ // 절곡품 options 키 상수
+ const OPTION_ITEM_NAME = 'item_name';
+ const OPTION_ITEM_SEP = 'item_sep';
+ const OPTION_ITEM_BENDING = 'item_bending';
+ const OPTION_ITEM_SPEC = 'item_spec';
+ const OPTION_MATERIAL = 'material';
+ const OPTION_MODEL_NAME = 'model_name';
+ const OPTION_MODEL_UA = 'model_UA';
+ const OPTION_SEARCH_KEYWORD = 'search_keyword';
+ const OPTION_RAIL_WIDTH = 'rail_width';
+ const OPTION_BENDING_DATA = 'bendingData';
+ const OPTION_IMAGE_PATH = 'image_path';
+ const OPTION_EXIT_DIRECTION = 'exit_direction';
+ const OPTION_BOX_WIDTH = 'box_width';
+ const OPTION_BOX_HEIGHT = 'box_height';
+ const OPTION_FRONT_BOTTOM_WIDTH = 'front_bottom_width';
+ const OPTION_MEMO = 'memo';
+ const OPTION_AUTHOR = 'author';
+ const OPTION_REGISTRATION_DATE = 'registration_date';
+ const OPTION_PARENT_NUM = 'parent_num';
+}
+```
+
+---
+
+## 7. 주의사항
+
+- ✅ 기존 `ItemsController` / `ItemsService` 무변경
+- ✅ items 테이블 스키마 무변경 — options JSON만 활용
+- ✅ `item_category = 'BENDING'` 필터로 기존 items API 영향 없음
+- ✅ `setOption()`으로 개별 키 업데이트 — 기존 키 보존
+- ✅ `ApiResponse::handle()` 사용 — 직접 JSON 반환 금지
+- ✅ FormRequest에서만 유효성 검증 — 컨트롤러 validate() 금지
+- ✅ i18n 메시지 키 사용 — 직접 문자열 금지
+- ✅ SoftDeletes 적용
+- ⚠️ `BendingInfoBuilder` / `PrefixResolver` 무변경
diff --git a/dev/dev_plans/bending-management/step3-MNG화면.md b/dev/dev_plans/bending-management/step3-MNG화면.md
new file mode 100644
index 0000000..0be37b7
--- /dev/null
+++ b/dev/dev_plans/bending-management/step3-MNG화면.md
@@ -0,0 +1,524 @@
+# Step 3: MNG 관리 화면 (Blade + HTMX)
+
+> **프로젝트**: MNG (`sam/mng`)
+> **선행 조건**: Step 2 (API 엔드포인트) 완료
+> **참조**: 프로토타입 `SAM/work/절곡/`, MNG 기존 Blade 패턴
+
+---
+
+## 1. 메뉴 구조
+
+### 생산관리 하위에 추가
+
+```
+생산 관리 — DB menus 테이블 (동적 메뉴)
+├─ 품목기준 필드 관리 ✅
+├─ 견적수식 관리 ✅
+├─ 제품 관리 (준비중)
+├─ 자재 관리 (준비중)
+├─ BOM 관리 (준비중)
+├─ 카테고리 관리 (준비중)
+└─ 🆕 절곡품 관리 ← tinker로 menus 테이블에 추가
+ ├─ 기초관리 (/bending/base) ← 개별 부품 CRUD
+ └─ 절곡품 (/bending/products) ← 모델별 조합 관리
+```
+
+### 메뉴 등록 방법
+
+⚠️ **시더 실행 금지** — tinker로 수동 등록
+⚠️ **sidebar-static.blade.php 사용 안 함** — 현재 레이아웃은 동적 사이드바(`partials/sidebar.blade.php`) 사용
+
+MNG 사이드바는 DB `menus` 테이블 기반 동적 메뉴 시스템.
+``로 직접 호출 시 sanctum 인증 문제 발생.
+MNG 세션 인증으로 R2 파일을 스트리밍하는 프록시 라우트 필요.
+
+```php
+// FileViewController.php
+class FileViewController extends Controller
+{
+ public function show(int $id)
+ {
+ $file = File::findOrFail($id);
+ $stream = Storage::disk('r2')->readStream($file->file_path);
+
+ return response()->stream(function () use ($stream) {
+ fpassthru($stream);
+ if (is_resource($stream)) fclose($stream);
+ }, 200, [
+ 'Content-Type' => $file->mime_type,
+ 'Content-Disposition' => 'inline',
+ 'Cache-Control' => 'private, max-age=3600',
+ ]);
+ }
+}
+```
+
+**Blade에서 사용**:
+```html
+
+
+
+
+@if($fileId)
+
+@else
+