문서업데이트
This commit is contained in:
209
digitalTwin/architecture-v4.md
Normal file
209
digitalTwin/architecture-v4.md
Normal file
@@ -0,0 +1,209 @@
|
||||
# 디지털트윈 아키텍처 v4
|
||||
|
||||
## 변경사항 (v3 → v4)
|
||||
|
||||
| 구분 | v3 | v4 |
|
||||
| :--- | :--- | :--- |
|
||||
| OTA 업데이트 | 개념만 존재 | Fleet Manager + MQTT 구현 |
|
||||
| 디바이스 관리 | 없음 | Device Registry 추가 |
|
||||
| 상태 모니터링 | 없음 | Heartbeat + Metrics 추가 |
|
||||
| 원격 제어 | 없음 | MQTT 기반 명령 추가 |
|
||||
| Agent | 없음 | Fleet Agent 추가 |
|
||||
|
||||
---
|
||||
|
||||
## Mermaid 다이어그램
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
flowchart BT
|
||||
subgraph Global_Platform["☁️ Vexplor 글로벌 플랫폼"]
|
||||
direction TB
|
||||
AAS_Dashboard["<b>💻 AAS 통합 대시보드</b><br>(React/Next.js)<br>• 중앙 모니터링<br>• Fleet 관리 UI"]
|
||||
Global_API["<b>🌐 글로벌 API 게이트웨이</b><br>• 사용자 인증 (Auth)<br>• 고객사 라우팅<br>• Fleet API"]
|
||||
|
||||
subgraph Fleet_System["🎛️ Fleet Management"]
|
||||
Fleet_Manager["<b>📊 Fleet Manager</b><br>• Device Registry<br>• 배포 오케스트레이션<br>• 상태 모니터링"]
|
||||
MQTT_Broker["<b>📡 MQTT Broker</b><br>(Mosquitto/EMQX)<br>• 실시간 통신<br>• 10,000+ 연결"]
|
||||
Monitoring["<b>📈 Monitoring</b><br>(Prometheus/Grafana)<br>• 메트릭 수집<br>• 알림"]
|
||||
end
|
||||
|
||||
Update_Server["<b>🚀 배포/업데이트 매니저</b><br>• Docker 이미지 레지스트리 (Harbor)<br>• 버전 관리<br>• Canary 배포"]
|
||||
end
|
||||
|
||||
subgraph Local_Server["스피폭스 사내 서버 (Local Server)"]
|
||||
Fleet_Agent_A["<b>🤖 Fleet Agent</b><br>• MQTT 연결<br>• Heartbeat (30초)<br>• 원격 명령 실행<br>• Docker 관리"]
|
||||
VEX_Engine["<b>VEX Flow 엔진</b><br>데이터 수집/처리"]
|
||||
Customer_DB[("<b>사내 통합 DB</b><br>(모든 데이터 보유)")]
|
||||
Watchtower_A["<b>🐋 Watchtower</b><br>이미지 자동 업데이트"]
|
||||
end
|
||||
|
||||
subgraph Edge_Internals["🖥️ 엣지 디바이스 (Store & Forward)"]
|
||||
Edge_Collector["<b>수집/가공</b><br>(Python)"]
|
||||
Edge_Buffer[("<b>💾 로컬 버퍼</b><br>(TimescaleDB)<br>단절 시 임시 저장")]
|
||||
Edge_Sender["<b>📤 전송 매니저</b><br>(Priority Queue)"]
|
||||
Edge_Retry_Queue[("<b>🕒 재전송 큐</b><br>(SQLite/File)")]
|
||||
end
|
||||
|
||||
subgraph Factory_A["🏭 스피폭스 공장 현장 (Factory Floor)"]
|
||||
Edge_Internals
|
||||
PLC_A["PLC / 센서"]
|
||||
end
|
||||
|
||||
subgraph Customer_A["🏢 고객사 A: 스피폭스 (사내망)"]
|
||||
Local_Server
|
||||
Factory_A
|
||||
end
|
||||
|
||||
subgraph Local_Server_B["고객사 B 사내 서버"]
|
||||
Fleet_Agent_B["<b>🤖 Fleet Agent</b>"]
|
||||
Watchtower_B["<b>🐋 Watchtower</b>"]
|
||||
end
|
||||
|
||||
subgraph Customer_B["🏭 고객사 B (확장 예정)"]
|
||||
Local_Server_B
|
||||
end
|
||||
|
||||
subgraph Local_Server_N["고객사 N 사내 서버"]
|
||||
Fleet_Agent_N["<b>🤖 Fleet Agent</b>"]
|
||||
end
|
||||
|
||||
subgraph Customer_N["🏭 고객사 N (10,000개)"]
|
||||
Local_Server_N
|
||||
end
|
||||
|
||||
%% 대시보드 연결
|
||||
AAS_Dashboard <--> Global_API
|
||||
AAS_Dashboard <--> Fleet_Manager
|
||||
|
||||
%% Fleet System 내부 연결
|
||||
Fleet_Manager <--> MQTT_Broker
|
||||
Fleet_Manager <--> Monitoring
|
||||
Fleet_Manager <--> Update_Server
|
||||
|
||||
%% 공장 내부 연결
|
||||
PLC_A <--> Edge_Collector
|
||||
Edge_Collector --> Edge_Buffer
|
||||
Edge_Buffer --> Edge_Sender
|
||||
Edge_Sender -- ① 정상 전송 --> VEX_Engine
|
||||
Edge_Sender -- ② 전송 실패 시 --> Edge_Retry_Queue
|
||||
Edge_Retry_Queue -. ③ 네트워크 복구 시 재전송 .-> Edge_Sender
|
||||
VEX_Engine <--> Customer_DB
|
||||
|
||||
%% Fleet Agent 연결 (MQTT - Outbound Only)
|
||||
Fleet_Agent_A == 📡 MQTT (Heartbeat/명령) ==> MQTT_Broker
|
||||
Fleet_Agent_B == 📡 MQTT ==> MQTT_Broker
|
||||
Fleet_Agent_N == 📡 MQTT ==> MQTT_Broker
|
||||
|
||||
%% Agent ↔ 로컬 컴포넌트
|
||||
Fleet_Agent_A <--> VEX_Engine
|
||||
Fleet_Agent_A <--> Watchtower_A
|
||||
Fleet_Agent_A <--> Customer_DB
|
||||
|
||||
%% OTA 업데이트 (Pull 방식)
|
||||
Update_Server -. 이미지 배포 .-> Watchtower_A
|
||||
Update_Server -. 이미지 배포 .-> Watchtower_B
|
||||
Watchtower_A -. 컨테이너 업데이트 .-> VEX_Engine
|
||||
|
||||
%% 엣지 업데이트
|
||||
VEX_Engine -. 엣지 업데이트 .-> Edge_Collector
|
||||
|
||||
%% 스타일
|
||||
AAS_Dashboard:::user
|
||||
Global_API:::global
|
||||
Update_Server:::global
|
||||
Fleet_Manager:::fleet
|
||||
MQTT_Broker:::fleet
|
||||
Monitoring:::fleet
|
||||
VEX_Engine:::localServer
|
||||
Customer_DB:::localServer
|
||||
Fleet_Agent_A:::agent
|
||||
Fleet_Agent_B:::agent
|
||||
Fleet_Agent_N:::agent
|
||||
Watchtower_A:::agent
|
||||
Watchtower_B:::agent
|
||||
Edge_Collector:::edge
|
||||
Edge_Buffer:::edgedb
|
||||
Edge_Sender:::edge
|
||||
Edge_Retry_Queue:::fail
|
||||
PLC_A:::factory
|
||||
|
||||
classDef factory fill:#e1f5fe,stroke:#01579b,stroke-width:2px
|
||||
classDef edge fill:#fff9c4,stroke:#fbc02d,stroke-width:2px
|
||||
classDef edgedb fill:#fff9c4,stroke:#fbc02d,stroke-width:2px,stroke-dasharray: 5 5
|
||||
classDef localServer fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
|
||||
classDef global fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
|
||||
classDef user fill:#ffebee,stroke:#c62828,stroke-width:2px
|
||||
classDef fleet fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
|
||||
classDef agent fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
|
||||
classDef fail fill:#ffebee,stroke:#c62828,stroke-width:2px,stroke-dasharray: 5 5
|
||||
|
||||
linkStyle 8 stroke:#2e7d32,stroke-width:2px,fill:none
|
||||
linkStyle 9 stroke:#c62828,stroke-width:2px,fill:none
|
||||
linkStyle 10 stroke:#fbc02d,stroke-width:2px,stroke-dasharray: 5 5,fill:none
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 추가된 컴포넌트 설명
|
||||
|
||||
### 1. Fleet Management (신규)
|
||||
|
||||
| 컴포넌트 | 역할 |
|
||||
| :--- | :--- |
|
||||
| **Fleet Manager** | 10,000개 디바이스 등록/관리, 배포 오케스트레이션 |
|
||||
| **MQTT Broker** | 실시간 양방향 통신 (Outbound Only 유지) |
|
||||
| **Monitoring** | Prometheus + Grafana, 메트릭 수집 & 알림 |
|
||||
|
||||
### 2. Fleet Agent (각 공장 서버에 설치)
|
||||
|
||||
| 기능 | 설명 |
|
||||
| :--- | :--- |
|
||||
| **MQTT 연결** | 글로벌 플랫폼과 상시 연결 (Outbound) |
|
||||
| **Heartbeat** | 30초마다 상태 보고 |
|
||||
| **원격 명령** | 업데이트, 재시작, 설정 변경 수신 |
|
||||
| **Docker 관리** | 컨테이너 상태 모니터링 & 제어 |
|
||||
|
||||
### 3. Watchtower (기존 유지)
|
||||
|
||||
- Harbor에서 새 이미지 자동 Pull
|
||||
- Fleet Agent의 명령으로 즉시 업데이트 가능
|
||||
|
||||
---
|
||||
|
||||
## 통신 흐름 비교
|
||||
|
||||
### v3 (기존)
|
||||
```
|
||||
보안 커넥터 ←→ 글로벌 API (양방향 터널)
|
||||
```
|
||||
|
||||
### v4 (신규)
|
||||
```
|
||||
Fleet Agent ──→ MQTT Broker (Outbound Only)
|
||||
←── 명령 수신 (Subscribe)
|
||||
──→ 상태 보고 (Publish)
|
||||
|
||||
Watchtower ──→ Harbor (Pull Only)
|
||||
```
|
||||
|
||||
**장점:**
|
||||
- 방화벽 Inbound 규칙 불필요
|
||||
- 10,000개 동시 연결 가능
|
||||
- 실시간 명령 전달
|
||||
|
||||
---
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```
|
||||
[공장 → 글로벌]
|
||||
PLC → 엣지 → VEX Flow → Fleet Agent → MQTT → Fleet Manager → Dashboard
|
||||
|
||||
[글로벌 → 공장]
|
||||
Dashboard → Fleet Manager → MQTT → Fleet Agent → Docker/VEX Flow
|
||||
```
|
||||
|
||||
725
digitalTwin/fleet-management-plan.md
Normal file
725
digitalTwin/fleet-management-plan.md
Normal file
@@ -0,0 +1,725 @@
|
||||
# Fleet Management 시스템 구축 계획서
|
||||
|
||||
## 개요
|
||||
|
||||
**목표:** 10,000개 이상의 온프레미스 공장 서버를 중앙에서 효율적으로 관리
|
||||
|
||||
**현재 상태:** 1개 업체 (스피폭스), Watchtower 기반 자동 업데이트
|
||||
|
||||
**목표 상태:** 10,000개 업체, 실시간 모니터링 & 원격 제어 가능
|
||||
|
||||
---
|
||||
|
||||
## 목차
|
||||
|
||||
1. [아키텍처 설계](#1-아키텍처-설계)
|
||||
2. [Phase별 구현 계획](#2-phase별-구현-계획)
|
||||
3. [핵심 컴포넌트 상세](#3-핵심-컴포넌트-상세)
|
||||
4. [데이터베이스 스키마](#4-데이터베이스-스키마)
|
||||
5. [API 설계](#5-api-설계)
|
||||
6. [기술 스택](#6-기술-스택)
|
||||
7. [일정 및 마일스톤](#7-일정-및-마일스톤)
|
||||
8. [리스크 및 대응](#8-리스크-및-대응)
|
||||
|
||||
---
|
||||
|
||||
## 1. 아키텍처 설계
|
||||
|
||||
### 1.1 전체 아키텍처
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ Vexplor 글로벌 플랫폼 │
|
||||
├─────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Web UI │ │ Fleet API │ │ Config │ │ Monitoring │ │
|
||||
│ │ (Dashboard) │ │ Gateway │ │ Server │ │ & Alerts │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └────────────────┼────────────────┼────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Message │ │ Device │ │
|
||||
│ │ Broker │ │ Registry │ │
|
||||
│ │ (MQTT) │ │ (Redis) │ │
|
||||
│ └──────┬──────┘ └─────────────┘ │
|
||||
│ │ │
|
||||
└──────────────────────────┼────────────────────────────────────────────┘
|
||||
│
|
||||
│ MQTT (TLS)
|
||||
│
|
||||
┌──────────────────┼──────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Agent │ │ Agent │ │ Agent │
|
||||
│ 스피폭스 │ │ 엔키드 │ │ 고객 N │
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
│ │ │
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Vexplor │ │ Vexplor │ │ Vexplor │
|
||||
│ Backend │ │ Backend │ │ Backend │
|
||||
│Frontend │ │Frontend │ │Frontend │
|
||||
│ DB │ │ DB │ │ DB │
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
```
|
||||
|
||||
### 1.2 통신 흐름
|
||||
|
||||
```
|
||||
[공장 서버 → 글로벌]
|
||||
1. Agent 시작 시 MQTT 연결 (Outbound Only)
|
||||
2. 주기적 Heartbeat 전송 (30초)
|
||||
3. 상태/메트릭 보고 (5분)
|
||||
4. 로그 전송 (선택적)
|
||||
|
||||
[글로벌 → 공장 서버]
|
||||
1. 업데이트 명령
|
||||
2. 설정 변경
|
||||
3. 재시작 명령
|
||||
4. 데이터 요청
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Phase별 구현 계획
|
||||
|
||||
### Phase 1: 기반 구축 (1~10개 업체)
|
||||
**기간:** 2주
|
||||
|
||||
| 구현 항목 | 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- |
|
||||
| Device Registry API | 디바이스 등록/조회 | P0 |
|
||||
| Heartbeat API | 상태 보고 수신 | P0 |
|
||||
| 기본 대시보드 | 디바이스 목록/상태 표시 | P1 |
|
||||
| Agent 기본 버전 | Heartbeat 전송 기능 | P0 |
|
||||
|
||||
**산출물:**
|
||||
- `POST /api/fleet/devices/register`
|
||||
- `POST /api/fleet/devices/heartbeat`
|
||||
- `GET /api/fleet/devices`
|
||||
- Agent Docker 이미지
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: 실시간 통신 (10~100개 업체)
|
||||
**기간:** 4주
|
||||
|
||||
| 구현 항목 | 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- |
|
||||
| MQTT 브로커 설치 | Eclipse Mosquitto | P0 |
|
||||
| Agent MQTT 연결 | 상시 연결 유지 | P0 |
|
||||
| 원격 명령 기능 | 업데이트/재시작 명령 | P1 |
|
||||
| 실시간 상태 업데이트 | WebSocket → 대시보드 | P1 |
|
||||
|
||||
**산출물:**
|
||||
- MQTT 브로커 (Docker)
|
||||
- Agent v2 (MQTT 지원)
|
||||
- 원격 명령 UI
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: 배포 관리 (100~500개 업체)
|
||||
**기간:** 6주
|
||||
|
||||
| 구현 항목 | 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- |
|
||||
| 버전 관리 시스템 | 릴리즈 버전 관리 | P0 |
|
||||
| 단계적 롤아웃 | Canary 배포 | P0 |
|
||||
| 롤백 기능 | 이전 버전 복구 | P0 |
|
||||
| 그룹 관리 | 지역/업종별 그룹핑 | P1 |
|
||||
| 배포 스케줄링 | 시간대별 배포 | P2 |
|
||||
|
||||
**산출물:**
|
||||
- Release Management UI
|
||||
- Deployment Pipeline
|
||||
- Rollback 자동화
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: 모니터링 강화 (500~2,000개 업체)
|
||||
**기간:** 6주
|
||||
|
||||
| 구현 항목 | 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- |
|
||||
| 메트릭 수집 | CPU/Memory/Disk | P0 |
|
||||
| 알림 시스템 | Slack/Email/SMS | P0 |
|
||||
| 로그 중앙화 | 원격 로그 수집 | P1 |
|
||||
| 이상 탐지 | 자동 장애 감지 | P1 |
|
||||
| SLA 대시보드 | 가용성 리포트 | P2 |
|
||||
|
||||
**산출물:**
|
||||
- Prometheus + Grafana
|
||||
- Alert Manager
|
||||
- Log Aggregator (Loki)
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: 대규모 확장 (2,000~10,000개 업체)
|
||||
**기간:** 8주
|
||||
|
||||
| 구현 항목 | 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- |
|
||||
| MQTT 클러스터링 | 고가용성 브로커 | P0 |
|
||||
| 샤딩 | 지역별 분산 | P0 |
|
||||
| 자동 프로비저닝 | 신규 업체 자동 설정 | P1 |
|
||||
| API Rate Limiting | 과부하 방지 | P1 |
|
||||
| 멀티 리전 | 글로벌 분산 | P2 |
|
||||
|
||||
**산출물:**
|
||||
- MQTT Cluster (EMQX)
|
||||
- Regional Gateway
|
||||
- Auto-provisioning System
|
||||
|
||||
---
|
||||
|
||||
## 3. 핵심 컴포넌트 상세
|
||||
|
||||
### 3.1 Fleet Agent (공장 서버에 설치)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Fleet Agent │
|
||||
├─────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ MQTT │ │ Command │ │
|
||||
│ │ Client │ │ Executor │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────────────────────┐ │
|
||||
│ │ Core Controller │ │
|
||||
│ └─────────────────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Metrics │ │ Docker │ │
|
||||
│ │ Collector │ │ Manager │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**주요 기능:**
|
||||
- MQTT 연결 유지 (자동 재연결)
|
||||
- Heartbeat 전송 (30초)
|
||||
- 시스템 메트릭 수집
|
||||
- Docker 컨테이너 관리
|
||||
- 원격 명령 실행
|
||||
|
||||
### 3.2 Fleet Manager (글로벌 서버)
|
||||
|
||||
**주요 기능:**
|
||||
- 디바이스 등록/인증
|
||||
- 상태 모니터링
|
||||
- 배포 오케스트레이션
|
||||
- 설정 관리
|
||||
- 알림 발송
|
||||
|
||||
### 3.3 Message Broker (MQTT)
|
||||
|
||||
**선택지:**
|
||||
| 옵션 | 장점 | 단점 | 추천 규모 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| Mosquitto | 가볍고 간단 | 클러스터링 어려움 | ~1,000 |
|
||||
| EMQX | 클러스터링, 고성능 | 복잡함 | 1,000~100,000 |
|
||||
| HiveMQ | 엔터프라이즈급 | 비용 | 100,000+ |
|
||||
|
||||
**권장:** Phase 1~3은 Mosquitto, Phase 4~5는 EMQX
|
||||
|
||||
---
|
||||
|
||||
## 4. 데이터베이스 스키마
|
||||
|
||||
### 4.1 디바이스 테이블
|
||||
|
||||
```sql
|
||||
-- 디바이스 (공장 서버) 정보
|
||||
CREATE TABLE fleet_devices (
|
||||
id SERIAL PRIMARY KEY,
|
||||
device_id VARCHAR(50) UNIQUE NOT NULL, -- 고유 식별자
|
||||
company_code VARCHAR(20) NOT NULL, -- 회사 코드
|
||||
device_name VARCHAR(100), -- 표시 이름
|
||||
|
||||
-- 연결 정보
|
||||
ip_address VARCHAR(45),
|
||||
last_seen_at TIMESTAMPTZ,
|
||||
is_online BOOLEAN DEFAULT false,
|
||||
|
||||
-- 버전 정보
|
||||
agent_version VARCHAR(20),
|
||||
app_version VARCHAR(20),
|
||||
|
||||
-- 시스템 정보
|
||||
os_info JSONB,
|
||||
hardware_info JSONB,
|
||||
|
||||
-- 그룹/태그
|
||||
device_group VARCHAR(50),
|
||||
tags JSONB DEFAULT '[]',
|
||||
|
||||
-- 메타
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
FOREIGN KEY (company_code) REFERENCES company_info(company_code)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_fleet_devices_company ON fleet_devices(company_code);
|
||||
CREATE INDEX idx_fleet_devices_online ON fleet_devices(is_online);
|
||||
CREATE INDEX idx_fleet_devices_group ON fleet_devices(device_group);
|
||||
```
|
||||
|
||||
### 4.2 Heartbeat 로그 테이블
|
||||
|
||||
```sql
|
||||
-- Heartbeat 기록 (TimescaleDB 권장)
|
||||
CREATE TABLE fleet_heartbeats (
|
||||
id BIGSERIAL,
|
||||
device_id VARCHAR(50) NOT NULL,
|
||||
received_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
|
||||
-- 상태
|
||||
status VARCHAR(20), -- OK, WARNING, ERROR
|
||||
uptime_seconds BIGINT,
|
||||
|
||||
-- 메트릭
|
||||
cpu_percent DECIMAL(5,2),
|
||||
memory_percent DECIMAL(5,2),
|
||||
disk_percent DECIMAL(5,2),
|
||||
|
||||
-- 컨테이너 상태
|
||||
containers JSONB,
|
||||
|
||||
PRIMARY KEY (device_id, received_at)
|
||||
);
|
||||
|
||||
-- TimescaleDB 하이퍼테이블 변환 (선택)
|
||||
-- SELECT create_hypertable('fleet_heartbeats', 'received_at');
|
||||
```
|
||||
|
||||
### 4.3 배포 테이블
|
||||
|
||||
```sql
|
||||
-- 릴리즈 버전 관리
|
||||
CREATE TABLE fleet_releases (
|
||||
id SERIAL PRIMARY KEY,
|
||||
version VARCHAR(20) NOT NULL,
|
||||
release_type VARCHAR(20), -- stable, beta, hotfix
|
||||
|
||||
-- 이미지 정보
|
||||
backend_image VARCHAR(200),
|
||||
frontend_image VARCHAR(200),
|
||||
agent_image VARCHAR(200),
|
||||
|
||||
-- 변경사항
|
||||
changelog TEXT,
|
||||
|
||||
-- 상태
|
||||
status VARCHAR(20) DEFAULT 'draft', -- draft, testing, released, deprecated
|
||||
released_at TIMESTAMPTZ,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 배포 작업
|
||||
CREATE TABLE fleet_deployments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
release_id INTEGER REFERENCES fleet_releases(id),
|
||||
|
||||
-- 배포 대상
|
||||
target_type VARCHAR(20), -- all, group, specific
|
||||
target_value VARCHAR(100), -- 그룹명 또는 device_id
|
||||
|
||||
-- 롤아웃 설정
|
||||
rollout_strategy VARCHAR(20), -- immediate, canary, scheduled
|
||||
rollout_percentage INTEGER,
|
||||
scheduled_at TIMESTAMPTZ,
|
||||
|
||||
-- 상태
|
||||
status VARCHAR(20) DEFAULT 'pending',
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
|
||||
-- 결과
|
||||
total_devices INTEGER,
|
||||
success_count INTEGER DEFAULT 0,
|
||||
failed_count INTEGER DEFAULT 0,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 개별 디바이스 배포 상태
|
||||
CREATE TABLE fleet_deployment_status (
|
||||
id SERIAL PRIMARY KEY,
|
||||
deployment_id INTEGER REFERENCES fleet_deployments(id),
|
||||
device_id VARCHAR(50),
|
||||
|
||||
status VARCHAR(20) DEFAULT 'pending', -- pending, downloading, installing, completed, failed
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
error_message TEXT,
|
||||
|
||||
UNIQUE(deployment_id, device_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 4.4 알림 규칙 테이블
|
||||
|
||||
```sql
|
||||
-- 알림 규칙
|
||||
CREATE TABLE fleet_alert_rules (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
|
||||
-- 조건
|
||||
condition_type VARCHAR(50), -- offline, version_mismatch, high_cpu, etc.
|
||||
condition_value JSONB,
|
||||
threshold_minutes INTEGER, -- 조건 지속 시간
|
||||
|
||||
-- 알림 채널
|
||||
notify_channels JSONB, -- ["slack", "email"]
|
||||
notify_targets JSONB, -- 수신자 목록
|
||||
|
||||
-- 상태
|
||||
is_enabled BOOLEAN DEFAULT true,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 알림 기록
|
||||
CREATE TABLE fleet_alerts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
rule_id INTEGER REFERENCES fleet_alert_rules(id),
|
||||
device_id VARCHAR(50),
|
||||
|
||||
alert_type VARCHAR(50),
|
||||
message TEXT,
|
||||
severity VARCHAR(20), -- info, warning, critical
|
||||
|
||||
-- 해결 상태
|
||||
status VARCHAR(20) DEFAULT 'open', -- open, acknowledged, resolved
|
||||
resolved_at TIMESTAMPTZ,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API 설계
|
||||
|
||||
### 5.1 Device Management API
|
||||
|
||||
```yaml
|
||||
# 디바이스 등록
|
||||
POST /api/fleet/devices/register
|
||||
Request:
|
||||
device_id: string (required)
|
||||
company_code: string (required)
|
||||
device_name: string
|
||||
agent_version: string
|
||||
os_info: object
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
device_id: string
|
||||
mqtt_credentials:
|
||||
broker_url: string
|
||||
username: string
|
||||
password: string
|
||||
|
||||
# 디바이스 목록 조회
|
||||
GET /api/fleet/devices
|
||||
Query:
|
||||
company_code: string
|
||||
is_online: boolean
|
||||
device_group: string
|
||||
page: number
|
||||
limit: number
|
||||
Response:
|
||||
success: boolean
|
||||
data: Device[]
|
||||
pagination: { total, page, limit }
|
||||
|
||||
# 디바이스 상세 조회
|
||||
GET /api/fleet/devices/:deviceId
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
device: Device
|
||||
recent_heartbeats: Heartbeat[]
|
||||
recent_alerts: Alert[]
|
||||
```
|
||||
|
||||
### 5.2 Heartbeat API
|
||||
|
||||
```yaml
|
||||
# Heartbeat 전송
|
||||
POST /api/fleet/devices/:deviceId/heartbeat
|
||||
Request:
|
||||
status: string
|
||||
uptime_seconds: number
|
||||
metrics:
|
||||
cpu_percent: number
|
||||
memory_percent: number
|
||||
disk_percent: number
|
||||
containers:
|
||||
- name: string
|
||||
status: string
|
||||
version: string
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
commands: Command[] # 대기 중인 명령 반환
|
||||
```
|
||||
|
||||
### 5.3 Deployment API
|
||||
|
||||
```yaml
|
||||
# 배포 생성
|
||||
POST /api/fleet/deployments
|
||||
Request:
|
||||
release_id: number
|
||||
target_type: "all" | "group" | "specific"
|
||||
target_value: string
|
||||
rollout_strategy: "immediate" | "canary" | "scheduled"
|
||||
rollout_percentage: number
|
||||
scheduled_at: datetime
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
deployment_id: number
|
||||
estimated_devices: number
|
||||
|
||||
# 배포 상태 조회
|
||||
GET /api/fleet/deployments/:deploymentId
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
deployment: Deployment
|
||||
status_summary:
|
||||
pending: number
|
||||
in_progress: number
|
||||
completed: number
|
||||
failed: number
|
||||
device_statuses: DeploymentStatus[]
|
||||
|
||||
# 배포 롤백
|
||||
POST /api/fleet/deployments/:deploymentId/rollback
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
rollback_deployment_id: number
|
||||
```
|
||||
|
||||
### 5.4 Command API
|
||||
|
||||
```yaml
|
||||
# 원격 명령 전송
|
||||
POST /api/fleet/devices/:deviceId/commands
|
||||
Request:
|
||||
command_type: "update" | "restart" | "config" | "logs"
|
||||
payload: object
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
command_id: string
|
||||
status: "queued"
|
||||
|
||||
# 명령 결과 조회
|
||||
GET /api/fleet/commands/:commandId
|
||||
Response:
|
||||
success: boolean
|
||||
data:
|
||||
command_id: string
|
||||
status: "queued" | "sent" | "executing" | "completed" | "failed"
|
||||
result: object
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 기술 스택
|
||||
|
||||
### 6.1 글로벌 플랫폼
|
||||
|
||||
| 컴포넌트 | 기술 | 비고 |
|
||||
| :--- | :--- | :--- |
|
||||
| Fleet API | Node.js (기존 backend-node 확장) | 기존 코드 재사용 |
|
||||
| Message Broker | Mosquitto → EMQX | 단계적 전환 |
|
||||
| Device Registry | Redis | 빠른 조회 |
|
||||
| Database | PostgreSQL | 기존 DB 확장 |
|
||||
| Time-series DB | TimescaleDB | Heartbeat 저장 |
|
||||
| Monitoring | Prometheus + Grafana | 메트릭 시각화 |
|
||||
| Log | Loki | 로그 중앙화 |
|
||||
| Alert | AlertManager | 알림 관리 |
|
||||
|
||||
### 6.2 Fleet Agent
|
||||
|
||||
| 컴포넌트 | 기술 | 비고 |
|
||||
| :--- | :--- | :--- |
|
||||
| Runtime | Go 또는 Node.js | 가볍고 안정적 |
|
||||
| MQTT Client | Paho MQTT | 표준 라이브러리 |
|
||||
| Docker SDK | Docker API | 컨테이너 관리 |
|
||||
| Metrics | gopsutil | 시스템 메트릭 |
|
||||
|
||||
### 6.3 대시보드
|
||||
|
||||
| 컴포넌트 | 기술 | 비고 |
|
||||
| :--- | :--- | :--- |
|
||||
| UI Framework | Next.js (기존) | 기존 코드 확장 |
|
||||
| Real-time | Socket.io | 실시간 상태 |
|
||||
| Charts | Recharts | 메트릭 시각화 |
|
||||
| Map | Leaflet | 지역별 표시 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 일정 및 마일스톤
|
||||
|
||||
### 7.1 전체 일정
|
||||
|
||||
```
|
||||
2025 Q1 2025 Q2 2025 Q3
|
||||
│ │ │
|
||||
├── Phase 1 (2주) ─────────┤ │
|
||||
│ Device Registry │ │
|
||||
│ Heartbeat API │ │
|
||||
│ 기본 대시보드 │ │
|
||||
│ │ │
|
||||
│ ├── Phase 2 (4주) ──────────┤ │
|
||||
│ │ MQTT 브로커 │ │
|
||||
│ │ Agent v2 │ │
|
||||
│ │ 원격 명령 │ │
|
||||
│ │ │ │
|
||||
│ │ ├── Phase 3 (6주) ──────┤
|
||||
│ │ │ 버전 관리 │
|
||||
│ │ │ Canary 배포 │
|
||||
│ │ │ 롤백 │
|
||||
│ │ │ │
|
||||
```
|
||||
|
||||
### 7.2 상세 마일스톤
|
||||
|
||||
| 마일스톤 | 목표 | 완료 기준 | 예상 일정 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| M1 | Device Registry | 디바이스 등록/조회 API 완료 | 1주차 |
|
||||
| M2 | Heartbeat | 상태 보고 & 저장 완료 | 2주차 |
|
||||
| M3 | Basic Dashboard | 디바이스 목록 UI 완료 | 2주차 |
|
||||
| M4 | MQTT Setup | 브로커 설치 & 연결 테스트 | 4주차 |
|
||||
| M5 | Agent v2 | MQTT 기반 Agent 완료 | 6주차 |
|
||||
| M6 | Remote Command | 업데이트/재시작 명령 완료 | 8주차 |
|
||||
| M7 | Release Mgmt | 버전 관리 UI 완료 | 10주차 |
|
||||
| M8 | Canary Deploy | 단계적 배포 완료 | 14주차 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 리스크 및 대응
|
||||
|
||||
### 8.1 기술적 리스크
|
||||
|
||||
| 리스크 | 영향 | 확률 | 대응 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| MQTT 연결 불안정 | 높음 | 중간 | 자동 재연결, 오프라인 큐 |
|
||||
| 대량 동시 접속 | 높음 | 높음 | 클러스터링, 로드밸런싱 |
|
||||
| 보안 취약점 | 높음 | 낮음 | TLS 필수, 인증 강화 |
|
||||
| 네트워크 단절 | 중간 | 높음 | 로컬 캐시, 재전송 로직 |
|
||||
|
||||
### 8.2 운영 리스크
|
||||
|
||||
| 리스크 | 영향 | 확률 | 대응 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 잘못된 배포 | 높음 | 중간 | Canary 배포, 자동 롤백 |
|
||||
| 모니터링 누락 | 중간 | 중간 | 다중 알림 채널 |
|
||||
| 버전 파편화 | 중간 | 높음 | 강제 업데이트 정책 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 다음 단계
|
||||
|
||||
### 즉시 시작할 작업 (Phase 1)
|
||||
|
||||
1. **Device Registry 테이블 생성**
|
||||
- `fleet_devices` 테이블 마이그레이션
|
||||
|
||||
2. **Fleet API 엔드포인트 개발**
|
||||
- `POST /api/fleet/devices/register`
|
||||
- `POST /api/fleet/devices/:deviceId/heartbeat`
|
||||
- `GET /api/fleet/devices`
|
||||
|
||||
3. **Agent 기본 버전 개발**
|
||||
- Docker 이미지로 배포
|
||||
- 주기적 Heartbeat 전송
|
||||
|
||||
4. **대시보드 기본 화면**
|
||||
- 디바이스 목록
|
||||
- 온라인/오프라인 상태 표시
|
||||
|
||||
---
|
||||
|
||||
## 부록
|
||||
|
||||
### A. MQTT 토픽 설계
|
||||
|
||||
```
|
||||
vexplor/
|
||||
├── devices/
|
||||
│ ├── {device_id}/
|
||||
│ │ ├── status # 상태 보고 (Agent → Server)
|
||||
│ │ ├── metrics # 메트릭 보고 (Agent → Server)
|
||||
│ │ ├── commands # 명령 수신 (Server → Agent)
|
||||
│ │ └── responses # 명령 응답 (Agent → Server)
|
||||
│ │
|
||||
├── broadcasts/
|
||||
│ ├── all # 전체 공지
|
||||
│ └── groups/{group} # 그룹별 공지
|
||||
│
|
||||
└── system/
|
||||
├── announcements # 시스템 공지
|
||||
└── maintenance # 점검 알림
|
||||
```
|
||||
|
||||
### B. Agent 설정 파일
|
||||
|
||||
```yaml
|
||||
# /opt/vexplor/agent/config.yaml
|
||||
device:
|
||||
id: "SPIFOX-001"
|
||||
company_code: "SPIFOX"
|
||||
name: "스피폭스 메인 서버"
|
||||
|
||||
mqtt:
|
||||
broker: "mqtts://mqtt.vexplor.com:8883"
|
||||
username: "${MQTT_USERNAME}"
|
||||
password: "${MQTT_PASSWORD}"
|
||||
keepalive: 60
|
||||
reconnect_interval: 5
|
||||
|
||||
heartbeat:
|
||||
interval: 30 # seconds
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
interval: 300 # 5 minutes
|
||||
collect:
|
||||
- cpu
|
||||
- memory
|
||||
- disk
|
||||
- network
|
||||
|
||||
docker:
|
||||
socket: "/var/run/docker.sock"
|
||||
managed_containers:
|
||||
- vexplor-backend
|
||||
- vexplor-frontend
|
||||
- vexplor-db
|
||||
```
|
||||
|
||||
### C. 참고 자료
|
||||
|
||||
- [EMQX Documentation](https://docs.emqx.com/)
|
||||
- [Eclipse Mosquitto](https://mosquitto.org/)
|
||||
- [AWS IoT Device Management](https://aws.amazon.com/iot-device-management/)
|
||||
- [Google Cloud IoT Core](https://cloud.google.com/iot-core)
|
||||
- [HashiCorp Nomad](https://www.nomadproject.io/)
|
||||
|
||||
|
Before Width: | Height: | Size: 1012 KiB After Width: | Height: | Size: 1012 KiB |
BIN
digitalTwin/디지털트윈 아키텍쳐_v4.png
Normal file
BIN
digitalTwin/디지털트윈 아키텍쳐_v4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 MiB |
Reference in New Issue
Block a user