ERP-node/YARD_MANAGEMENT_3D_PLAN.md

38 KiB

야드 관리 3D 기능 구현 계획서

1. 기능 개요

목적

대시보드에서 야드(Yard)의 자재 배치 상태를 3D로 시각화하고 관리하는 위젯

주요 특징

  • 대시보드 위젯: 대시보드의 위젯 형태로 추가되는 기능
  • 야드 레이아웃 관리: 여러 야드 레이아웃을 생성, 선택, 수정, 삭제 가능
  • 3D 시각화: Three.js + React Three Fiber를 사용한 3D 렌더링
  • 자재 배치: 3D 공간에서 자재를 직접 배치 및 이동 가능
  • 자재 정보: 배치된 자재 클릭 시 상세 정보 표시 (읽기 전용 자재 정보 + 편집 가능한 배치 정보)

위젯 통합

  • 위젯 타입: yard-management-3d
  • 위치: 대시보드 관리 > 데이터 위젯 > 야드 관리 3D
  • 표시 모드:
    • 편집 모드: 플레이스홀더 표시
    • 뷰 모드: 실제 야드 관리 기능 실행

2. 데이터베이스 설계

2.1. yard_layout 테이블

야드 레이아웃 정보 저장

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 테이블

야드 내 자재 배치 정보 (외부 자재 데이터 참조)

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를 받기 전까지 사용할 임시 자재 데이터

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. 초기 데이터 마이그레이션 스크립트

-- 샘플 야드 레이아웃
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): 임시 자재 마스터 사용

// temp_material_master 테이블에서 조회
GET / api / materials / temp;

향후 (Phase 2): 외부 API 연동

// 외부 시스템 자재 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

구현 완료

주요 메서드:

  • getAllLayouts(): 모든 야드 레이아웃 목록 조회 (배치 자재 개수 포함)
  • getLayoutById(id): 특정 야드 레이아웃 상세 조회
  • createLayout(data): 새 야드 레이아웃 생성
  • updateLayout(id, data): 야드 레이아웃 수정 (이름, 설명만)
  • deleteLayout(id): 야드 레이아웃 삭제 (CASCADE로 배치 자재도 함께 삭제)
  • duplicateLayout(id, newName): 야드 레이아웃 복제 (배치 자재 포함)
  • getPlacementsByLayoutId(layoutId): 특정 야드의 모든 배치 자재 조회
  • addMaterialPlacement(layoutId, data): 야드에 자재 배치 추가
  • 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: 새 레이아웃 생성 (name, description)
  • PUT /api/yard-layouts/:id: 레이아웃 수정 (이름, 설명만)
  • DELETE /api/yard-layouts/:id: 레이아웃 삭제 (CASCADE)
  • POST /api/yard-layouts/:id/duplicate: 레이아웃 복제 (name)
  • GET /api/yard-layouts/:id/placements: 레이아웃의 배치 자재 목록
  • POST /api/yard-layouts/:id/placements: 자재 배치 추가
  • PUT /api/yard-layouts/placements/:id: 배치 정보 수정
  • DELETE /api/yard-layouts/placements/:id: 배치 해제
  • PUT /api/yard-layouts/:id/placements/batch: 배치 일괄 업데이트

모든 엔드포인트는 authMiddleware로 인증 보호됨

3.3. MaterialService

경로: backend-node/src/services/MaterialService.ts

구현 완료

주요 메서드:

  • getTempMaterials(params): 임시 자재 목록 조회 (검색, 카테고리 필터, 페이징)
  • getTempMaterialByCode(code): 특정 자재 상세 조회
  • getCategories(): 카테고리 목록 조회

3.4. MaterialController

경로: backend-node/src/controllers/MaterialController.ts

구현 완료

엔드포인트:

  • GET /api/materials/temp: 임시 자재 마스터 목록 (검색, 필터링, 페이징)
  • GET /api/materials/temp/categories: 카테고리 목록
  • GET /api/materials/temp/:code: 특정 자재 상세

향후: 외부 API 프록시로 변경 예정

3.5. Routes

경로:

  • backend-node/src/routes/yardLayoutRoutes.ts
  • backend-node/src/routes/materialRoutes.ts

구현 완료

app.ts에 등록:

  • app.use("/api/yard-layouts", yardLayoutRoutes)
  • app.use("/api/materials", materialRoutes)

4. 프론트엔드 컴포넌트 설계

4.1. YardManagement3DWidget (메인 위젯)

경로: frontend/components/admin/dashboard/widgets/YardManagement3DWidget.tsx

구현 완료

주요 기능:

  1. 레이아웃 선택/생성 모드와 3D 편집 모드 전환
  2. 편집 모드와 뷰 모드 구분 (isEditMode props)
  3. API 연동 (yardLayoutApi)

상태 관리:

- layouts: YardLayout[]                // 전체 레이아웃 목록
- selectedLayout: YardLayout | null    // 선택된 레이아웃
- isCreateModalOpen: boolean           // 생성 모달 표시 여부
- isLoading: boolean                   // 로딩 상태

하위 컴포넌트:

  • YardLayoutList: 레이아웃 목록 표시
  • YardLayoutCreateModal: 새 레이아웃 생성 모달
  • YardEditor: 3D 편집 화면

4.2. API 클라이언트

경로: frontend/lib/api/yardLayoutApi.ts

구현 완료

yardLayoutApi:

  • getAllLayouts(): 모든 레이아웃 목록
  • getLayoutById(id): 레이아웃 상세
  • createLayout(data): 레이아웃 생성
  • updateLayout(id, data): 레이아웃 수정
  • deleteLayout(id): 레이아웃 삭제
  • duplicateLayout(id, name): 레이아웃 복제
  • getPlacementsByLayoutId(layoutId): 배치 목록
  • addMaterialPlacement(layoutId, data): 배치 추가
  • updatePlacement(placementId, data): 배치 수정
  • removePlacement(placementId): 배치 삭제
  • batchUpdatePlacements(layoutId, placements): 일괄 업데이트

materialApi:

  • getTempMaterials(params): 임시 자재 목록
  • getTempMaterialByCode(code): 자재 상세
  • getCategories(): 카테고리 목록

4.3. YardLayoutList (레이아웃 목록)

경로: frontend/components/admin/dashboard/widgets/yard-3d/YardLayoutList.tsx

구현 예정

  • 테이블 형식으로 레이아웃 목록 표시
  • 검색 및 정렬 기능
  • 행 클릭 시 레이아웃 선택 (편집 모드 진입)
  • 작업 메뉴 (편집, 복제, 삭제)

4.4. YardLayoutCreateModal (레이아웃 생성 모달)

경로: frontend/components/admin/dashboard/widgets/yard-3d/YardLayoutCreateModal.tsx

구현 예정

  • 야드 이름, 설명 입력
  • Shadcn UI Dialog 사용
  • 생성 완료 시 자동으로 편집 모드 진입

4.5. YardEditor (3D 편집 화면)

경로: frontend/components/admin/dashboard/widgets/yard-3d/YardEditor.tsx

구현 예정

주요 구성:

  • 상단 툴바 (뒤로가기, 저장, 자재 추가 등)
  • 좌측: 3D 캔버스
  • 우측: 자재 정보 패널 (선택 시 표시)

기술 스택:

  • React Three Fiber
  • @react-three/drei (OrbitControls, Grid, Box)
  • Three.js

주요 기능:

  1. 야드 바닥 그리드 표시
  2. 자재 3D 박스 렌더링
  3. 자재 클릭 이벤트 처리
  4. 자재 드래그 앤 드롭 (위치 이동)
  5. 카메라 컨트롤 (회전, 줌)

4.6. MaterialInfoPanel (자재 정보 패널)

경로: frontend/components/admin/dashboard/widgets/yard-3d/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. 테이블 생성 스크립트 작성 (create_yard_management_tables.sql)
  2. 마이그레이션 실행
  3. Service, Controller, Routes 구현
  4. API 클라이언트 구현 (yardLayoutApi, materialApi)

Phase 2: 메인 위젯 및 레이아웃 관리 🔄 진행 중

  1. types.ts에 위젯 타입 추가
  2. DashboardTopMenu에 위젯 추가
  3. DashboardDesigner에 위젯 타이틀/컨텐츠 추가
  4. YardManagement3DWidget 메인 컴포넌트 구현
  5. YardLayoutList 컴포넌트 구현
  6. YardLayoutCreateModal 컴포넌트 구현

Phase 3: 3D 편집 화면 대기 중

  1. YardEditor 메인 컴포넌트
  2. 상단 툴바 (뒤로가기, 저장, 자재 추가)
  3. 레이아웃 구성 (좌측 캔버스 + 우측 패널)

Phase 4: 3D 캔버스 기본 구조 대기 중

  1. Yard3DCanvas 컴포넌트 기본 구조
  2. React Three Fiber 설정
  3. 야드 바닥 그리드 렌더링
  4. 카메라 컨트롤 (OrbitControls)
  5. 자재 3D 박스 렌더링

Phase 5: 자재 배치 및 인터랙션 대기 중

  1. MaterialLibrary 컴포넌트 구현
  2. 자재 선택 및 추가
  3. 자재 드래그 앤 드롭 배치
  4. 자재 클릭 선택
  5. 자재 위치 이동 (드래그)

Phase 6: 자재 정보 패널 및 편집 대기 중

  1. MaterialInfoPanel 컴포넌트 구현
  2. 자재 정보 표시 (읽기 전용 + 편집 가능)
  3. 자재 배치 정보 수정
  4. 배치 해제 기능
  5. 변경사항 저장

Phase 7: 통합 및 최적화 대기 중

  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 스타일)

예시:

// 잘못된 방법 ❌
window.alert("저장되었습니다");
if (window.confirm("삭제하시겠습니까?")) { ... }

// 올바른 방법 ✅
<AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>배치 해제</AlertDialogTitle>
      <AlertDialogDescription>
         자재를 야드에서 제거하시겠습니까?
      </AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>취소</AlertDialogCancel>
      <AlertDialogAction onClick={handleRemove}>확인</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

8. API 명세서

8.1. 야드 레이아웃 API

GET /api/yard-layouts

설명: 모든 야드 레이아웃 목록 조회

응답:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "A구역",
      "description": "메인 야드 A구역",
      "placement_count": 15,
      "created_at": "2025-01-01T00:00:00Z"
    }
  ]
}

GET /api/yard-layouts/:id

설명: 특정 야드 레이아웃 상세 조회

응답:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "A구역",
    "description": "메인 야드 A구역",
    "created_at": "2025-01-01T00:00:00Z"
  }
}

POST /api/yard-layouts

설명: 새 야드 레이아웃 생성

요청:

{
  "name": "D구역",
  "description": "신규 야드"
}

PUT /api/yard-layouts/:id

설명: 야드 레이아웃 수정 (이름, 설명만)

요청:

{
  "name": "D구역 (수정)",
  "description": "수정된 설명"
}

DELETE /api/yard-layouts/:id

설명: 야드 레이아웃 삭제

8.2. 자재 배치 API

GET /api/yard-layouts/:id/materials

설명: 특정 야드의 모든 자재 조회

응답:

{
  "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

설명: 야드에 자재 추가

요청:

{
  "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

설명: 자재 정보 수정

요청:

{
  "position_x": 25,
  "position_z": 25,
  "quantity": 55
}

DELETE /api/yard-materials/:id

설명: 자재 삭제

PUT /api/yard-layouts/:id/materials/batch

설명: 여러 자재 일괄 업데이트 (드래그로 여러 자재 이동 시)

요청:

{
  "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. 참고 자료