심장 박동 마스터하기: InfluxDB와 Grafana를 활용한 고주파 건강 모니터링 시스템 설계

발행: (2026년 4월 24일 AM 09:23 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.

Introduction

고주파 건강 모니터링은 심박수, 혈중 산소(SpO₂), 심전도(ECG)와 같은 센서에서 분당 수천 개의 데이터 포인트를 생성합니다. 이러한 데이터를 전통적인 관계형 데이터베이스에 저장하면 금방 비현실적이 됩니다. InfluxDB와 같은 시계열 데이터베이스(TSDB)는 이러한 워크로드에 필요한 쓰기 처리량과 저장 효율성을 제공합니다.

Architecture Overview

The data flow consists of:

graph TD
    A[Wearable Sensors / IoT Node] -->|MQTT/HTTP| B(Telegraf Collector)
    B -->|Line Protocol| C{InfluxDB 2.x}
    C -->|Flux Query| D[Grafana Dashboard]
    C -->|Retention Policy| E[Downsampled Long‑term Storage]

    subgraph "Data Engineering Layer"
    B
    C
    E
    end

    style C fill:#f96,stroke:#333,stroke-width:2px
  • Wearable Sensors / IoT Node – MQTT 또는 HTTP를 통해 데이터를 전송합니다.
  • Telegraf – 데이터를 수신하고 라인 프로토콜을 사용해 InfluxDB에 기록하는 범용 데이터 수집기입니다.
  • InfluxDB 2.x – 원시 측정값을 저장하고 다운샘플링을 위한 백그라운드 작업을 수행합니다.
  • Grafana – Flux 쿼리를 사용해 데이터를 시각화합니다.

전제 조건

  • Docker 및 Docker Compose
  • IoT 프로토콜(MQTT/HTTP)에 대한 기본 지식
  • InfluxDB 2.x, Telegraf, Grafana

Docker Compose 설정

Create a docker-compose.yml file to orchestrate the services:

version: '3.8'
services:
  influxdb:
    image: influxdb:2.7
    ports:
      - "8086:8086"
    volumes:
      - influxdb-data:/var/lib/influxdb2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=password123
      - DOCKER_INFLUXDB_INIT_ORG=my-health
      - DOCKER_INFLUXDB_INIT_BUCKET=raw_vitals

  telegraf:
    image: telegraf:latest
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    depends_on:
      - influxdb

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    depends_on:
      - influxdb

volumes:
  influxdb-data:

Running docker compose up -d will start a reproducible, isolated environment.

InfluxDB 스키마 설계

건강 바이탈 데이터를 태그(메타데이터)와 필드(측정값)로 구성합니다.

Measurement: vitals
Tags:        patient_id="user_01", device_type="watch_v2"
Fields:      bpm (float), spo2 (float), ecg_mv (float)

태그는 인덱싱되어 효율적인 쿼리를 가능하게 하며, 필드는 실제 수치 값을 저장합니다.

텔레그라프 구성

다음 내용을 telegraf.conf 파일로 저장하십시오 (TOML 형식). 이 설정은 HTTP 리스너를 구성하여 JSON 페이로드를 수신하고 이를 InfluxDB로 전달합니다.

[[inputs.http_listener_v2]]
  service_address = ":8080"
  path = "/telegraf"
  methods = ["POST"]
  data_format = "json"
  tag_keys = ["patient_id", "device_type"]

[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "${INFLUX_TOKEN}"
  organization = "my-health"
  bucket = "raw_vitals"

InfluxDB 작업을 이용한 다운샘플링

수년간 모든 ECG 샘플을 저장하는 것은 비용이 많이 듭니다. 원시 데이터는 24시간 동안 보관하고, 다운샘플링된 데이터는 장기 분석을 위해 보관합니다. 아래 Flux 작업은 1분 평균을 생성하고 별도의 버킷에 기록합니다.

option task = {name: "Downsample_Vitals", every: 1m}

from(bucket: "raw_vitals")
  |> range(start: -task.every)
  |> filter(fn: (r) => r._measurement == "vitals")
  |> mean()
  |> set(key: "_measurement", value: "vitals_1m_avg")
  |> to(bucket: "long_term_vitals")

Grafana 설정

  1. InfluxDB를 데이터 소스로 추가합니다 (Flux를 쿼리 언어로 선택).
  2. 다음 Flux 쿼리를 사용하여 심박수(bpm)를 시각화하는 대시보드 패널을 만듭니다:
from(bucket: "raw_vitals")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "vitals")
  |> filter(fn: (r) => r["_field"] == "bpm")
  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
  |> yield(name: "mean")

알림

Grafana(또는 InfluxDB Tasks)를 사용하여 심박수가 임계값을 초과할 때, 예를 들어 bpm > 150가 5 분 이상 지속될 경우 트리거되는 알림 규칙을 설정합니다. 알림은 Slack, Discord 또는 기타 채널로 알림을 보낼 수 있습니다.

Conclusion

InfluxDB, Telegraf, Grafana를 결합함으로써 원시 센서 신호를 실행 가능한 건강 인사이트로 변환합니다. 이 스택은 높은 쓰기 처리량, 효율적인 저장소, 유연한 시각화를 제공하여 개인 또는 연구 수준의 건강 모니터링에 적합합니다.

다음 단계?

  • 실시간으로 부정맥을 감지하기 위해 AI 레이어(예: Python)를 추가합니다.
  • HIPAA‑준수 배포를 위해 멀티‑테넌트 아키텍처와 암호화‑휴지(encryption‑at‑rest)를 탐색합니다.
0 조회
Back to Blog

관련 글

더 보기 »