초기 커밋
This commit is contained in:
595
docs/ARCHITECTURE.md
Normal file
595
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,595 @@
|
||||
# core-api 아키텍처 문서
|
||||
|
||||
## 1. 개요
|
||||
|
||||
IoT 임베디드 디바이스 통신, 사용자/관리자 관리, 모니터링, 데이터 분석을 지원하는 FastAPI 기반 통합 백엔드 서버이다. 향후 MSA 전환을 고려한 논리적 계층 분리를 핵심 설계 원칙으로 한다.
|
||||
|
||||
**주요 특징:**
|
||||
- Flutter 웹/앱 프론트엔드 연동
|
||||
- MariaDB + MongoDB 듀얼 DB
|
||||
- MQTT + Socket.IO 실시간 통신
|
||||
- Celery 비동기 태스크 처리
|
||||
- RBAC 기반 접근 제어
|
||||
|
||||
---
|
||||
|
||||
## 2. 계층 아키텍처
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ASGI Entry Point │
|
||||
│ Socket.IO ASGIApp (최외곽 래퍼) │
|
||||
│ app/asgi.py │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Middleware Stack │
|
||||
│ RequestIDMiddleware → RequestLoggingMiddleware → CORS │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ API Layer │
|
||||
│ app/api/v1/endpoints/*.py │
|
||||
│ auth │ users │ devices │ monitoring │ analytics │ system│
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Service Layer │
|
||||
│ app/services/*.py │
|
||||
│ AuthService │ UserService │ DeviceService │ ... │
|
||||
├───────────────────────┬─────────────────────────────────────┤
|
||||
│ Repository Layer │ Communication Layer │
|
||||
│ app/repositories/*.py │ app/communication/ │
|
||||
│ BaseRepository[T] │ mqtt/ │ socketio/ │ external/ │
|
||||
├───────────────────────┴─────────────────────────────────────┤
|
||||
│ DB Layer │
|
||||
│ MariaDB │ MongoDB │ Redis │
|
||||
│ app/db/mariadb.py │ mongodb.py │ redis.py │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ │
|
||||
┌───────┴───────┐ ┌────────┴────────┐
|
||||
│ Celery Tasks │ │ Data Processing │
|
||||
│ app/tasks/*.py │ │ app/processing/ │
|
||||
└────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
### 의존성 규칙
|
||||
|
||||
```
|
||||
API Layer → Service Layer → Repository Layer → DB Layer
|
||||
│
|
||||
Communication Layer (MQTT, Socket.IO, External API)
|
||||
│
|
||||
Task Layer (Celery)
|
||||
```
|
||||
|
||||
- 각 계층은 **바로 아래 계층만** 의존한다.
|
||||
- 도메인 간 직접 Repository 호출을 금지하고, 반드시 Service 인터페이스를 통해 통신한다.
|
||||
- 이 규칙을 지키면 향후 MSA 전환 시 Service 인터페이스를 gRPC/HTTP 호출로 교체하는 것만으로 분리가 가능하다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 디렉토리 구조
|
||||
|
||||
```
|
||||
python-api/
|
||||
├── pyproject.toml # 의존성 + 빌드 설정
|
||||
├── .env.example # 환경변수 템플릿
|
||||
├── alembic.ini # Alembic 마이그레이션 설정
|
||||
├── Dockerfile # 앱 이미지
|
||||
├── Dockerfile.worker # Celery 워커 이미지
|
||||
├── docker-compose.yml # 개발 환경
|
||||
├── docker-compose.prod.yml # 프로덕션 오버라이드
|
||||
│
|
||||
├── alembic/ # DB 마이그레이션
|
||||
│ ├── env.py
|
||||
│ ├── script.py.mako
|
||||
│ └── versions/
|
||||
│
|
||||
├── scripts/ # 운영 스크립트
|
||||
│ ├── init_db.py # DB 시드 데이터
|
||||
│ ├── create_superuser.py # 관리자 계정 생성
|
||||
│ ├── run_dev.sh
|
||||
│ ├── run_worker.sh
|
||||
│ └── run_beat.sh
|
||||
│
|
||||
├── docker/
|
||||
│ └── mosquitto/mosquitto.conf
|
||||
│
|
||||
├── tests/ # 테스트
|
||||
│ ├── conftest.py
|
||||
│ ├── unit/
|
||||
│ ├── integration/
|
||||
│ └── e2e/
|
||||
│
|
||||
├── docs/ # 문서
|
||||
│
|
||||
└── app/ # 애플리케이션 루트
|
||||
├── main.py # FastAPI 앱 팩토리 + 라이프사이클
|
||||
├── asgi.py # ASGI 엔트리포인트
|
||||
├── core/ # 횡단 관심사
|
||||
├── middleware/ # HTTP 미들웨어
|
||||
├── db/ # DB 연결/세션
|
||||
├── models/ # DB 모델 (mariadb/ + mongodb/)
|
||||
├── schemas/ # Pydantic DTO
|
||||
├── repositories/ # 데이터 접근 계층
|
||||
├── services/ # 비즈니스 로직
|
||||
├── api/ # API 라우터
|
||||
├── admin/ # SQLAdmin 관리자 패널
|
||||
├── communication/ # MQTT, Socket.IO, 외부 API
|
||||
├── tasks/ # Celery 비동기 태스크
|
||||
├── processing/ # 데이터 분석 파이프라인
|
||||
└── utils/ # 범용 유틸리티
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 기술 스택
|
||||
|
||||
| 카테고리 | 기술 | 용도 |
|
||||
|---------|------|------|
|
||||
| **Web Framework** | FastAPI + Uvicorn | ASGI 비동기 웹 서버 |
|
||||
| **MariaDB ORM** | SQLModel + SQLAlchemy(async) + aiomysql | 관계형 DB 비동기 ORM |
|
||||
| **Migration** | Alembic + pymysql | DB 스키마 마이그레이션 |
|
||||
| **MongoDB ODM** | Beanie + Motor | 문서 DB 비동기 ODM |
|
||||
| **Cache/Queue** | Redis (hiredis) | 캐싱 + Celery 브로커/백엔드 |
|
||||
| **Auth** | python-jose + passlib[bcrypt] | JWT 토큰 + 비밀번호 해싱 |
|
||||
| **MQTT** | fastapi-mqtt | IoT 디바이스 양방향 통신 |
|
||||
| **WebSocket** | python-socketio | 실시간 프론트엔드 푸시 |
|
||||
| **Background** | Celery + Flower | 비동기 태스크 + 모니터링 |
|
||||
| **Admin** | SQLAdmin | 관리자 대시보드 |
|
||||
| **Data** | Polars + Pandas + NumPy | 데이터 분석/집계/통계 |
|
||||
| **Logging** | structlog | 구조화 로깅 (JSON/Console) |
|
||||
| **Test** | pytest + pytest-asyncio + factory-boy | 테스트 프레임워크 |
|
||||
| **Lint** | Ruff + mypy + pre-commit | 코드 품질 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 데이터 모델
|
||||
|
||||
### 5.1 MariaDB (관계형 — SQLModel)
|
||||
|
||||
```
|
||||
┌──────────────┐ 1:1 ┌──────────────┐
|
||||
│ User │────────────▶│ UserProfile │
|
||||
│──────────────│ │──────────────│
|
||||
│ id (PK) │ │ user_id (FK) │
|
||||
│ email │ │ full_name │
|
||||
│ hashed_pwd │ │ phone │
|
||||
│ role │ │ organization │
|
||||
│ is_active │ │ avatar_url │
|
||||
│ is_verified │ └───────────────┘
|
||||
│ last_login_at│
|
||||
└──────┬───────┘
|
||||
│ 1:N
|
||||
▼
|
||||
┌──────────────┐ ┌───────────────┐
|
||||
│ RefreshToken │ │ OAuthAccount │
|
||||
│──────────────│ │───────────────│
|
||||
│ user_id (FK) │ │ user_id (FK) │
|
||||
│ token │ │ provider │
|
||||
│ expires_at │ │ provider_uid │
|
||||
│ is_revoked │ │ access_token │
|
||||
└──────────────┘ └───────────────┘
|
||||
|
||||
┌──────────────┐ N:1 ┌──────────────┐
|
||||
│ Device │────────────▶│ DeviceGroup │
|
||||
│──────────────│ │──────────────│
|
||||
│ device_uid │ │ name │
|
||||
│ name │ │ description │
|
||||
│ device_type │ └──────────────┘
|
||||
│ status │
|
||||
│ firmware_ver │
|
||||
│ ip_address │
|
||||
│ owner_id(FK) │
|
||||
│ last_seen_at │
|
||||
└──────────────┘
|
||||
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ AlertRule │ │ Alert │
|
||||
│──────────────│ │──────────────│
|
||||
│ metric │◀────────────│ rule_id (FK) │
|
||||
│ condition │ │ device_id(FK)│
|
||||
│ threshold │ │ severity │
|
||||
│ severity │ │ message │
|
||||
│ is_enabled │ │ is_ack │
|
||||
└──────────────┘ └──────────────┘
|
||||
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ SystemConfig │ │ AuditLog │
|
||||
│──────────────│ │──────────────│
|
||||
│ key (unique) │ │ user_id (FK) │
|
||||
│ value │ │ action │
|
||||
│ is_secret │ │ resource_type│
|
||||
└──────────────┘ │ details │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**공통 Mixin:**
|
||||
- `TimestampMixin` — `created_at`, `updated_at` (서버 기본값 + 자동 갱신)
|
||||
- `SoftDeleteMixin` — `is_deleted`, `deleted_at` (논리 삭제)
|
||||
|
||||
### 5.2 MongoDB (문서형 — Beanie)
|
||||
|
||||
| Collection | 주요 필드 | 인덱스 | 비고 |
|
||||
|-----------|----------|--------|------|
|
||||
| `device_logs` | device_id, event_type, payload, timestamp | device_id, event_type, timestamp(desc) | TTL: 90일 |
|
||||
| `telemetry_data` | device_id, metrics(dict), timestamp | device_id, timestamp(desc), 복합(device_id+timestamp) | 시계열 |
|
||||
| `analytics_results` | analysis_type, parameters, result, device_id, period | analysis_type, device_id, created_at(desc) | 분석 결과 |
|
||||
| `notifications` | user_id, title, message, type, is_read | user_id, 복합(user_id+is_read), created_at(desc) | 사용자 알림 |
|
||||
|
||||
---
|
||||
|
||||
## 6. API 엔드포인트
|
||||
|
||||
### 6.1 인증 (`/api/v1/auth`)
|
||||
|
||||
| Method | Path | 설명 | 인증 |
|
||||
|--------|------|------|------|
|
||||
| POST | `/register` | 회원가입 → 토큰 반환 | - |
|
||||
| POST | `/login` | 로그인 → 토큰 반환 | - |
|
||||
| POST | `/refresh` | 리프레시 토큰으로 갱신 | - |
|
||||
| POST | `/logout` | 모든 리프레시 토큰 폐기 | Bearer |
|
||||
|
||||
### 6.2 사용자 (`/api/v1/users`)
|
||||
|
||||
| Method | Path | 설명 | 권한 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/me` | 내 정보 조회 | 인증됨 |
|
||||
| PATCH | `/me` | 내 프로필 수정 | 인증됨 |
|
||||
| GET | `/` | 사용자 목록 (페이징) | SUPERADMIN, ADMIN |
|
||||
| GET | `/{user_id}` | 사용자 상세 | SUPERADMIN, ADMIN |
|
||||
| POST | `/` | 사용자 생성 | SUPERADMIN, ADMIN |
|
||||
| PATCH | `/{user_id}` | 사용자 수정 | SUPERADMIN, ADMIN |
|
||||
| DELETE | `/{user_id}` | 사용자 삭제 (소프트) | SUPERADMIN, ADMIN |
|
||||
|
||||
### 6.3 디바이스 (`/api/v1/devices`)
|
||||
|
||||
| Method | Path | 설명 | 권한 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/` | 디바이스 목록 (페이징) | 인증됨 |
|
||||
| GET | `/{device_id}` | 디바이스 상세 | 인증됨 |
|
||||
| POST | `/` | 디바이스 등록 | SUPERADMIN, ADMIN, MANAGER |
|
||||
| PATCH | `/{device_id}` | 디바이스 수정 | SUPERADMIN, ADMIN, MANAGER |
|
||||
| DELETE | `/{device_id}` | 디바이스 삭제 (소프트) | SUPERADMIN, ADMIN |
|
||||
|
||||
### 6.4 모니터링 (`/api/v1/monitoring`)
|
||||
|
||||
| Method | Path | 설명 | 권한 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/health` | 시스템 상태 상세 | MANAGEMENT |
|
||||
| GET | `/alerts` | 미확인 알림 목록 | MANAGEMENT |
|
||||
| POST | `/alerts/{id}/acknowledge` | 알림 확인 처리 | 인증됨 |
|
||||
| GET | `/alert-rules` | 알림 규칙 목록 | MANAGEMENT |
|
||||
| POST | `/alert-rules` | 알림 규칙 생성 | 인증됨 |
|
||||
|
||||
### 6.5 분석 (`/api/v1/analytics`)
|
||||
|
||||
| Method | Path | 설명 | 권한 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/telemetry/{device_id}` | 텔레메트리 집계 | MANAGEMENT |
|
||||
| POST | `/reports/{device_id}` | 종합 리포트 생성 | MANAGEMENT |
|
||||
| GET | `/status/{device_id}` | 디바이스 상태 분석 | MANAGEMENT |
|
||||
| GET | `/trends/{device_id}` | 추세 분석 | MANAGEMENT |
|
||||
| GET | `/results` | 분석 결과 조회 | MANAGEMENT |
|
||||
|
||||
### 6.6 시스템 (`/api/v1/system`)
|
||||
|
||||
| Method | Path | 설명 | 권한 |
|
||||
|--------|------|------|------|
|
||||
| GET | `/health` | 헬스체크 | - |
|
||||
| GET | `/info` | 시스템 정보 | SUPERADMIN |
|
||||
|
||||
---
|
||||
|
||||
## 7. 인증/인가 체계
|
||||
|
||||
### 7.1 JWT 토큰 흐름
|
||||
|
||||
```
|
||||
클라이언트 서버
|
||||
│ │
|
||||
│─── POST /auth/login ──────────▶│
|
||||
│ {email, password} │
|
||||
│ │── 비밀번호 검증
|
||||
│ │── Access Token 생성 (30분)
|
||||
│ │── Refresh Token 생성 (7일)
|
||||
│ │── Refresh Token DB 저장
|
||||
│◀── {access_token, │
|
||||
│ refresh_token} ────────────│
|
||||
│ │
|
||||
│─── GET /api/v1/users/me ──────▶│
|
||||
│ Authorization: Bearer {AT} │── decode_token()
|
||||
│ │── get_current_user_payload()
|
||||
│◀── {user data} ───────────────│
|
||||
│ │
|
||||
│─── POST /auth/refresh ────────▶│
|
||||
│ {refresh_token} │── 기존 RT 폐기
|
||||
│ │── 새 AT + RT 발급
|
||||
│◀── {new tokens} ──────────────│
|
||||
```
|
||||
|
||||
### 7.2 역할 기반 접근 제어 (RBAC)
|
||||
|
||||
```
|
||||
SUPERADMIN (4) ─── 전체 시스템 관리, 시스템 설정
|
||||
│
|
||||
ADMIN (3) ─── 사용자/디바이스 관리, 삭제 권한
|
||||
│
|
||||
MANAGER (2) ─── 디바이스 등록/수정, 모니터링, 분석
|
||||
│
|
||||
USER (1) ─── 자기 프로필, 디바이스 조회
|
||||
│
|
||||
DEVICE (0) ─── 디바이스 전용 (MQTT 인증)
|
||||
```
|
||||
|
||||
- `require_role(*roles)` — 허용된 역할만 접근 가능한 Dependency
|
||||
- `can_manage_user(actor_role, target_role)` — 상위 역할만 하위 역할 관리 가능
|
||||
|
||||
---
|
||||
|
||||
## 8. 실시간 통신
|
||||
|
||||
### 8.1 MQTT (IoT 디바이스 ↔ 서버)
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────────┐ ┌──────────┐
|
||||
│ Device │──MQTT───▶│ Mosquitto │──────────▶│ Server │
|
||||
│ │◀──MQTT───│ (Broker) │◀──────────│ │
|
||||
└──────────┘ └──────────────┘ └──────────┘
|
||||
```
|
||||
|
||||
**토픽 구조:**
|
||||
|
||||
| 방향 | 토픽 패턴 | 용도 |
|
||||
|------|----------|------|
|
||||
| Device → Server | `devices/{uid}/telemetry` | 센서 데이터 전송 |
|
||||
| Device → Server | `devices/{uid}/status` | 상태 변경 알림 |
|
||||
| Device → Server | `devices/{uid}/log` | 이벤트 로그 |
|
||||
| Device → Server | `devices/{uid}/response` | 명령 응답 |
|
||||
| Server → Device | `devices/{uid}/command` | 원격 명령 |
|
||||
| Server → Device | `devices/{uid}/config` | 설정 변경 |
|
||||
| Server → Device | `devices/{uid}/ota` | 펌웨어 업데이트 |
|
||||
|
||||
**데이터 파이프라인:**
|
||||
```
|
||||
MQTT 수신 → JSON 파싱 → MongoDB 저장 → Socket.IO 브로드캐스트
|
||||
```
|
||||
|
||||
### 8.2 Socket.IO (서버 → 프론트엔드)
|
||||
|
||||
| 네임스페이스 | 이벤트 | 설명 |
|
||||
|------------|--------|------|
|
||||
| `/monitoring` | `telemetry` | 실시간 텔레메트리 데이터 |
|
||||
| `/monitoring` | `device_status` | 디바이스 상태 변경 |
|
||||
| `/device` | `device_response` | 디바이스 명령 응답 |
|
||||
| `/device` | `send_command` | 클라이언트→디바이스 명령 전달 |
|
||||
| `/notification` | `notification` | 사용자 알림 푸시 |
|
||||
|
||||
**Room 기반 구독:**
|
||||
- `device:{device_uid}` — 특정 디바이스 모니터링
|
||||
- `user:{user_id}` — 특정 사용자 알림
|
||||
|
||||
---
|
||||
|
||||
## 9. 비동기 태스크 (Celery)
|
||||
|
||||
### 9.1 큐 구성
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Redis │ ← Broker (redis://...6379/1)
|
||||
│ (Broker) │ ← Result Backend (redis://...6379/2)
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌────┴────────────────────────────────┐
|
||||
│ Celery Workers │
|
||||
├─────────┬───────────┬───────────────┤
|
||||
│ default │ analytics │ notifications │ devices │
|
||||
│ queue │ queue │ queue │ queue │
|
||||
├─────────┼───────────┼───────────────┤
|
||||
│ 토큰정리 │ 일간분석 │ 푸시알림 │ 헬스체크 │
|
||||
│ 이메일 │ 디바이스분석 │ 대량알림 │ OTA배치 │
|
||||
└─────────┴───────────┴───────────────┘
|
||||
```
|
||||
|
||||
### 9.2 Beat 스케줄 (정기 실행)
|
||||
|
||||
| 태스크 | 스케줄 | 큐 | 설명 |
|
||||
|--------|--------|-----|------|
|
||||
| `cleanup_expired_tokens` | 매일 03:00 | default | 만료/폐기된 리프레시 토큰 삭제 |
|
||||
| `check_device_health` | 5분마다 | devices | 10분 이상 미응답 디바이스를 OFFLINE 처리 |
|
||||
| `run_daily_analytics` | 매일 01:00 | analytics | 전일 텔레메트리 데이터 집계 및 저장 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 미들웨어 파이프라인
|
||||
|
||||
요청은 아래 순서로 미들웨어를 통과한다:
|
||||
|
||||
```
|
||||
요청 ──▶ RequestIDMiddleware ──▶ RequestLoggingMiddleware ──▶ CORS ──▶ FastAPI Router
|
||||
│ │
|
||||
│ X-Request-ID 생성/전파 │ method, path, status, elapsed_ms 로깅
|
||||
│ structlog 컨텍스트 바인딩 │
|
||||
▼ ▼
|
||||
응답 ◀── X-Request-ID 헤더 추가 ◀── 로그 기록 ◀────────────────────── 핸들러 응답
|
||||
```
|
||||
|
||||
**RateLimitMiddleware** (선택 사용):
|
||||
- Redis 기반 IP별 속도 제한
|
||||
- 기본값: 100 요청/60초
|
||||
- `/docs`, `/redoc` 경로 제외
|
||||
|
||||
---
|
||||
|
||||
## 11. 데이터 분석 파이프라인
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌────────────────┐
|
||||
│ TelemetryData │────▶│ Polars/Pandas │────▶│ AnalyticsResult│
|
||||
│ (MongoDB) │ │ Processing │ │ (MongoDB) │
|
||||
└─────────────────┘ └──────────────────┘ └────────────────┘
|
||||
│
|
||||
┌─────────┴──────────┐
|
||||
│ │
|
||||
┌──────┴──────┐ ┌──────┴──────┐
|
||||
│ Aggregation │ │ Analysis │
|
||||
│ (Polars) │ │ (NumPy) │
|
||||
│ │ │ │
|
||||
│ - resample │ │ - trend │
|
||||
│ - group_by │ │ - anomaly │
|
||||
│ - mean/sum │ │ - percentile│
|
||||
└─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
| 모듈 | 기능 |
|
||||
|------|------|
|
||||
| `telemetry_pipeline` | 시간 간격별 텔레메트리 집계 (Polars group_by_dynamic) |
|
||||
| `report_pipeline` | 디바이스 종합 리포트 생성 (상태 + 추세) |
|
||||
| `device_analyzer` | 디바이스 상태 변경 분석, 가동률 계산 |
|
||||
| `trend_analyzer` | 선형 회귀 기반 추세 분석 (NumPy polyfit) |
|
||||
| `statistics` | 이동평균, Z-score 이상치 탐지, 백분위 통계 |
|
||||
|
||||
---
|
||||
|
||||
## 12. MSA 전환 전략
|
||||
|
||||
현재 모놀리식 구조에서 각 도메인을 독립 서비스로 분리할 수 있는 논리적 경계가 이미 설정되어 있다.
|
||||
|
||||
| 도메인 | 현재 패키지 | 향후 MSA 서비스 | 주 DB |
|
||||
|--------|------------|----------------|-------|
|
||||
| auth | auth_service + auth_repo | Auth Service | MariaDB + Redis |
|
||||
| users | user_service + user_repo | User Service | MariaDB |
|
||||
| devices | device_service + device_repo | Device Service | MariaDB + MongoDB |
|
||||
| monitoring | monitoring_service + monitoring_repo | Monitoring Service | MongoDB + Redis |
|
||||
| analytics | analytics_service + analytics_repo | Analytics Service | MongoDB |
|
||||
| notification | notification_service + socketio | Notification Service | Redis + MongoDB |
|
||||
|
||||
**전환 시 변경점:**
|
||||
1. Service 간 호출을 HTTP/gRPC 클라이언트로 교체
|
||||
2. 각 서비스별 독립 DB 인스턴스 할당
|
||||
3. 이벤트 버스(Kafka/RabbitMQ)로 서비스 간 비동기 통신
|
||||
4. API Gateway 도입 (인증/라우팅 통합)
|
||||
|
||||
---
|
||||
|
||||
## 13. 배포 구성
|
||||
|
||||
### 13.1 Docker 서비스
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Mosquitto │:1883 (MQTT)
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌──────────┐ ┌──────┴──────┐ ┌──────────┐
|
||||
│ Redis │:6379 ◀─│ App │:8000 ──▶│ MariaDB │ (호스트)
|
||||
└────┬─────┘ │ (FastAPI) │ └──────────┘
|
||||
│ └──────┬──────┘ ┌──────────┐
|
||||
│ │ ────▶│ MongoDB │ (호스트)
|
||||
│ ┌──────┴──────┐ └──────────┘
|
||||
├──────────────│ Worker │
|
||||
│ │ (Celery) │
|
||||
│ └─────────────┘
|
||||
│ ┌─────────────┐
|
||||
├──────────────│ Beat │
|
||||
│ │ (Scheduler) │
|
||||
│ └─────────────┘
|
||||
│ ┌─────────────┐
|
||||
└──────────────│ Flower │:5555 (모니터링)
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
- MariaDB/MongoDB는 **호스트에 직접 설치** (Docker 외부)
|
||||
- App, Worker, Beat, Flower, Redis, Mosquitto는 **Docker 컨테이너**로 관리
|
||||
|
||||
### 13.2 환경별 차이
|
||||
|
||||
| 항목 | 개발 (docker-compose.yml) | 프로덕션 (docker-compose.prod.yml) |
|
||||
|------|--------------------------|-----------------------------------|
|
||||
| App 워커 수 | 1 (reload 모드) | 4 |
|
||||
| Celery 동시성 | 2 | 4 |
|
||||
| Worker 레플리카 | 1 | 2 |
|
||||
| 로그 레벨 | info | warning |
|
||||
| Flower 인증 | 없음 | basic_auth |
|
||||
| 볼륨 마운트 | 소스 코드 (.:/app) | 이미지 내장 |
|
||||
|
||||
---
|
||||
|
||||
## 14. 실행 방법
|
||||
|
||||
### 개발 환경
|
||||
|
||||
```bash
|
||||
# 1. 환경변수 설정
|
||||
cp .env.example .env
|
||||
# .env 파일에서 DB 접속 정보 등 수정
|
||||
|
||||
# 2. 의존성 설치
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# 3. DB 마이그레이션
|
||||
alembic upgrade head
|
||||
|
||||
# 4. 시드 데이터
|
||||
python -m scripts.init_db
|
||||
|
||||
# 5. 슈퍼관리자 생성
|
||||
python -m scripts.create_superuser admin@example.com password123
|
||||
|
||||
# 6. 인프라 (Redis + Mosquitto)
|
||||
docker-compose up -d redis mosquitto
|
||||
|
||||
# 7. 앱 서버 실행
|
||||
uvicorn app.asgi:app --reload
|
||||
|
||||
# 8. Celery 워커 (별도 터미널)
|
||||
celery -A app.tasks.celery_app worker --loglevel=info -Q default,analytics,notifications,devices
|
||||
|
||||
# 9. Celery 스케줄러 (별도 터미널)
|
||||
celery -A app.tasks.celery_app beat --loglevel=info
|
||||
```
|
||||
|
||||
### Docker 전체 스택
|
||||
|
||||
```bash
|
||||
# 개발
|
||||
docker-compose up -d
|
||||
|
||||
# 프로덕션
|
||||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
```
|
||||
|
||||
### 검증
|
||||
|
||||
```bash
|
||||
# 헬스체크
|
||||
curl http://localhost:8000/api/v1/system/health
|
||||
|
||||
# Swagger UI
|
||||
open http://localhost:8000/docs
|
||||
|
||||
# Flower (Celery 모니터링)
|
||||
open http://localhost:5555
|
||||
|
||||
# SQLAdmin (관리자)
|
||||
open http://localhost:8000/admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 15. 테스트
|
||||
|
||||
```bash
|
||||
# 전체 테스트
|
||||
pytest tests/ -v
|
||||
|
||||
# 커버리지
|
||||
pytest tests/ -v --cov=app --cov-report=html
|
||||
|
||||
# 단위 테스트만
|
||||
pytest tests/unit/ -v
|
||||
|
||||
# 통합 테스트만
|
||||
pytest tests/integration/ -v
|
||||
```
|
||||
|
||||
**테스트 구조:**
|
||||
- `tests/unit/` — 순수 함수 테스트 (보안, 검증, 통계, 권한)
|
||||
- `tests/integration/` — API 엔드포인트 + DB 연동 테스트
|
||||
- `tests/e2e/` — 전체 CRUD 플로우 테스트
|
||||
Reference in New Issue
Block a user