# 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/)

