Next.js에서 chart.js를 이용해서 그래프 그리기
지난 시간에 이어서…
- 지난 시간에 라즈베리파이 피코로 실외에 있는 고양이 겨울집 내부의 온/습도를 측정한 다음, mqtt 통신을 통해서 원격의 구독서버가 값을 받아오는 것을 포스팅 했었습니다.
 - 오늘은 이 값을 이용해서 그래프를 그리는 페이지를 작성해 보겠습니다.
 
서버로그를 JSON으로 변환
- 구독 서버가 출력하는 로그는 이런 형태인데요
 
2025-02-20 22:39:40 {"device_id": "d2", "humidity": 30.8, "temperature": -1.5}
2025-02-20 22:40:22 {"device_id": "d2", "humidity": 32.7, "temperature": -0.9}
2025-02-20 22:41:22 {"device_id": "d2", "humidity": 32.7, "temperature": -0.8}
- 저기서 날짜 시간 부분을 time 프로퍼티로 추가했습니다.
 - 그리고 기상청 데이터를 기반으로 해당 시간에 기록된 실외 온도를 out 프로퍼티로 추가했습니다.
 
[{"time": "2025-02-20 22:39:40", "device_id": "d2", "humidity": 30.8, "temperature": -1.5,"out": -3.2},
{"time": "2025-02-20 22:40:22", "device_id": "d2", "humidity": 32.7, "temperature": -0.9,"out": -3.3},
{"time": "2025-02-20 22:41:22", "device_id": "d2", "humidity": 32.7, "temperature": -0.8,"out": -3.2}]
- 파일의 실제 길이는 더 길겠죠??
 
next.js 설치
- npm을 이용해서 next.js를 설치해주세요. 이때 타입스크립트를 이용하겠습니다.
 - 디렉토리나 인덱스 페이지와 컴포넌트 구성은 각자 알아서 해주시면 됩니다.
 
JSON 로딩 유틸리티 모듈
- JSON 파일을 로딩하는 간단한 모듈을 아래와 같이 작성합니다.
 
import jsonData from '../data/log-0220.json'; // JSON 파일 경로
interface THItem {
    time: string;
    temperature: number;
    humidity: number;
    device_id: string;
    out: number,
}
export const getJsonData = (): THItem[] => {
    return jsonData as THItem[];
};
차트를 그려주는 컴포넌트
- chart.js를 이용해서 그래프를 그려주는 컴포넌트를 작성했습니다.
 
'use client';
import React, {ComponentType} from 'react';
import {Line} from 'react-chartjs-2';
import {Chart as ChartJS, LinearScale, PointElement, LineElement, Legend} from 'chart.js';
import type {ChartData, ChartOptions} from 'chart.js';
ChartJS.register(
    LinearScale,
    PointElement,
    LineElement,
    Legend
);
interface Props {
    data: {
        time: string,
        device_id: string,
        temperature: number,
        humidity: number,
        out: number,
    }[];
}
const Chart1Client: ComponentType<Props> = ({data}) => {
    const chartData: ChartData = {
        labels: data.map((_, index) => index),
        datasets: [
            {
                label: "온도",
                data: data.map(item => item.temperature),
                borderColor: 'red',
                backgroundColor: 'rgba(255, 0, 0, 0.2)',
                tension: 0.1,
                pointRadius: 0,
                yAxisID: 'y1',
            },
            {
                label: "바깥온도",
                data: data.map(item => item.out),
                borderColor: 'orange',
                backgroundColor: 'rgba(255, 69, 0, 0.2)',
                tension: 0.1,
                pointRadius: 0,
                yAxisID: 'y1',
            },
            {
                label: "습도",
                data: data.map(item => item.humidity),
                borderColor: 'blue',
                backgroundColor: 'rgba(255, 0, 255, 0.2)',
                tension: 0.1,
                pointRadius: 0,
                yAxisID: 'y2',
            }],
    };
    const chartOptions: ChartOptions = {
        scales: {
            x: {
                title: {
                    display: true,
                    text: '분',
                },
                type: 'linear',
                ticks: {
                    stepSize: 60,
                }
            },
            y1: {
                type: 'linear',
                display: true,
                position: 'left',
                title: {
                    display: true,
                    text: '온도',
                },
            },
            y2: {
                type: 'linear',
                display: true,
                position: 'right',
                grid: {
                    drawOnChartArea: false,
                },
                title: {
                    display: true,
                    text: '습도',
                },
            },
        },
    };
    return (
        <Line data={chartData} options={chartOptions}></Line>
    );
}
export default Chart1Client;
- 그리하여 아래와 같은 차트를 그릴 수 있었습니다.
    
 
시연연상
- 이 차트를 활용한 영상도 함께 봐주시면 감사하겠습니다.
 

Comments