ERP-node/YARD_MANAGEMENT_3D_DATA_BIN...

17 KiB

야드 관리 3D - 데이터 바인딩 시스템 재설계

1. 개요

현재 방식의 문제점

  • 고정된 임시 자재 마스터(temp_material_master) 테이블에 의존
  • 실제 외부 시스템의 자재 데이터와 연동 불가
  • 자재 목록이 제한적이고 유연성 부족
  • 사용자가 직접 데이터를 선택하거나 입력할 수 없음

새로운 방식의 목표

  • 차트/리스트 위젯과 동일한 데이터 소스 선택 방식 적용
  • DB 커넥션 또는 REST API를 통해 실제 자재 데이터 연동
  • 사용자가 자재명, 수량 등을 직접 매핑 및 입력 가능
  • 설정되지 않은 요소는 뷰어에서 명확히 표시

2. 핵심 변경사항

2.1 요소(Element) 개념 도입

  • 기존: 자재 목록에서 클릭 → 즉시 배치
  • 변경: [+ 요소 추가] 버튼 클릭 → 3D 캔버스에 즉시 빈 요소 배치 → 우측 패널이 데이터 바인딩 설정 화면으로 전환

2.2 데이터 소스 선택

  • 현재 DB (내부 PostgreSQL)
  • 외부 DB 커넥션
  • REST API

2.3 데이터 매핑

  • 자재명 필드 선택 (데이터 소스에서)
  • 수량 필드 선택 (데이터 소스에서)
  • 단위 직접 입력 (예: EA, BOX, KG 등)
  • 색상 선택

3. 데이터베이스 스키마 변경

3.1 기존 테이블 수정: yard_material_placement

-- 기존 컬럼 변경
ALTER TABLE yard_material_placement
  -- 기존 컬럼 제거 (외부 자재 ID 관련)
  DROP COLUMN IF EXISTS external_material_id,

  -- 데이터 소스 정보 추가
  ADD COLUMN data_source_type VARCHAR(20), -- 'database', 'external_db', 'rest_api'
  ADD COLUMN data_source_config JSONB, -- 데이터 소스 설정

  -- 데이터 바인딩 정보 추가
  ADD COLUMN data_binding JSONB, -- 필드 매핑 정보

  -- 자재 정보를 NULL 허용으로 변경 (설정 전에는 NULL)
  ALTER COLUMN material_code DROP NOT NULL,
  ALTER COLUMN material_name DROP NOT NULL,
  ALTER COLUMN quantity DROP NOT NULL;

3.2 data_source_config 구조

interface DataSourceConfig {
  type: "database" | "external_db" | "rest_api";

  // type === 'database' (현재 DB)
  query?: string;

  // type === 'external_db' (외부 DB)
  connectionId?: number;
  query?: string;

  // type === 'rest_api'
  url?: string;
  method?: "GET" | "POST";
  headers?: Record<string, string>;
  queryParams?: Record<string, string>;
  body?: string;
  dataPath?: string; // 응답에서 데이터 배열 경로 (예: "data.items")
}

3.3 data_binding 구조

interface DataBinding {
  // 데이터 소스의 특정 행 선택
  selectedRowIndex?: number;

  // 필드 매핑 (데이터 소스에서 선택)
  materialNameField?: string; // 자재명이 들어있는 컬럼명
  quantityField?: string; // 수량이 들어있는 컬럼명

  // 단위는 사용자가 직접 입력
  unit: string; // 예: "EA", "BOX", "KG", "M" 등
}

4. UI/UX 설계

4.1 편집 모드 (YardEditor)

┌─────────────────────────────────────────────────────────────┐
│ [← 목록으로]  야드명: A구역                      [저장]    │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌───────────────────────────┐  ┌──────────────────────────┐│
│  │                           │  │                          ││
│  │                           │  │  [+ 요소 추가]           ││
│  │                           │  │                          ││
│  │      3D 캔버스            │  │  ┌────────────────────┐ ││
│  │                           │  │  │ □ 요소 1          │ ││
│  │                           │  │  │   자재: 철판 A     │ ││
│  │                           │  │  │   수량: 50 EA      │ ││
│  │                           │  │  │   [편집] [삭제]    │ ││
│  │                           │  │  └────────────────────┘ ││
│  │                           │  │                          ││
│  │                           │  │  ┌────────────────────┐ ││
│  │                           │  │  │ □ 요소 2 (미설정) │ ││
│  │                           │  │  │   데이터 바인딩    │ ││
│  │                           │  │  │   설정 필요        │ ││
│  │                           │  │  │   [설정] [삭제]    │ ││
│  │                           │  │  └────────────────────┘ ││
│  │                           │  │                          ││
│  └───────────────────────────┘  └──────────────────────────┘│
│                                                               │
└─────────────────────────────────────────────────────────────┘

4.1.1 요소 목록 (우측 패널)

  • [+ 요소 추가] 버튼: 새 요소 생성
  • 요소 카드:
    • 설정 완료: 자재명, 수량 표시 + [편집] [삭제] 버튼
    • 미설정: "데이터 바인딩 설정 필요" + [설정] [삭제] 버튼

4.1.2 요소 추가 흐름

1. [+ 요소 추가] 클릭
   ↓
2. 3D 캔버스의 기본 위치(0,0,0)에 회색 반투명 박스로 빈 요소 즉시 배치
   ↓
3. 요소가 자동 선택됨
   ↓
4. 우측 패널이 "데이터 바인딩 설정" 화면으로 자동 전환
   (요소 목록에서 [설정] 버튼을 클릭해도 동일한 화면)

4.2 데이터 바인딩 설정 패널 (우측)

[+ 요소 추가] 버튼 클릭 시 또는 [설정] 버튼 클릭 시 우측 패널이 아래와 같이 변경됩니다:

┌──────────────────────────────────────┐
│  데이터 바인딩 설정           [← 목록]│
├──────────────────────────────────────┤
│                                                            │
│  ┌─ 1단계: 데이터 소스 선택 ─────────────────────────┐  │
│  │                                                      │  │
│  │  ○ 현재 DB     ○ 외부 DB     ○ REST API           │  │
│  │                                                      │  │
│  │  [현재 DB 선택 시]                                  │  │
│  │  ┌────────────────────────────────────────────┐    │  │
│  │  │ SELECT material_name, quantity, unit       │    │  │
│  │  │ FROM inventory                             │    │  │
│  │  │ WHERE status = 'available'                 │    │  │
│  │  └────────────────────────────────────────────┘    │  │
│  │  [실행] 버튼                                        │  │
│  │                                                      │  │
│  │  [외부 DB 선택 시]                                  │  │
│  │  - 외부 커넥션 선택 드롭다운                        │  │
│  │  - SQL 쿼리 입력                                    │  │
│  │  - [실행] 버튼                                      │  │
│  │                                                      │  │
│  │  [REST API 선택 시]                                 │  │
│  │  - URL 입력                                         │  │
│  │  - Method 선택 (GET/POST)                          │  │
│  │  - Headers, Query Params 설정                      │  │
│  │  - [실행] 버튼                                      │  │
│  │                                                      │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                            │
│  ┌─ 2단계: 쿼리 결과 및 필드 매핑 ──────────────────────┐  │
│  │                                                      │  │
│  │  쿼리 결과 (5행):                                   │  │
│  │  ┌────────────────────────────────────────────┐    │  │
│  │  │ material_name  │ quantity │ status         │    │  │
│  │  │ 철판 A         │ 50       │ available      │ ○ │  │
│  │  │ 강관 파이프    │ 100      │ available      │ ○ │  │
│  │  │ 볼트 세트      │ 500      │ in_stock       │ ○ │  │
│  │  └────────────────────────────────────────────┘    │  │
│  │                                                      │  │
│  │  필드 매핑:                                          │  │
│  │  자재명: [material_name ▼]                          │  │
│  │  수량:   [quantity ▼]                               │  │
│  │                                                      │  │
│  │  단위 입력:                                          │  │
│  │  단위:   [EA_____________]                          │  │
│  │          (예: EA, BOX, KG, M, L 등)                 │  │
│  │                                                      │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                            │
│  ┌─ 3단계: 배치 설정 ──────────────────────────────────┐  │
│  │                                                      │  │
│  │  색상: [🎨 #3b82f6]                                 │  │
│  │                                                      │  │
│  │  크기:                                               │  │
│  │  너비: [5] 높이: [5] 깊이: [5]                      │  │
│  │                                                      │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                            │
│                          [← 목록으로]  [저장]           │
└──────────────────────────────────────┘

참고:

  • [← 목록으로] 버튼: 요소 목록 화면으로 돌아갑니다
  • [저장] 버튼: 데이터 바인딩 설정을 저장하고 요소 목록 화면으로 돌아갑니다
  • 저장하지 않고 나가면 요소는 "미설정" 상태로 남습니다

4.3 뷰어 모드 (Yard3DViewer)

4.3.1 설정된 요소

  • 정상적으로 3D 박스 렌더링
  • 클릭 시 자재명, 수량 정보 표시

4.3.2 미설정 요소

┌─────────────────────┐
│                     │
│   ⚠️               │
│                     │
│  설정되지 않은      │
│  요소입니다         │
│                     │
└─────────────────────┘
  • 반투명 회색 박스로 표시
  • 클릭 시 "데이터 바인딩이 설정되지 않았습니다" 메시지

5. 구현 단계

Phase 1: 데이터베이스 스키마 변경

  • yard_material_placement 테이블 수정
  • 마이그레이션 스크립트 작성
  • 기존 데이터 호환성 처리

Phase 2: 백엔드 API 수정

  • YardLayoutService.ts 수정
    • addMaterialPlacement: 데이터 소스/바인딩 정보 저장
    • updatePlacement: 데이터 바인딩 업데이트
    • getPlacementsByLayoutId: 새 필드 포함하여 조회
  • 데이터 소스 실행 로직 추가
    • DB 쿼리 실행
    • 외부 DB 쿼리 실행
    • REST API 호출

Phase 3: 프론트엔드 타입 정의

  • types.ts에 새로운 인터페이스 추가
    • YardElementDataSource
    • YardElementDataBinding
    • YardPlacement 업데이트

Phase 4: 요소 추가 및 관리

  • YardEditor.tsx 수정
    • [+ 요소 추가] 버튼 구현
    • 빈 요소 생성 로직 (즉시 3D 캔버스에 배치)
    • 요소 추가 시 자동으로 해당 요소 선택
    • 우측 패널 상태 관리 (요소 목록 ↔ 데이터 바인딩 설정)
    • 요소 목록 UI
    • 설정/미설정 상태 구분 표시

Phase 5: 데이터 바인딩 패널

  • YardElementConfigPanel.tsx 생성 (우측 패널 컴포넌트)
    • [← 목록으로] 버튼으로 요소 목록으로 복귀
    • 1단계: 데이터 소스 선택 (DatabaseConfig, ExternalDbConfig, RestApiConfig 재사용)
    • 2단계: 쿼리 결과 테이블 + 행 선택 + 필드 매핑
      • 자재명 필드 선택 (드롭다운)
      • 수량 필드 선택 (드롭다운)
      • 단위 직접 입력 (Input)
    • 3단계: 배치 설정 (색상, 크기)
    • [저장] 버튼으로 설정 저장 및 목록으로 복귀

Phase 6: 3D 캔버스 렌더링 수정

  • Yard3DCanvas.tsx 수정
    • 설정된 요소: 기존 렌더링
    • 미설정 요소: 회색 반투명 박스 + 경고 아이콘

Phase 7: 뷰어 모드 수정

  • Yard3DViewer.tsx 수정
    • 미설정 요소 감지
    • 미설정 요소 클릭 시 안내 메시지

Phase 8: 임시 테이블 제거

  • temp_material_master 테이블 삭제
  • 관련 API 및 UI 코드 정리

6. 데이터 구조 예시

6.1 데이터 소스 + 필드 매핑 사용

{
  "id": 1,
  "yard_layout_id": 1,
  "material_code": null,
  "material_name": "철판 A타입",
  "quantity": 50,
  "unit": "EA",
  "data_source_type": "database",
  "data_source_config": {
    "type": "database",
    "query": "SELECT material_name, quantity FROM inventory WHERE material_id = 'MAT-001'"
  },
  "data_binding": {
    "selectedRowIndex": 0,
    "materialNameField": "material_name",
    "quantityField": "quantity",
    "unit": "EA"
  },
  "position_x": 10,
  "position_y": 0,
  "position_z": 10,
  "size_x": 5,
  "size_y": 5,
  "size_z": 5,
  "color": "#ef4444"
}

6.2 미설정 요소

{
  "id": 3,
  "yard_layout_id": 1,
  "material_code": null,
  "material_name": null,
  "quantity": null,
  "unit": null,
  "data_source_type": null,
  "data_source_config": null,
  "data_binding": null,
  "position_x": 30,
  "position_y": 0,
  "position_z": 30,
  "size_x": 5,
  "size_y": 5,
  "size_z": 5,
  "color": "#9ca3af"
}

7. 장점

  1. 유연성: 다양한 데이터 소스 지원 (내부 DB, 외부 DB, REST API)
  2. 실시간성: 실제 시스템의 자재 데이터와 연동 가능
  3. 일관성: 차트/리스트 위젯과 동일한 데이터 소스 선택 방식
  4. 사용자 경험: 데이터 매핑 방식 선택 가능 (자동/수동)
  5. 확장성: 새로운 데이터 소스 타입 추가 용이
  6. 명확성: 미설정 요소를 시각적으로 구분

8. 마이그레이션 전략

8.1 기존 데이터 처리

  • 기존 temp_material_master 기반 배치 데이터를 수동 입력 모드로 전환
  • external_material_iddata_binding.mode = 'manual'로 변환

8.2 단계적 전환

  1. 새 스키마 적용 (기존 컬럼 유지)
  2. 새 UI/로직 구현 및 테스트
  3. 기존 데이터 마이그레이션
  4. 임시 테이블 및 구 코드 제거

9. 기술 스택

  • 백엔드: PostgreSQL JSONB, Node.js/TypeScript
  • 프론트엔드: React, TypeScript, Shadcn UI
  • 3D 렌더링: React Three Fiber, Three.js
  • 데이터 소스: 기존 DatabaseConfig, ExternalDbConfig, RestApiConfig 컴포넌트 재사용

10. 예상 개발 기간

  • Phase 1-2 (DB/백엔드): 1일
  • Phase 3-4 (프론트엔드 구조): 1일
  • Phase 5 (데이터 바인딩 모달): 2일
  • Phase 6-7 (3D 렌더링/뷰어): 1일
  • Phase 8 (정리 및 테스트): 0.5일

총 예상 기간: 약 5.5일