React에서 Chart.js로 반응형 그래프에 2개 데이터 그리기 (with TypeScript)

사공 오·2025년 4월 27일
0

library

목록 보기
1/1

결과 이미지

Chart.js를 사용해서 반응형으로 한 차트에 막대 그래프 2개를 렌더링 시켜보겠습니다.

설치하기

react에서 사용하려면 react-chartjs-2도 설치가 필요합니다.

npm install react-chartjs-2 chart.js

기본적인 요소

  1. 차트 컴포넌트
    1-1. 차트 컴포넌트에 props로 넘길 data
    1-2. 차트 컴포넌트에 props로 넘길 options
  2. register

1. 차트 컴포넌트

기본적으로 차트가 그려질 컴포넌트.
컴포넌트로 선언할 수 있는 것들은 react-chartjs-2 공식사이트에서 확인할 수 있습니다.

<Bar data={data} options={options} />
<Doughnut data={data} options={options} /> 
<Chart type={...} options={...} data={...} /> //type을 넘겨주면 Chart 컴포넌트로 모든 타입의 차트사용 가능(multiple 타입 시 주로 사용)

1-1. data객체

import { ChartData } from 'chart.js';

const data: ChartData<'bar'> = {
      labels: ['1번', '2번', '3번'], // 해당 바에 해당하는 라벨
      datasets: [
        {
          label: '정답률',
          type: 'bar',
          data: [80, 20, 40],
          backgroundColor: param.correctRate?.map((data) => 
             if (data === min && data === max) return REPORT_COLORS.FIVE_PRIMARY;
          return REPORT_COLORS.THREE_PRIMARY), //조건부로 다른 색상으로 랜더링 가능
          // barThickness: 20, //두께 픽셀로 지정
          barPercentage: 0.5, //두께를 비율로 지정 최대 1
          borderRadius: 20, // 모퉁이 둥글리기
          borderSkipped: 'bottom', // 하단 양끝은 둥글리기 생략
        },
        {
          label: '평균시간',
          type: 'bar', //type이 두가지가 다를 경우 다르게 선언할 수 있음 (생략가능)
          data: [100, 210, 350],
          backgroundColor: REPORT_COLORS.FIVE_PRIMARY,
          yAxisID: 'yRight', //두가지 바가 있을 경우 y축ID 선언 option 설정 시 사용됨.
          barPercentage: 0.5,
          borderRadius: 20,
          borderSkipped: 'bottom',
        },
      ],
    });

labels - 각 막대(bar)의 이름입니다.
datasets - 이 차트에 그릴 데이터 집합으로, '정답률', '평균시간' 데이터를 선언했습니다.

  • props로 넘길 data객체의 type을 ChartData<'bar'>로 선언하여 타입 안전성을 높여줍니다. 또한 데이터 수정 시 많은 옵션 값들을 파악하기 용이합니다.
  • 두 가지의 데이터가 같은 x축을 가지고, 다른 y축을 가졌으므로 option 선언을 위해 yAxisID: 'yRight' 를 선언하였습니다.
  • barThickness로 px로 막대의 두께를 고정하고 싶었지만 그럴 경우 두 막대의 간격이 중간으로 딱붙어버리는 상황으로 간격을 조정하는 옵션이 없어서 어쩔 수 없이 barPercentage를 사용해서 스타일링 했습니다. (사실 그냥 그래프 오픈소스를 하나 만들어볼까 고민 중입니다)

1-2. option

import { ChartOptions } from 'chart.js';

 const chartOptions: ChartOptions<'bar'> = {
    responsive: true, //반응형 처리
    maintainAspectRatio: false, //기본 비율(가로:세로 비율)을 유지 X 
    plugins: {
      legend: {
        display: false,
      },
    },
    scales: {
      x: {
        grid: {
          drawTicks: false,
        },
        ticks: {
          padding: 10,
          font: {
            size: 16,
            weight: 'bold',
            family: fontFamily[0],
          },
          color: REPORT_COLORS.BW_767676,
        },
      },
      y: {
        grid: {
          display: false,
        },
        min: 0,
        max: 100,
        ticks: {
          callback: function (value) {
            return value + '%';
          },
          stepSize: 20,
          font: {
            size: 16,
            weight: 600,
            family: fontFamily[0],
          },
          color: REPORT_COLORS.BW_A3A3A3,
          align: 'start',
        },
      },
      yRight: {
        min: 0,
        max: 360, //최대 5분, 그외는 6분이상으로 처리
        position: 'right', // 오른쪽에 배치
        grid: { drawTicks: false },
        ticks: {
          padding: 10,
          callback: function (value) {
            return Math.round(Number(value) / 60) < 6
              ? `${Math.round(Number(value) / 60)}m`
              : '6m ↑'; //초단위 데이터를 분으로 변경
          },
          stepSize: 60, //스텝당 60초씩 계산되도록
          font: {
            size: 16,
            weight: 'bold',
            family: fontFamily[0],
          },
          color: REPORT_COLORS.BW_A3A3A3,
          align: 'start',
        },
      },
    },
  };

반응형 처리

{ responsive: true, maintainAspectRatio: false, }
위의 두 옵션을 줘야 상단 부모에서 높이를 고정하고 width를 100%로 주면 좌우로 아무리 브라우저를 늘였다 줄였다 해도 width를 다채우는 그래프를 그릴 수 있습니다.
maintainAspectRatio를 true로 줄 경우 브라우저를 줄였을때는 비율에 맞게 줄어들지만 다시 브라우저를 늘려도 크기가 같이 커지지않는 문제가 발생하므로 높이를 고정하고 좌우 반응형으로 구현했습니다.

  • scales (y, yRight)
    상단에서 선언한 'yRight'축(평균시간)을 position: 'right'옵션을 줘서 오른쪽에 배치시켰습니다. align: 'start' 로 y축 눈금(tick) 레이블의 정렬 방향을 왼쪽으로 붙도록 정의했습니다.

2.register

chart.js에서 필요한 것들을 import 해온 후 register를 해야 차트를 렌더링 할 수 있습니다.
(ChartJS.register(...)를 빼먹으면 차트가 아예 안 나와요.)

import {
  ChartData,
  Chart as ChartJS,
  ChartOptions,
  LineElement,
  Tooltip,
} from 'chart.js';
ChartJS.register(LineElement, Tooltip);

필요한 것들을 register에 등록하지 않은 경우 차트가 렌더링되지 않으면 콘솔에러가 나오므로 확인 후 필요한 요소들을 추가해주시면 됩니다!

이러한 과정을 거치면 위 이미지에 해당하는 그래프를 만들 수 있습니다 🥰


참고링크
https://www.chartjs.org/docs/latest/charts/bar.html
https://react-chartjs-2.js.org/components/

0개의 댓글