diff --git a/digitalTwin/architecture-v4.md b/digitalTwin/architecture-v4.md new file mode 100644 index 00000000..96e32ef1 --- /dev/null +++ b/digitalTwin/architecture-v4.md @@ -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["💻 AAS 통합 대시보드
(React/Next.js)
• 중앙 모니터링
• Fleet 관리 UI"] + Global_API["🌐 글로벌 API 게이트웨이
• 사용자 인증 (Auth)
• 고객사 라우팅
• Fleet API"] + + subgraph Fleet_System["🎛️ Fleet Management"] + Fleet_Manager["📊 Fleet Manager
• Device Registry
• 배포 오케스트레이션
• 상태 모니터링"] + MQTT_Broker["📡 MQTT Broker
(Mosquitto/EMQX)
• 실시간 통신
• 10,000+ 연결"] + Monitoring["📈 Monitoring
(Prometheus/Grafana)
• 메트릭 수집
• 알림"] + end + + Update_Server["🚀 배포/업데이트 매니저
• Docker 이미지 레지스트리 (Harbor)
• 버전 관리
• Canary 배포"] + end + + subgraph Local_Server["스피폭스 사내 서버 (Local Server)"] + Fleet_Agent_A["🤖 Fleet Agent
• MQTT 연결
• Heartbeat (30초)
• 원격 명령 실행
• Docker 관리"] + VEX_Engine["VEX Flow 엔진
데이터 수집/처리"] + Customer_DB[("사내 통합 DB
(모든 데이터 보유)")] + Watchtower_A["🐋 Watchtower
이미지 자동 업데이트"] + end + + subgraph Edge_Internals["🖥️ 엣지 디바이스 (Store & Forward)"] + Edge_Collector["수집/가공
(Python)"] + Edge_Buffer[("💾 로컬 버퍼
(TimescaleDB)
단절 시 임시 저장")] + Edge_Sender["📤 전송 매니저
(Priority Queue)"] + Edge_Retry_Queue[("🕒 재전송 큐
(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["🤖 Fleet Agent"] + Watchtower_B["🐋 Watchtower"] + end + + subgraph Customer_B["🏭 고객사 B (확장 예정)"] + Local_Server_B + end + + subgraph Local_Server_N["고객사 N 사내 서버"] + Fleet_Agent_N["🤖 Fleet Agent"] + 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 +``` + diff --git a/digitalTwin/fleet-management-plan.md b/digitalTwin/fleet-management-plan.md new file mode 100644 index 00000000..e80aaab9 --- /dev/null +++ b/digitalTwin/fleet-management-plan.md @@ -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/) + diff --git a/디지털트윈 아키텍쳐_v3.png b/digitalTwin/디지털트윈 아키텍쳐_v3.png similarity index 100% rename from 디지털트윈 아키텍쳐_v3.png rename to digitalTwin/디지털트윈 아키텍쳐_v3.png diff --git a/digitalTwin/디지털트윈 아키텍쳐_v4.png b/digitalTwin/디지털트윈 아키텍쳐_v4.png new file mode 100644 index 00000000..62d72b47 Binary files /dev/null and b/digitalTwin/디지털트윈 아키텍쳐_v4.png differ