docs: [frontend] BOM Tree 시각화 React 구현 요청서 추가
- API 완료 상태 (GET /items/{id}/bom/tree)
- 재귀 트리 UI 명세 (유형별 뱃지, 펼침/접힘, 수량 표시)
- TypeScript 타입, 컴포넌트 구조, 렌더링 예시 코드 포함
This commit is contained in:
1
INDEX.md
1
INDEX.md
@@ -289,6 +289,7 @@ DB 도메인별:
|
||||
| [barobill-react-improvement-request.md](plans/barobill-react-improvement-request.md) | 바로빌 React 개선 요청서 (동기화 버튼, 인증서/잔액 표시, 계좌/카드 목록, Server Action 6개) |
|
||||
| [receiving-lot-auto-generate-request.md](plans/receiving-lot-auto-generate-request.md) | 입고등록 원자재로트번호 자동채번 적용 요청 (읽기전용 변경, API 자동생성) |
|
||||
| [stock-detail-inventory-adjustment-request.md](plans/stock-detail-inventory-adjustment-request.md) | 재고 조정 위치 이동 요청 (입고관리 → 재고 상세 화면) |
|
||||
| [bom-tree-visualization-request.md](plans/bom-tree-visualization-request.md) | BOM Tree 시각화 React 구현 요청 (API 완료, 재귀 트리 UI) |
|
||||
|
||||
### frontend/integration/ — 프론트엔드 개발 가이드
|
||||
|
||||
|
||||
292
plans/bom-tree-visualization-request.md
Normal file
292
plans/bom-tree-visualization-request.md
Normal file
@@ -0,0 +1,292 @@
|
||||
# BOM Tree 시각화 React 구현 요청
|
||||
|
||||
**날짜:** 2026-03-18
|
||||
**요청자:** R&D실 (백엔드)
|
||||
**대상:** React 프론트엔드
|
||||
**API 상태:** 구현 완료 (tree 엔드포인트 존재)
|
||||
|
||||
---
|
||||
|
||||
## 변경 요약
|
||||
|
||||
품목관리 또는 품목기준관리에서 **BOM(Bill of Materials) 트리를 시각적으로 표시**하는 UI를 추가한다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 배경
|
||||
|
||||
### 현재 상태
|
||||
|
||||
| 시스템 | BOM Tree UI | 비고 |
|
||||
|--------|:----------:|------|
|
||||
| MNG (Laravel) | ✅ 구현됨 | 3-panel: 검색 + 트리 + 상세 |
|
||||
| 서비스 (React) | ❌ 미구현 | API는 있으나 UI 없음 |
|
||||
|
||||
### MNG 참고 화면
|
||||
|
||||
```
|
||||
MNG 품목관리 (item-management)
|
||||
┌──────────┬──────────────────────────┬──────────────┐
|
||||
│ 품목 검색 │ BOM 트리 시각화 │ 품목 상세 │
|
||||
│ │ │ │
|
||||
│ 🔍 검색 │ ▼ [FG] 제품A │ 코드: P-001 │
|
||||
│ │ ├─ [PT] 부품B (x2) │ 이름: 제품A │
|
||||
│ · P-001 │ │ └─ [RM] SUS 철판 (x5)│ 유형: 완제품 │
|
||||
│ · P-002 │ ├─ [SM] 볼트 M8 (x10) │ │
|
||||
│ │ └─ [RM] EGI 판재 (x3) │ │
|
||||
└──────────┴──────────────────────────┴──────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 구현 위치
|
||||
|
||||
### 안 1: 품목 상세 화면에 BOM 탭 추가 (권장)
|
||||
|
||||
```
|
||||
품목관리 > 품목 상세 (/master-data/item-management/{id})
|
||||
├─ 기본정보 (기존)
|
||||
├─ BOM Tree 탭 ← 신규
|
||||
└─ 기타 탭
|
||||
```
|
||||
|
||||
### 안 2: 독립 BOM 뷰어 페이지
|
||||
|
||||
```
|
||||
기준정보 관리 > BOM 뷰어 (/master-data/bom-viewer)
|
||||
├─ 품목 검색 (좌측)
|
||||
└─ BOM Tree 시각화 (우측)
|
||||
```
|
||||
|
||||
> 구현 위치는 프론트엔드 개발자 판단에 맡김. 기존 화면 구조에 맞는 위치 선택.
|
||||
|
||||
---
|
||||
|
||||
## 3. BOM Tree UI 명세
|
||||
|
||||
### 3.1 트리 노드 구조
|
||||
|
||||
```
|
||||
▼ [FG] P-001 | 제품A x1
|
||||
├─ ▼ [PT] PT-001 | 가이드레일 조립품 x2
|
||||
│ ├─ [RM] 20000 | SUS1.2*1219*2438 x5
|
||||
│ ├─ [SM] 80067 | 가스켓쫄대(삼각) x10
|
||||
│ └─ [SM] 80061 | 8인치후렌지 x2
|
||||
├─ [RM] 30000 | EGI1.2*1219*2438 x3
|
||||
└─ [SM] 00043 | 불연지퍼 x20
|
||||
```
|
||||
|
||||
### 3.2 노드 요소
|
||||
|
||||
| 요소 | 설명 |
|
||||
|------|------|
|
||||
| ▼/▶ | 펼침/접힘 토글 (자식 있을 때만) |
|
||||
| 유형 뱃지 | `[FG]` `[PT]` `[RM]` `[SM]` `[CS]` — 색상 구분 |
|
||||
| 코드 | 품목코드 (monospace) |
|
||||
| 품목명 | 품목 이름 |
|
||||
| 수량 | `x2`, `x5` — 부모 대비 필요 수량 |
|
||||
|
||||
### 3.3 유형별 뱃지 색상
|
||||
|
||||
| 유형 | 코드 | 색상 | 설명 |
|
||||
|------|------|------|------|
|
||||
| 완제품 | FG | 🔵 blue | 최상위 제품 |
|
||||
| 부품 | PT | 🟢 green | 조립 부품 (자식 가질 수 있음) |
|
||||
| 원자재 | RM | 🟠 orange | 미가공 원자재 (leaf) |
|
||||
| 부자재 | SM | 🟣 purple | 부자재 (leaf) |
|
||||
| 소모품 | CS | ⚪ gray | 소모품 (leaf) |
|
||||
|
||||
### 3.4 인터랙션
|
||||
|
||||
| 동작 | 설명 |
|
||||
|------|------|
|
||||
| 노드 펼침/접힘 | 화살표 클릭 시 자식 노드 토글 |
|
||||
| 전체 펼침 | 버튼 클릭 시 모든 노드 펼침 |
|
||||
| 전체 접힘 | 버튼 클릭 시 루트만 표시 |
|
||||
| 노드 클릭 | (선택) 해당 품목 상세 정보 표시 또는 품목 상세 페이지 이동 |
|
||||
|
||||
---
|
||||
|
||||
## 4. API 스펙 (구현 완료)
|
||||
|
||||
### 4.1 Items BOM Tree
|
||||
|
||||
```
|
||||
GET /api/v1/items/{id}/bom/tree
|
||||
```
|
||||
|
||||
**응답:**
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": 100,
|
||||
"code": "P-001",
|
||||
"name": "제품A",
|
||||
"item_type": "FG",
|
||||
"specification": "...",
|
||||
"unit": "EA",
|
||||
"quantity": 1,
|
||||
"depth": 0,
|
||||
"children": [
|
||||
{
|
||||
"id": 200,
|
||||
"code": "PT-001",
|
||||
"name": "가이드레일 조립품",
|
||||
"item_type": "PT",
|
||||
"quantity": 2,
|
||||
"depth": 1,
|
||||
"children": [
|
||||
{
|
||||
"id": 300,
|
||||
"code": "20000",
|
||||
"name": "SUS1.2*1219*2438",
|
||||
"item_type": "RM",
|
||||
"quantity": 5,
|
||||
"depth": 2,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 400,
|
||||
"code": "00043",
|
||||
"name": "불연지퍼",
|
||||
"item_type": "SM",
|
||||
"quantity": 20,
|
||||
"depth": 1,
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Products BOM Tree (제품 기반)
|
||||
|
||||
```
|
||||
GET /api/v1/products/{id}/bom
|
||||
```
|
||||
|
||||
**응답 구조 동일** — `type` 필드가 `PRODUCT` 또는 `MATERIAL`로 구분.
|
||||
|
||||
### 4.3 BOM Flat List (참고)
|
||||
|
||||
```
|
||||
GET /api/v1/items/{id}/bom → 1단계 자식만 (flat)
|
||||
GET /api/v1/items/{id}/bom/tree → 전체 계층 (recursive)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. TypeScript 타입
|
||||
|
||||
```typescript
|
||||
interface BomTreeNode {
|
||||
id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
item_type: 'FG' | 'PT' | 'RM' | 'SM' | 'CS';
|
||||
specification?: string;
|
||||
unit?: string;
|
||||
quantity: number;
|
||||
depth: number;
|
||||
children: BomTreeNode[];
|
||||
}
|
||||
|
||||
// 유형별 뱃지 색상 매핑
|
||||
const ITEM_TYPE_COLORS: Record<string, string> = {
|
||||
FG: 'bg-blue-100 text-blue-800',
|
||||
PT: 'bg-green-100 text-green-800',
|
||||
RM: 'bg-orange-100 text-orange-800',
|
||||
SM: 'bg-purple-100 text-purple-800',
|
||||
CS: 'bg-gray-100 text-gray-800',
|
||||
};
|
||||
|
||||
const ITEM_TYPE_LABELS: Record<string, string> = {
|
||||
FG: '완제품', PT: '부품', RM: '원자재', SM: '부자재', CS: '소모품',
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 컴포넌트 구조 제안
|
||||
|
||||
```
|
||||
BomTreeViewer/
|
||||
├─ BomTreeViewer.tsx # 메인 컨테이너 (API 호출 + 상태 관리)
|
||||
├─ BomTreeNode.tsx # 개별 노드 (재귀 렌더링)
|
||||
├─ BomTreeToolbar.tsx # 전체 펼침/접힘 버튼
|
||||
└─ types.ts # BomTreeNode 타입
|
||||
```
|
||||
|
||||
### 재귀 렌더링 핵심
|
||||
|
||||
```tsx
|
||||
function BomTreeNode({ node, level = 0 }: { node: BomTreeNode; level?: number }) {
|
||||
const [isOpen, setIsOpen] = useState(level < 2); // 2단계까지 기본 펼침
|
||||
const hasChildren = node.children.length > 0;
|
||||
|
||||
return (
|
||||
<div style={{ marginLeft: level * 24 }}>
|
||||
<div className="flex items-center gap-2 py-1 hover:bg-gray-50 rounded">
|
||||
{/* 펼침/접힘 */}
|
||||
{hasChildren ? (
|
||||
<button onClick={() => setIsOpen(!isOpen)}>
|
||||
{isOpen ? '▼' : '▶'}
|
||||
</button>
|
||||
) : <span className="w-4" />}
|
||||
|
||||
{/* 유형 뱃지 */}
|
||||
<span className={`text-xs px-1.5 py-0.5 rounded ${ITEM_TYPE_COLORS[node.item_type]}`}>
|
||||
{node.item_type}
|
||||
</span>
|
||||
|
||||
{/* 코드 + 이름 */}
|
||||
<span className="font-mono text-sm text-gray-500">{node.code}</span>
|
||||
<span className="text-sm">{node.name}</span>
|
||||
|
||||
{/* 수량 */}
|
||||
<span className="text-sm text-blue-600 ml-auto">x{node.quantity}</span>
|
||||
</div>
|
||||
|
||||
{/* 재귀: 자식 노드 */}
|
||||
{isOpen && hasChildren && node.children.map(child => (
|
||||
<BomTreeNode key={child.id} node={child} level={level + 1} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Server Action 예시
|
||||
|
||||
```typescript
|
||||
// actions.ts
|
||||
export async function getBomTree(itemId: number) {
|
||||
return fetchApi(`/items/${itemId}/bom/tree`);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 작업 체크리스트
|
||||
|
||||
- [ ] `BomTreeViewer` 컴포넌트 생성 (재귀 트리 렌더링)
|
||||
- [ ] 유형별 뱃지 색상 적용 (FG/PT/RM/SM/CS)
|
||||
- [ ] 펼침/접힘 토글 구현
|
||||
- [ ] 전체 펼침/접힘 버튼
|
||||
- [ ] `GET /api/v1/items/{id}/bom/tree` 연동
|
||||
- [ ] 품목 상세 또는 독립 페이지에 배치
|
||||
- [ ] (선택) 노드 클릭 시 품목 상세 이동
|
||||
|
||||
---
|
||||
|
||||
## 참고
|
||||
|
||||
- MNG BOM Tree 구현: `mng/resources/views/item-management/index.blade.php` (라인 248-316)
|
||||
- API Tree 빌더: `api/app/Services/Products/ProductComponentResolver.php`
|
||||
- Items BOM API: `api/app/Http/Controllers/Api/V1/ItemsBomController.php`
|
||||
Reference in New Issue
Block a user