내부 데이터를 시각화해야 할 때, 대부분 두 가지 선택지 사이에서 고민하게 됩니다.
BI 툴은 설정이 간편하지만 커스터마이징이 어렵고, 직접 개발은 자유도가 높지만 리소스가 많이 듭니다.
둘 사이 어딘가에, 조금 더 가볍고 빠른 방법이 있을까 하는 생각에서 이번 구성을 시도해보게 됐습니다.
이번에 구성해본 방식은 다음 세 가지 도구를 조합한 형태입니다.
이 세 가지를 연결해주는 툴로는 셀렉트어드민을 사용했습니다.
복잡한 설정 없이도 대시보드를 만들 수 있는지 확인해보는 실험이었습니다.
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 설정
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
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 작성 없이도 이런 구조가 만들어졌습니다.
SQL과 Chart.js만으로 대시보드를 구성하는 방법이 얼마나 실용적인지 확인해보고 싶었고,
이번 구성은 그런 가능성을 보여주는 좋은 실험이었습니다.
모든 상황에 적용할 수 있는 건 아니겠지만,
필요한 결과를 빠르게 만들고 개선해 나가는 구조로서는 꽤 괜찮은 선택이 될 수 있습니다.
전체 템플릿 예제나 구성 방식이 궁금하다면 아래 내용을 참고하셔도 좋습니다.
비슷한 고민을 하고 계셨다면, 이 방식이 하나의 힌트가 될 수 있을지도 모르겠습니다.