427 lines
17 KiB
Markdown
427 lines
17 KiB
Markdown
# 야드 관리 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`
|
|
|
|
```sql
|
|
-- 기존 컬럼 변경
|
|
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 구조
|
|
|
|
```typescript
|
|
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 구조
|
|
|
|
```typescript
|
|
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 데이터 소스 + 필드 매핑 사용
|
|
|
|
```json
|
|
{
|
|
"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 미설정 요소
|
|
|
|
```json
|
|
{
|
|
"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_id` → `data_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일**
|