라즈베리파이로 웹 기반 IoT 대시보드 만들기 (Flask + Chart.js)

IoT 프로젝트를 진행하면서 센서 데이터를 실시간으로 확인하고 시각화하는 것은 필수적인 과정입니다. 라즈베리파이는 소형 컴퓨터이지만, Flask 웹 서버와 Chart.js를 활용하면 실시간 데이터 시각화 대시보드를 손쉽게 구축할 수 있습니다. 이번 글에서는 라즈베리파이에 Flask를 설치하고, 센서 데이터를 수집해 Chart.js 기반 웹 대시보드로 표시하는 방법을 단계별로 설명합니다.

웹 기반 IoT 대시보드 개요

IoT 대시보드는 센서 데이터를 수집, 분석, 시각화하여 사용자가 쉽게 이해할 수 있도록 도와주는 웹 애플리케이션입니다. 주요 기능은 다음과 같습니다.

  • 센서 실시간 데이터 표시
  • 온도, 습도, 전력, 조도 등 다양한 변수 모니터링
  • 그래프와 차트를 통한 시각적 피드백
  • 원격 접속을 통한 관리 및 제어

라즈베리파이는 GPIO 핀을 통해 센서 데이터를 읽고, Flask 웹 서버를 통해 브라우저에서 데이터를 확인할 수 있어 IoT 대시보드 구축에 적합합니다.

준비물

웹 기반 IoT 대시보드 프로젝트를 위해 필요한 준비물은 다음과 같습니다.

  • 라즈베리파이 4 Model B (또는 3B 이상)
  • MicroSD 카드 (32GB 이상)
  • 전원 어댑터 (5V 3A 이상)
  • DHT11/DHT22 온습도 센서 또는 기타 GPIO 센서
  • Python 3 환경 및 Flask, Chart.js 라이브러리

센서는 온도·습도 외에도 조도, 기울기, 전력 등 다양한 데이터를 수집할 수 있으며, GPIO 핀 또는 I2C/SPI 통신을 통해 연결 가능합니다.

환경 설정

  1. Python과 pip 업데이트
sudo apt update
sudo apt upgrade
sudo apt install python3-pip
  1. Flask 설치
pip3 install flask
  1. 센서 라이브러리 설치 (DHT 예제)
pip3 install Adafruit_DHT

Flask 웹 서버 구성

Flask는 파이썬 기반 경량 웹 프레임워크로, 간단한 서버 구현부터 REST API까지 다양한 기능을 제공합니다. 아래는 라즈베리파이에서 Flask 서버를 구축하는 기본 코드입니다.

from flask import Flask, render_template, jsonify
import Adafruit_DHT
import time

app = Flask(__name__)

DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 4

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/data')
def data():
    humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
    if humidity is not None and temperature is not None:
        return jsonify({'temperature': round(temperature,1), 'humidity': round(humidity,1)})
    else:
        return jsonify({'temperature': None, 'humidity': None})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

이 코드에서는 / 경로로 접속하면 HTML 페이지를, /data 경로로 접속하면 센서 데이터를 JSON 형식으로 반환하도록 구성되어 있습니다.

Chart.js를 이용한 실시간 그래프

Chart.js는 HTML5 Canvas 기반의 JavaScript 차트 라이브러리로, 실시간 데이터 시각화에 적합합니다. templates/index.html 파일을 만들어 웹 페이지를 구성합니다.

<!DOCTYPE html>
<html>
<head>
    <title>IoT Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
    <h2>IoT 센서 데이터 대시보드</h2>
    <canvas id="tempChart" width="400" height="200"></canvas>
    <canvas id="humChart" width="400" height="200"></canvas>

    <script>
        const tempCtx = document.getElementById('tempChart').getContext('2d');
        const humCtx = document.getElementById('humChart').getContext('2d');

        const tempChart = new Chart(tempCtx, {
            type: 'line',
            data: { labels: [], datasets: [{ label: 'Temperature (C)', data: [], borderColor: 'red', fill: false }] },
            options: { responsive: true, scales: { x: { display: true }, y: { beginAtZero: true } } }
        });

        const humChart = new Chart(humCtx, {
            type: 'line',
            data: { labels: [], datasets: [{ label: 'Humidity (%)', data: [], borderColor: 'blue', fill: false }] },
            options: { responsive: true, scales: { x: { display: true }, y: { beginAtZero: true } } }
        });

        function updateData() {
            fetch('/data')
            .then(response => response.json())
            .then(data => {
                const timeLabel = new Date().toLocaleTimeString();
                
                tempChart.data.labels.push(timeLabel);
                tempChart.data.datasets[0].data.push(data.temperature);
                if(tempChart.data.labels.length > 20){
                    tempChart.data.labels.shift();
                    tempChart.data.datasets[0].data.shift();
                }
                tempChart.update();

                humChart.data.labels.push(timeLabel);
                humChart.data.datasets[0].data.push(data.humidity);
                if(humChart.data.labels.length > 20){
                    humChart.data.labels.shift();
                    humChart.data.datasets[0].data.shift();
                }
                humChart.update();
            });
        }

        setInterval(updateData, 2000);
    </script>
</body>
</html>

이 페이지는 2초마다 /data 경로에서 최신 센서 데이터를 받아온 뒤, 그래프를 업데이트합니다. 시간 라벨은 현재 시간을 표시하며, 최신 20개의 데이터만 보여 실시간 감시가 가능합니다.

프로젝트 확장 아이디어

  • 다중 센서 통합: 온도, 습도 외에도 조도, CO2, 전력량 데이터를 함께 표시
  • 경보 시스템 연동: 임계값 초과 시 웹 알림, 이메일, 푸시 알림 발송
  • 모바일 최적화: CSS와 반응형 웹 디자인 적용
  • 데이터 저장: SQLite, MySQL과 연동하여 장기 기록 및 분석 가능
  • 외부 API 연동: 날씨, 위치 정보, 주가 데이터 등 실시간 외부 정보 통합

성능 및 안정성 팁

  • 라즈베리파이 GPIO를 통한 센서 읽기 시, read_retry 함수를 사용하여 안정적인 데이터 수집
  • Flask 서버는 기본 개발용 서버이므로, 실제 배포 시에는 gunicorn이나 nginx와 연동 추천
  • Chart.js 실시간 업데이트 시 데이터 배열 길이를 제한하여 브라우저 메모리 사용량 최소화
  • Wi-Fi 환경이 불안정하면 데이터 수집 주기를 조금 늘려 안정성을 확보

마무리

라즈베리파이와 Flask, Chart.js를 활용하면 IoT 센서 데이터를 실시간으로 시각화하는 웹 기반 대시보드를 손쉽게 구축할 수 있습니다. 단순한 온습도 모니터링부터 스마트홈 제어, 산업용 센서 모니터링까지 확장할 수 있으며, Python과 JavaScript를 연동해 효율적인 데이터 처리 및 시각화를 구현할 수 있습니다.

이번 글에서 다룬 Flask 서버 구축, Chart.js 기반 그래프 구현, 센서 데이터 실시간 반영 방법을 기반으로, 자신만의 맞춤형 IoT 대시보드를 개발할 수 있으며, 이를 통해 원격 모니터링과 데이터 분석이 가능해집니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다