Files
python-api/docs/ARCHITECTURE.md
2026-03-01 07:44:19 +09:00

26 KiB

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:

  • TimestampMixincreated_at, updated_at (서버 기본값 + 자동 갱신)
  • SoftDeleteMixinis_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. 실행 방법

개발 환경

# 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 전체 스택

# 개발
docker-compose up -d

# 프로덕션
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

검증

# 헬스체크
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. 테스트

# 전체 테스트
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 플로우 테스트