시작하기

플랫폼 아키텍처

에너지 관리 시스템은 하나의 거대한 앱보다 역할이 다른 몇 개의 서비스로 나누는 편이 운영하기 좋습니다. 수집은 24시간 멈추면 안 되고, 화면은 자주 배포하고, 보고서는 정해진 시각에 무겁게 돕니다. 성격이 다르니 배포 단위도 다르게 가져갑니다.


1. 전체 구성

[현장 계기] ──Modbus/MQTT/TCP──> [수집 서비스 (DAQ)]
                                        │ insert
                                        ▼
[웹 (SPA)] ──HTTP──> [API 서버] ───> [DB (MariaDB)] <─── [보고서 서비스]
                                        ▲                       │
                                        │ 집계 배치               ▼
                                  [집계/절감 배치]         [파일 저장소 (S3/MinIO)]
구성 요소역할기술 예시
수집 (DAQ)계기 폴링/구독, 원시 저장, 실시간 알람Python, pymodbus, paho-mqtt, APScheduler
집계 배치시간/일/월 집계, 절감 계산Python 배치, SQL
API마스터 CRUD, 조회, 권한Node.js Express, Sequelize
웹대시보드, 관리 화면React, TypeScript, Chart.js
보고서스케줄, HTML/PDF 생성FastAPI, Jinja2, WeasyPrint
DB마스터, 원시, 집계, 메타MariaDB / MySQL
저장소보고서 파일, 이미지S3, MinIO, 로컬

2. 데이터 계층 분리

데이터 성격별로 테이블을 나누는 것이 성능과 운영의 핵심입니다.

계층테이블 예시특징
마스터company, plant, meter, collector적고, 자주 안 바뀜, soft delete
원시power_measurement, flow_measurement매우 많음, insert 위주
집계summary, baseline_saving조회 위주, 재계산 가능
운영alarm_event, report이벤트, 이력
설정common_code, tariff, report_schedule관리자 변경
  • 화면은 원시 테이블을 직접 조회하지 않습니다. 최근 1시간 실시간 차트 정도만 예외
  • 집계 테이블은 언제든 원시에서 다시 만들 수 있어야 합니다

3. 원시 데이터 규모

1분 주기 계기 500대 기준:

500 × 60 × 24 = 720,000 건/일
720,000 × 365 ≈ 2.6억 건/년
  • 월 단위 파티션 (PARTITION BY RANGE (TO_DAYS(measured_at)))
  • (meter_id, measured_at) 복합 인덱스 + unique
  • 보존 정책: 원시 1~3년, 집계 영구
  • 규모가 더 커지면 TimescaleDB, InfluxDB 같은 시계열 DB를 원시 계층에만 도입

4. 공유 DB vs 서비스별 DB

여러 서비스가 같은 DB를 공유하는 구조는 초기에 빠르지만 경계가 흐려집니다.

방식장점단점
공유 DB개발 빠름, 조인 쉬움스키마 변경 시 전 서비스 영향
서비스별 DB독립 배포데이터 동기화 필요

현실적인 절충:

  • 테이블 쓰기 소유권을 서비스별로 정합니다 (원시/집계는 DAQ, 마스터는 API, 보고서 메타는 보고서 서비스)
  • 다른 서비스는 읽기만 합니다
  • 스키마 변경은 마이그레이션 도구 하나로 관리합니다
  • ORM 모델이 언어별로 중복되므로 컬럼 변경 시 체크리스트로 동기화합니다

5. 실시간 데이터

대시보드 "현재 전력"을 DB 폴링으로 구현하면 부하가 큽니다.

DAQ → Redis (meter:{id}:latest) → API → WebSocket/SSE → 웹
  • 최신값은 Redis에 TTL과 함께 저장
  • 화면은 SSE나 WebSocket으로 구독, 또는 5~10초 폴링
  • TTL이 지나면 "통신 없음"으로 표시

6. 권한과 멀티테넌시

  • 모든 데이터에 company_id를 두고 API에서 강제 필터링
  • 역할(role) - 권한(permission) - 메뉴(menu) 구조로 화면 접근 제어
  • 사업장 단위 권한이 필요하면 member-plant 매핑을 추가
  • 보고서 서비스도 같은 토큰을 검증해야 합니다. 내부 서비스라고 인증을 빼면 파일 URL이 그대로 노출됩니다

7. 시간과 타임존

에너지 시스템 버그의 상당수는 시간입니다.

  • DB, 서버, 컨테이너, 게이트웨이의 타임존을 하나로 통일 (KST 또는 UTC + 변환 규칙)
  • 언어별 기본 동작이 다릅니다 (Node Date, Python naive datetime, MariaDB DATETIME)
  • 집계 경계, 보고서 기간, 스케줄 실행 시각이 모두 같은 타임존 기준인지 확인

8. 배포와 운영

대상배포 빈도주의
웹높음무중단 정적 배포
API중간롤링 배포
DAQ낮음배포 중 수집 공백 → 버퍼/재수집
보고서낮음스케줄 실행 시각 피해서 배포
  • 현장 게이트웨이는 원격 업데이트가 어려우므로 서버 쪽에서 호환성을 유지
  • 수집 서비스 헬스체크: 프로세스 생존이 아니라 마지막 수신 시각 기준

9. 설계 원칙 요약

  1. 원시는 불변, 집계는 재계산 가능
  2. 테이블 쓰기 소유권을 서비스별로 고정
  3. 설정(메모리맵, 요금, 스케줄, 계수)은 코드가 아닌 데이터
  4. 타임존은 한 곳에서 정의
  5. 수집 장애는 감지 가능해야 한다
Previous
개요와 용어