From b41da3261c9b08f4991997d9ade2d9e4e34759c5 Mon Sep 17 00:00:00 2001 From: dohyeons Date: Fri, 17 Oct 2025 14:05:54 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=BC=EB=93=9C=203d=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=20md=20=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YARD_MANAGEMENT_3D_PLAN.md | 925 +++++++++++++++++++++++++++++++++++++ 1 file changed, 925 insertions(+) create mode 100644 YARD_MANAGEMENT_3D_PLAN.md diff --git a/YARD_MANAGEMENT_3D_PLAN.md b/YARD_MANAGEMENT_3D_PLAN.md new file mode 100644 index 00000000..49938406 --- /dev/null +++ b/YARD_MANAGEMENT_3D_PLAN.md @@ -0,0 +1,925 @@ +# 야드 관리 3D 기능 구현 계획서 + +## 1. 기능 개요 + +### 목적 + +대시보드에서 야드(Yard)의 자재 배치 상태를 3D로 시각화하고 관리하는 위젯 + +### 주요 특징 + +- 각 대시보드는 하나의 야드(창고 내부 상태)를 나타냄 +- 3D 공간에서 자재를 직접 배치 및 이동 가능 +- 배치된 자재 클릭 시 상세 정보 표시 +- 여러 야드 레이아웃을 저장하고 선택 가능 + +--- + +## 2. 데이터베이스 설계 + +### 2.1. yard_layout 테이블 + +야드 레이아웃 정보 저장 + +```sql +CREATE TABLE yard_layout ( + id SERIAL PRIMARY KEY, + name VARCHAR(100) NOT NULL, -- 야드 이름 (예: "A구역", "1번 야드") + description TEXT, -- 설명 + created_by VARCHAR(50), -- 생성자 + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); +``` + +### 2.2. yard_material_placement 테이블 + +야드 내 자재 배치 정보 (외부 자재 데이터 참조) + +```sql +CREATE TABLE yard_material_placement ( + id SERIAL PRIMARY KEY, + yard_layout_id INTEGER REFERENCES yard_layout(id) ON DELETE CASCADE, + + -- 외부 자재 참조 (API로 받아올 데이터) + external_material_id VARCHAR(100) NOT NULL, -- 외부 시스템 자재 ID + material_code VARCHAR(50) NOT NULL, -- 자재 코드 (캐시) + material_name VARCHAR(100) NOT NULL, -- 자재 이름 (캐시) + quantity INTEGER NOT NULL DEFAULT 1, -- 수량 (캐시) + unit VARCHAR(20) DEFAULT 'EA', -- 단위 (캐시) + + -- 3D 위치 정보 + position_x NUMERIC(10, 2) NOT NULL DEFAULT 0, -- X 좌표 + position_y NUMERIC(10, 2) NOT NULL DEFAULT 0, -- Y 좌표 (높이) + position_z NUMERIC(10, 2) NOT NULL DEFAULT 0, -- Z 좌표 + + -- 3D 크기 정보 + size_x NUMERIC(10, 2) NOT NULL DEFAULT 5, -- 너비 + size_y NUMERIC(10, 2) NOT NULL DEFAULT 5, -- 높이 + size_z NUMERIC(10, 2) NOT NULL DEFAULT 5, -- 깊이 + + -- 외관 정보 + color VARCHAR(7) DEFAULT '#3b82f6', -- 색상 (HEX) + + -- 추가 정보 + status VARCHAR(20) DEFAULT 'normal', -- 상태 (normal, alert, warning) + memo TEXT, -- 메모 + + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 외부 자재 ID와 야드 레이아웃의 조합은 유니크해야 함 (중복 배치 방지) +CREATE UNIQUE INDEX idx_yard_material_unique + ON yard_material_placement(yard_layout_id, external_material_id); +``` + +### 2.3. temp_material_master 테이블 (임시 자재 마스터) + +외부 API를 받기 전까지 사용할 임시 자재 데이터 + +```sql +CREATE TABLE temp_material_master ( + id SERIAL PRIMARY KEY, + material_code VARCHAR(50) UNIQUE NOT NULL, -- 자재 코드 + material_name VARCHAR(100) NOT NULL, -- 자재 이름 + category VARCHAR(50), -- 카테고리 + unit VARCHAR(20) DEFAULT 'EA', -- 기본 단위 + default_color VARCHAR(7) DEFAULT '#3b82f6', -- 기본 색상 + description TEXT, -- 설명 + is_active BOOLEAN DEFAULT true, -- 사용 여부 + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 임시 자재 마스터 샘플 데이터 +INSERT INTO temp_material_master (material_code, material_name, category, unit, default_color, description) VALUES +('MAT-STEEL-001', '철판 A타입 (1200x2400)', '철강', 'EA', '#ef4444', '두께 10mm 철판'), +('MAT-STEEL-002', '철판 B타입 (1000x2000)', '철강', 'EA', '#dc2626', '두께 8mm 철판'), +('MAT-PIPE-001', '강관 파이프 (Φ100)', '파이프', 'EA', '#10b981', '길이 6m'), +('MAT-PIPE-002', '강관 파이프 (Φ150)', '파이프', 'EA', '#059669', '길이 6m'), +('MAT-BOLT-001', '볼트 세트 M12', '부품', 'BOX', '#f59e0b', '100개/박스'), +('MAT-BOLT-002', '볼트 세트 M16', '부품', 'BOX', '#d97706', '100개/박스'), +('MAT-ANGLE-001', '앵글 (75x75x6)', '형강', 'EA', '#8b5cf6', '길이 6m'), +('MAT-ANGLE-002', '앵글 (100x100x10)', '형강', 'EA', '#7c3aed', '길이 6m'), +('MAT-CHANNEL-001', '채널 (100x50x5)', '형강', 'EA', '#06b6d4', '길이 6m'), +('MAT-WIRE-001', '와이어 로프 (Φ12)', '케이블', 'M', '#ec4899', '롤 단위'); +``` + +### 2.4. 초기 데이터 마이그레이션 스크립트 + +```sql +-- 샘플 야드 레이아웃 +INSERT INTO yard_layout (name, description, created_by) VALUES +('A구역', '메인 야드 A구역', 'admin'), +('B구역', '메인 야드 B구역', 'admin'), +('C구역', '보조 야드 C구역', 'admin'); + +-- 샘플 자재 배치 (A구역) - 임시 자재 마스터 참조 +INSERT INTO yard_material_placement (yard_layout_id, external_material_id, material_code, material_name, + quantity, unit, position_x, position_y, position_z, size_x, size_y, size_z, color, status) VALUES +(1, 'TEMP-1', 'MAT-STEEL-001', '철판 A타입 (1200x2400)', 50, 'EA', 10, 0, 10, 8, 4, 8, '#ef4444', 'normal'), +(1, 'TEMP-2', 'MAT-STEEL-002', '철판 B타입 (1000x2000)', 30, 'EA', 25, 0, 10, 8, 4, 8, '#dc2626', 'normal'), +(1, 'TEMP-3', 'MAT-PIPE-001', '강관 파이프 (Φ100)', 100, 'EA', 40, 0, 10, 6, 6, 6, '#10b981', 'normal'), +(1, 'TEMP-4', 'MAT-BOLT-001', '볼트 세트 M12', 500, 'BOX', 55, 0, 10, 4, 4, 4, '#f59e0b', 'warning'); +``` + +### 2.5. 외부 자재 API 연동 구조 + +**현재 (Phase 1)**: 임시 자재 마스터 사용 + +```typescript +// temp_material_master 테이블에서 조회 +GET / api / materials / temp; +``` + +**향후 (Phase 2)**: 외부 API 연동 + +```typescript +// 외부 시스템 자재 API +GET /api/external/materials +Response: [ + { + id: "EXT-12345", + code: "MAT-STEEL-001", + name: "철판 A타입", + quantity: 150, + unit: "EA", + location: "창고A-1", + ... + } +] +``` + +--- + +## 3. 백엔드 API 설계 + +### 3.1. YardLayoutService + +**경로**: `backend-node/src/services/YardLayoutService.ts` + +```typescript +- getAllLayouts(): 모든 야드 레이아웃 목록 조회 +- getLayoutById(id): 특정 야드 레이아웃 상세 조회 +- createLayout(data): 새 야드 레이아웃 생성 +- updateLayout(id, data): 야드 레이아웃 수정 (이름, 설명) +- deleteLayout(id): 야드 레이아웃 삭제 +- getPlacementsByLayoutId(layoutId): 특정 야드의 모든 배치 자재 조회 +- addMaterialPlacement(layoutId, placementData): 야드에 자재 배치 추가 +- updatePlacement(placementId, data): 배치 정보 수정 (위치, 크기, 색상, 메모만) +- removePlacement(placementId): 배치 해제 (자재는 삭제되지 않음) +- batchUpdatePlacements(layoutId, placements[]): 여러 배치 일괄 업데이트 +``` + +**중요**: 자재 마스터 데이터(코드, 이름, 수량, 단위)는 읽기 전용 + +### 3.2. YardLayoutController + +**경로**: `backend-node/src/controllers/YardLayoutController.ts` + +- GET `/api/yard-layouts`: 모든 레이아웃 목록 +- GET `/api/yard-layouts/:id`: 특정 레이아웃 상세 +- POST `/api/yard-layouts`: 새 레이아웃 생성 +- PUT `/api/yard-layouts/:id`: 레이아웃 수정 (이름, 설명만) +- DELETE `/api/yard-layouts/:id`: 레이아웃 삭제 +- GET `/api/yard-layouts/:id/placements`: 레이아웃의 배치 자재 목록 +- POST `/api/yard-layouts/:id/placements`: 자재 배치 추가 +- PUT `/api/yard-placements/:id`: 배치 정보 수정 (위치, 크기, 색상, 메모만) +- DELETE `/api/yard-placements/:id`: 배치 해제 +- PUT `/api/yard-layouts/:id/placements/batch`: 배치 일괄 업데이트 + +### 3.3. MaterialController (임시 자재 조회용) + +**경로**: `backend-node/src/controllers/MaterialController.ts` + +- GET `/api/materials/temp`: 임시 자재 마스터 목록 조회 (검색, 필터링) +- GET `/api/materials/temp/:code`: 특정 자재 상세 조회 + +**향후**: 외부 API 프록시로 변경 예정 + +### 3.4. Routes + +**경로**: `backend-node/src/routes/yardLayoutRoutes.ts` + `materialRoutes.ts` + +--- + +## 4. 프론트엔드 컴포넌트 설계 + +### 4.1. YardManagement3DWidget (메인 위젯) + +**경로**: `frontend/components/admin/dashboard/widgets/YardManagement3DWidget.tsx` + +**주요 기능**: + +1. 야드 레이아웃 선택/생성 모드 전환 +2. 3D 캔버스 렌더링 +3. 자재 배치 및 이동 인터랙션 +4. 선택된 자재 정보 패널 표시 + +**상태 관리**: + +```typescript +- mode: 'select' | 'edit' | 'create' // 현재 모드 +- selectedLayoutId: number | null // 선택된 레이아웃 ID +- layoutData: YardLayout | null // 현재 레이아웃 데이터 +- materials: YardMaterial[] // 배치된 자재 목록 +- selectedMaterialId: string | null // 선택된 자재 ID +- isDragging: boolean // 드래그 중 여부 +``` + +### 4.2. YardLayoutSelector (레이아웃 선택) + +**경로**: `frontend/components/admin/dashboard/widgets/YardLayoutSelector.tsx` + +- 저장된 야드 레이아웃 목록 표시 +- 레이아웃 선택 기능 +- 새 레이아웃 생성 버튼 + +### 4.3. YardLayoutCreator (레이아웃 생성) + +**경로**: `frontend/components/admin/dashboard/widgets/YardLayoutCreator.tsx` + +- 야드 이름, 설명 입력 +- 야드 크기 설정 (width, depth, height) +- 그리드 크기 설정 + +### 4.4. Yard3DCanvas (3D 캔버스) + +**경로**: `frontend/components/admin/dashboard/widgets/Yard3DCanvas.tsx` + +**기술 스택**: + +- React Three Fiber +- @react-three/drei (OrbitControls, Grid, Box) +- Three.js + +**주요 기능**: + +1. 야드 바닥 그리드 표시 +2. 자재 3D 박스 렌더링 +3. 자재 클릭 이벤트 처리 +4. 자재 드래그 앤 드롭 (위치 이동) +5. 카메라 컨트롤 (회전, 줌) + +### 4.5. MaterialInfoPanel (자재 정보 패널) + +**경로**: `frontend/components/admin/dashboard/widgets/MaterialInfoPanel.tsx` + +**읽기 전용 정보** (외부 자재 데이터): + +- 자재 코드 +- 자재 이름 +- 수량 +- 단위 +- 카테고리 + +**수정 가능 정보** (배치 데이터): + +- 3D 위치 (X, Y, Z) +- 3D 크기 (너비, 높이, 깊이) +- 색상 +- 메모 + +**기능**: + +- 배치 정보 수정 +- 배치 해제 (야드에서 자재 제거) + +### 4.6. MaterialLibrary (자재 라이브러리) + +**경로**: `frontend/components/admin/dashboard/widgets/MaterialLibrary.tsx` + +- 사용 가능한 자재 목록 표시 +- 자재 검색 기능 +- 자재를 3D 캔버스로 드래그하여 배치 +- 자재 마스터 데이터 조회 (기존 테이블 활용 가능) + +--- + +## 5. UI/UX 설계 + +### 5.1. 초기 화면 (선택/생성 모드) + +야드 레이아웃 목록을 테이블 형식으로 표시 + +``` +┌──────────────────────────────────────────────────────────────────────────┐ +│ 야드 관리 3D [+ 새 야드 생성] │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ [검색: ________________] [정렬: 최근순 ▼] │ +│ │ +│ ┌────────────────────────────────────────────────────────────────────┐ │ +│ │ 야드명 │ 설명 │ 배치 자재 │ 최종 수정 │ 작업 │ │ +│ ├────────────────────────────────────────────────────────────────────┤ │ +│ │ A구역 │ 메인 야드 A구역 │ 15개 │ 2025-01-15 14:30 │ ⋮ │ │ +│ │ │ │ │ │ │ │ +│ ├────────────────────────────────────────────────────────────────────┤ │ +│ │ B구역 │ 메인 야드 B구역 │ 8개 │ 2025-01-14 10:20 │ ⋮ │ │ +│ │ │ │ │ │ │ │ +│ ├────────────────────────────────────────────────────────────────────┤ │ +│ │ C구역 │ 보조 야드 C구역 │ 3개 │ 2025-01-10 09:15 │ ⋮ │ │ +│ │ │ │ │ │ │ │ +│ └────────────────────────────────────────────────────────────────────┘ │ +│ │ +│ 총 3개 [1] 2 3 4 5 > │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ + +작업 메뉴 (⋮ 클릭 시): +┌─────────────┐ +│ 편집 │ +│ 복제 │ +│ 삭제 │ +└─────────────┘ +``` + +### 5.2. 레이아웃 생성 모달 + +새 야드 레이아웃을 생성할 때 표시되는 모달 + +``` +┌─────────────────────────────────────────────────┐ +│ 새 야드 레이아웃 생성 [X] │ +├─────────────────────────────────────────────────┤ +│ │ +│ 야드 이름 * │ +│ [____________________________________] │ +│ │ +│ 설명 │ +│ [____________________________________] │ +│ [____________________________________] │ +│ │ +│ [취소] [생성] │ +└─────────────────────────────────────────────────┘ +``` + +### 5.3. 편집 모드 - 전체 레이아웃 + +야드 편집 화면의 전체 구성 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ A구역 [저장] [미리보기] [취소] │ +├───────────────────────────────────────┬─────────────────────────────────────┤ +│ │ 도구 패널 [최소화] │ +│ ├─────────────────────────────────────┤ +│ │ │ +│ │ 자재 라이브러리 │ +│ │ ───────────────────── │ +│ │ [검색: ____________] [카테고리 ▼] │ +│ │ │ +│ 3D 캔버스 │ ┌───────────────────────┐ │ +│ │ │ MAT-STEEL-001 │ │ +│ (야드 그리드 + 자재 배치) │ │ 철판 A타입 │ │ +│ │ │ 50 EA 재고 있음 │ │ +│ - 마우스 드래그: 카메라 회전 │ │ [배치] │ │ +│ - 휠: 줌 인/아웃 │ └───────────────────────┘ │ +│ - 자재 클릭: 선택 │ │ +│ - 자재 드래그: 이동 │ ┌───────────────────────┐ │ +│ │ │ MAT-STEEL-002 │ │ +│ │ │ 철판 B타입 │ │ +│ │ │ 30 EA 재고 있음 │ │ +│ │ │ [배치] │ │ +│ │ └───────────────────────┘ │ +│ │ │ +│ │ ┌───────────────────────┐ │ +│ │ │ MAT-PIPE-001 │ │ +│ │ │ 강관 파이프 │ │ +│ │ │ 100 EA 재고 있음 │ │ +│ │ │ [배치] │ │ +│ │ └───────────────────────┘ │ +│ │ │ +│ │ ... (스크롤 가능) │ +│ │ │ +├───────────────────────────────────────┴─────────────────────────────────────┤ +│ 자재 정보 │ +│ ───────────────── │ +│ 선택된 자재: MAT-STEEL-001 (철판 A타입) │ +│ │ +│ 기본 정보 (읽기 전용) │ +│ 자재 코드: MAT-STEEL-001 │ +│ 자재 이름: 철판 A타입 (1200x2400) │ +│ 수량: 50 EA │ +│ 카테고리: 철강 │ +│ │ +│ 배치 정보 (수정 가능) │ +│ 3D 위치 │ +│ X: [____10.00____] m Y: [____0.00____] m Z: [____10.00____] m │ +│ │ +│ 3D 크기 │ +│ 너비: [____8.00____] m 높이: [____4.00____] m 깊이: [____8.00____] m │ +│ │ +│ 외관 │ +│ 색상: [■ #ef4444] [색상 선택] │ +│ │ +│ 메모 │ +│ [_____________________________________________________________________] │ +│ │ +│ [배치 해제] [변경 적용] [초기화] │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 5.4. 3D 캔버스 상세 + +3D 캔버스 내부의 시각적 요소 + +``` +┌─────────────────────────────────────────────────┐ +│ 카메라 컨트롤 [리셋] │ +│ 회전: 45° | 기울기: 30° | 줌: 100% │ +├─────────────────────────────────────────────────┤ +│ Y (높이) │ +│ ↑ │ +│ │ │ +│ │ │ +│ │ ┌───────┐ (자재) │ +│ │ │ │ │ +│ Z (깊이) │ │ MAT-1 │ (선택됨) │ +│ ↗ │ │ │ │ +│ / └────┴───────┴──→ X (너비) │ +│ / │ +│ / ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │ +│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ (그리드) │ +│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ +│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ +│ │ │ │ │ │ │□│ │ │ │ │ ← MAT-2 │ +│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ +│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ +│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ │ +│ │ +│ 범례: │ +│ ■ 선택된 자재 □ 일반 자재 │ +│ ─ 그리드 라인 (5m 단위) │ +│ │ +│ 조작 가이드: │ +│ • 마우스 왼쪽 드래그: 카메라 회전 │ +│ • 마우스 휠: 줌 인/아웃 │ +│ • 자재 클릭: 선택 │ +│ • 선택된 자재 드래그: 위치 이동 │ +└─────────────────────────────────────────────────┘ +``` + +### 5.5. 자재 배치 플로우 + +자재를 배치하는 과정 + +``` +1. 자재 라이브러리에서 자재 선택 + ┌─────────────────┐ + │ MAT-STEEL-001 │ ← 클릭 + │ 철판 A타입 │ + │ [배치] │ + └─────────────────┘ + ↓ +2. 3D 캔버스에 자재가 임시로 표시됨 (투명) + ┌─────────────────┐ + │ 3D 캔버스 │ + │ │ + │ [반투명 박스] │ ← 마우스 커서 따라 이동 + │ │ + └─────────────────┘ + ↓ +3. 원하는 위치에 클릭하여 배치 + ┌─────────────────┐ + │ 3D 캔버스 │ + │ │ + │ [실제 박스] │ ← 배치 완료 + │ │ + └─────────────────┘ + ↓ +4. 자재 정보 패널에 자동으로 선택됨 + ┌─────────────────────────┐ + │ 자재 정보 패널 │ + │ ─────────────────── │ + │ 선택된 자재: │ + │ MAT-STEEL-001 │ + │ │ + │ 수량: 50 EA │ + │ 위치: X:10, Y:0, Z:10 │ + │ ... │ + └─────────────────────────┘ +``` + +### 5.6. 반응형 레이아웃 (모바일/태블릿) + +모바일에서는 패널을 접거나 탭으로 전환 + +``` +모바일 (세로 모드): +┌───────────────────────┐ +│ A구역 [저장] │ +├───────────────────────┤ +│ │ +│ 3D 캔버스 │ +│ (전체 화면) │ +│ │ +│ │ +├───────────────────────┤ +│ [자재 라이브러리] [정보]│ ← 탭 전환 +├───────────────────────┤ +│ 선택된 자재: │ +│ MAT-STEEL-001 │ +│ 수량: 50 EA │ +│ ... │ +└───────────────────────┘ + +태블릿 (가로 모드): +┌─────────────────────────────────────┐ +│ A구역 [저장] │ +├──────────────────┬──────────────────┤ +│ │ 자재 라이브러리 │ +│ 3D 캔버스 │ ────────────── │ +│ │ [검색: ______] │ +│ │ MAT-STEEL-001 │ +│ │ ... │ +├──────────────────┴──────────────────┤ +│ 선택된 자재: MAT-STEEL-001 │ +│ 수량: 50 EA | 위치: X:10, Z:10 │ +└─────────────────────────────────────┘ +``` + +--- + +## 6. 구현 단계 + +### Phase 1: 데이터베이스 및 백엔드 API + +1. 테이블 생성 스크립트 작성 +2. 마이그레이션 실행 +3. Service, Controller, Routes 구현 +4. API 테스트 + +### Phase 2: 야드 레이아웃 선택/생성 + +1. YardLayoutSelector 컴포넌트 구현 +2. YardLayoutCreator 컴포넌트 구현 +3. API 연동 +4. 레이아웃 CRUD 기능 테스트 + +### Phase 3: 3D 캔버스 기본 구조 + +1. Yard3DCanvas 컴포넌트 기본 구조 +2. 야드 바닥 그리드 렌더링 +3. 카메라 컨트롤 (OrbitControls) +4. 자재 3D 박스 렌더링 + +### Phase 4: 자재 배치 및 인터랙션 + +1. MaterialLibrary 컴포넌트 구현 +2. 자재 드래그 앤 드롭 배치 +3. 자재 클릭 선택 +4. 자재 위치 이동 (드래그) + +### Phase 5: 자재 정보 패널 및 편집 + +1. MaterialInfoPanel 컴포넌트 구현 +2. 자재 정보 표시 +3. 자재 정보 수정 (수량, 위치, 크기 등) +4. 자재 삭제 + +### Phase 6: 통합 및 최적화 + +1. YardManagement3DWidget 통합 +2. 상태 관리 최적화 +3. 성능 최적화 (대량 자재 렌더링) +4. 에러 처리 및 로딩 상태 +5. 모바일/반응형 대응 (선택사항) + +### Phase 7: 대시보드 위젯 등록 + +1. types.ts에 위젯 타입 추가 +2. DashboardTopMenu에 위젯 추가 +3. CanvasElement에 위젯 렌더링 추가 +4. 위젯 설정 모달 (레이아웃 선택) + +--- + +## 7. 기술적 고려사항 + +### 7.1. 3D 렌더링 최적화 + +- 자재 수가 많을 경우 인스턴싱 사용 +- LOD (Level of Detail) 적용 고려 +- 카메라 거리에 따른 렌더링 최적화 + +### 7.2. 드래그 앤 드롭 + +- 3D 공간에서의 레이캐스팅 +- 그리드 스냅 기능 +- 충돌 감지 (자재 간 겹침 방지) + +### 7.3. 상태 관리 + +- 자재 위치 변경 시 실시간 업데이트 +- Debounce를 사용한 API 호출 최적화 +- 낙관적 업데이트 (Optimistic Update) + +### 7.4. 데이터 동기화 + +- 여러 사용자가 동시에 편집하는 경우 충돌 처리 +- WebSocket을 통한 실시간 동기화 (선택사항) + +### 7.5. UI/UX 규칙 + +#### 이모지 사용 금지 + +#### 모달 사용 규칙 + +**`window.alert`, `window.confirm` 사용 금지** + +모든 알림, 확인, 에러 메시지는 Shadcn UI 모달 컴포넌트 사용: + +- **일반 알림**: `Dialog` 컴포넌트 +- **확인 필요**: `AlertDialog` 컴포넌트 +- **삭제/해제 확인**: `AlertDialog` (Destructive 스타일) +- **성공 메시지**: `Dialog` 또는 `Toast` +- **에러 메시지**: `Dialog` (Error 스타일) + +**예시**: + +```typescript +// 잘못된 방법 ❌ +window.alert("저장되었습니다"); +if (window.confirm("삭제하시겠습니까?")) { ... } + +// 올바른 방법 ✅ + + + + 배치 해제 + + 이 자재를 야드에서 제거하시겠습니까? + + + + 취소 + 확인 + + + +``` + +--- + +## 8. API 명세서 + +### 8.1. 야드 레이아웃 API + +#### GET /api/yard-layouts + +**설명**: 모든 야드 레이아웃 목록 조회 + +**응답**: + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "name": "A구역", + "description": "메인 야드 A구역", + "placement_count": 15, + "created_at": "2025-01-01T00:00:00Z" + } + ] +} +``` + +#### GET /api/yard-layouts/:id + +**설명**: 특정 야드 레이아웃 상세 조회 + +**응답**: + +```json +{ + "success": true, + "data": { + "id": 1, + "name": "A구역", + "description": "메인 야드 A구역", + "created_at": "2025-01-01T00:00:00Z" + } +} +``` + +#### POST /api/yard-layouts + +**설명**: 새 야드 레이아웃 생성 + +**요청**: + +```json +{ + "name": "D구역", + "description": "신규 야드" +} +``` + +#### PUT /api/yard-layouts/:id + +**설명**: 야드 레이아웃 수정 (이름, 설명만) + +**요청**: + +```json +{ + "name": "D구역 (수정)", + "description": "수정된 설명" +} +``` + +#### DELETE /api/yard-layouts/:id + +**설명**: 야드 레이아웃 삭제 + +### 8.2. 자재 배치 API + +#### GET /api/yard-layouts/:id/materials + +**설명**: 특정 야드의 모든 자재 조회 + +**응답**: + +```json +{ + "success": true, + "data": [ + { + "id": 1, + "material_code": "MAT-001", + "material_name": "철판 A타입", + "quantity": 50, + "unit": "EA", + "position_x": 10, + "position_y": 0, + "position_z": 10, + "size_x": 8, + "size_y": 4, + "size_z": 8, + "color": "#ef4444", + "status": "normal", + "memo": null + } + ] +} +``` + +#### POST /api/yard-layouts/:id/materials + +**설명**: 야드에 자재 추가 + +**요청**: + +```json +{ + "material_code": "MAT-005", + "material_name": "신규 자재", + "quantity": 10, + "unit": "EA", + "position_x": 20, + "position_y": 0, + "position_z": 20, + "size_x": 5, + "size_y": 5, + "size_z": 5, + "color": "#3b82f6" +} +``` + +#### PUT /api/yard-materials/:id + +**설명**: 자재 정보 수정 + +**요청**: + +```json +{ + "position_x": 25, + "position_z": 25, + "quantity": 55 +} +``` + +#### DELETE /api/yard-materials/:id + +**설명**: 자재 삭제 + +#### PUT /api/yard-layouts/:id/materials/batch + +**설명**: 여러 자재 일괄 업데이트 (드래그로 여러 자재 이동 시) + +**요청**: + +```json +{ + "materials": [ + { "id": 1, "position_x": 15, "position_z": 15 }, + { "id": 2, "position_x": 30, "position_z": 15 } + ] +} +``` + +--- + +## 9. 테스트 시나리오 + +### 9.1. 기본 기능 테스트 + +- [ ] 야드 레이아웃 목록 조회 +- [ ] 야드 레이아웃 생성 +- [ ] 야드 레이아웃 선택 +- [ ] 3D 캔버스 렌더링 +- [ ] 자재 목록 조회 및 표시 + +### 9.2. 자재 배치 테스트 + +- [ ] 자재 라이브러리에서 드래그하여 배치 +- [ ] 배치된 자재 클릭하여 선택 +- [ ] 선택된 자재 정보 패널 표시 +- [ ] 자재 드래그하여 위치 이동 +- [ ] 자재 정보 수정 (수량, 크기 등) +- [ ] 자재 삭제 + +### 9.3. 인터랙션 테스트 + +- [ ] 카메라 회전 (OrbitControls) +- [ ] 카메라 줌 인/아웃 +- [ ] 그리드 스냅 기능 +- [ ] 여러 자재 동시 이동 +- [ ] 자재 간 충돌 방지 + +### 9.4. 저장 및 로드 테스트 + +- [ ] 자재 배치 후 저장 +- [ ] 저장된 레이아웃 다시 로드 +- [ ] 레이아웃 삭제 +- [ ] 레이아웃 복제 (선택사항) + +--- + +## 10. 향후 확장 가능성 + +- 자재 검색 및 필터링 (상태별, 자재 코드별) +- 자재 배치 히스토리 (변경 이력) +- 자재 배치 템플릿 (자주 사용하는 배치 저장) +- 자재 입출고 연동 (실시간 재고 반영) +- 자재 경로 최적화 (피킹 경로 표시) +- AR/VR 지원 (모바일 AR로 실제 야드 확인) +- 다중 사용자 동시 편집 (WebSocket) +- 자재 배치 분석 (공간 활용률, 접근성 등) + +--- + +## 11. 파일 구조 + +``` +backend-node/src/ +├── services/ +│ └── YardLayoutService.ts (신규) +├── controllers/ +│ └── YardLayoutController.ts (신규) +├── routes/ +│ └── yardLayoutRoutes.ts (신규) +└── app.ts (수정) + +frontend/components/admin/dashboard/ +├── widgets/ +│ ├── YardManagement3DWidget.tsx (신규 - 메인) +│ ├── YardLayoutSelector.tsx (신규) +│ ├── YardLayoutCreator.tsx (신규) +│ ├── Yard3DCanvas.tsx (신규) +│ ├── MaterialInfoPanel.tsx (신규) +│ └── MaterialLibrary.tsx (신규) +├── types.ts (수정 - 위젯 타입 추가) +├── DashboardTopMenu.tsx (수정 - 메뉴 추가) +└── CanvasElement.tsx (수정 - 렌더링 추가) + +db/ +└── migrations/ + └── create_yard_tables.sql (신규) +``` + +--- + +## 12. 예상 개발 기간 + +- Phase 1 (DB & API): 1일 +- Phase 2 (선택/생성): 1일 +- Phase 3 (3D 기본): 1일 +- Phase 4 (배치 인터랙션): 2일 +- Phase 5 (정보 패널): 1일 +- Phase 6 (통합/최적화): 1일 +- Phase 7 (대시보드 등록): 0.5일 + +**총 예상 기간: 7.5일** + +--- + +## 13. 참고 자료 + +- React Three Fiber: https://docs.pmnd.rs/react-three-fiber +- @react-three/drei: https://github.com/pmndrs/drei +- Three.js: https://threejs.org/docs/