Chart.js 대시보드, 더 간단하게 만들 수 없을까?

내부 데이터를 시각화해야 할 때, 대부분 두 가지 선택지 사이에서 고민하게 됩니다.
Metabase 같은 BI 툴을 쓸 것인가
직접 프론트엔드/백엔드를 개발할 것인가
BI 툴은 설정이 간편하지만 커스터마이징이 어렵고, 직접 개발은 자유도가 높지만 리소스가 많이 듭니다.
둘 사이 어딘가에, 조금 더 가볍고 빠른 방법이 있을까 하는 생각에서 이번 구성을 시도해보게 됐습니다.
SQL + YAML + Chart.js 조합
이번에 구성해본 방식은 다음 세 가지 도구를 조합한 형태입니다.
SQL: 데이터를 가져오기 위한 쿼리
YAML: 페이지와 필터 등 구조 정의
Chart.js: 시각화 라이브러리
이 세 가지를 연결해주는 툴로는 셀렉트어드민을 사용했습니다.
복잡한 설정 없이도 대시보드를 만들 수 있는지 확인해보는 실험이었습니다.
기본 구조
YAML을 이용해 페이지와 필터를 정의하고,
SQL로 데이터를 조회하고,
Chart.js로 시각화를 구성합니다.
예시로는 이커머스 월별 매출 데이터를 시각화하는 대시보드를 구성해봤습니다.
menus:
- path: pages/sales
pages:
- path: pages/sales
title: 매출 대시보드
params:
- key: date_range
label: 분석 기간
format: date
range: true
blocks:
- id: monthly-sales
type: query
sql: SELECT ...
display: chartjs
displayFn: |
// chart.js 설정
SQL 쿼리
YAML에서 정의한 필터 값은 자동으로 쿼리 파라미터에 바인딩됩니다.
SELECT
DATE_FORMAT(order_date, '%Y-%m') as month,
SUM(total_amount) as total_revenue
FROM orders
WHERE order_date >= :date_range1
AND order_date <= :date_range2
GROUP BY DATE_FORMAT(order_date, '%Y-%m')
ORDER BY month
Chart.js 설정
SQL 결과는 rows 배열로 전달되고, 이걸 그대로 Chart.js에 연결할 수 있습니다.
const labels = rows.map(row => row.month);
const revenueData = rows.map(row => row.total_revenue);
const data = {
labels: labels,
datasets: [{
label: '매출 (원)',
data: revenueData,
backgroundColor: 'rgba(54, 162, 235, 0.6)'
}]
};
const config = {
type: 'bar',
data: data,
options: {
responsive: true,
scales: {
y: {
title: { display: true, text: '매출 (원)' }
}
}
}
};
const myChart = new Chart(ctx, config);
실제 동작
위와 같이 구성하면 셀렉트어드민의 /pages/sales 경로 페이지에서 다음과 같은 대시보드가 만들어집니다.
프론트엔드 상태 관리나 별도 API 작성 없이도 이런 구조가 만들어졌습니다.
이 방식이 가질 수 있는 장점
작성하는 코드는 매우 단순합니다 (YAML + SQL + Chart.js)
Chart.js 문법을 그대로 활용할 수 있어 시각화 자유도가 높습니다
필터 값과 SQL 파라미터가 자동으로 연결됩니다
인증이나 배포 같은 부분은 플랫폼에서 처리합니다
이런 상황이라면 어울릴 수 있습니다
정리하며
SQL과 Chart.js만으로 대시보드를 구성하는 방법이 얼마나 실용적인지 확인해보고 싶었고,
이번 구성은 그런 가능성을 보여주는 좋은 실험이었습니다.
모든 상황에 적용할 수 있는 건 아니겠지만,
필요한 결과를 빠르게 만들고 개선해 나가는 구조로서는 꽤 괜찮은 선택이 될 수 있습니다.
전체 템플릿 예제나 구성 방식이 궁금하다면 아래 내용을 참고하셔도 좋습니다.
비슷한 고민을 하고 계셨다면, 이 방식이 하나의 힌트가 될 수 있을지도 모르겠습니다.