Chart.js로 직무 번아웃 데이터 시각화하기
복잡한 데이터를 직관적인 그래프로 표현하기
💭 왜 차트가 필요했나
직무 번아웃 테스트를 만들면서 고민이 생겼습니다. 5개 영역(정서적 고갈, 냉소, 성취감 저하, 신체/정신 증상, 환경적 요인)의 점수를 어떻게 보여줄까? 그냥 숫자로 나열하면 사용자가 자신의 상태를 한눈에 파악하기 어렵겠더군요.
"이미 위험한 영역이 어딘지 바로 보여줘야 하는데..." 고민하다가 **막대 그래프**가 떠올랐습니다. 각 영역의 점수를 시각적으로 비교할 수 있으니까요. 그래서 Chart.js를 도입하기로 결정했습니다.
💡 Chart.js를 선택한 이유
- • 간단한 API로 빠른 구현
- • 반응형 지원 (모바일 대응)
- • 커스터마이징이 자유로움
- • CDN으로 바로 사용 가능
🎯 설계 단계
차트를 만들기 전에 어떤 정보를 담을지 고민했습니다:
표시할 정보
- 1. 각 영역의 현재 점수 (예: 정서적 고갈 35점)
- 2. 각 영역의 만점 (정서적 고갈 최대 50점)
- 3. 비율로 계산 (35/50 = 70%)
- 4. 위험 수준 표시 (70% 이상이면 경고)
💻 구현 과정
1단계: Chart.js 추가
CDN으로 간단하게 추가했습니다.
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
2단계: Canvas 요소 준비
차트를 그릴 캔버스 영역을 HTML에 만들었습니다.
<div class="bg-gray-50 rounded-2xl p-6">
<canvas id="categoryChart" height="300"></canvas>
</div>
💡 높이 설정 팁
height 속성으로 차트 높이를 고정했습니다. CSS로 높이를 설정하면 Chart.js가 비율을 제대로 계산하지 못할 수 있습니다.
3단계: 데이터 준비
사용자의 검사 결과를 영역별로 정리했습니다.
// 영역별 점수 (LocalStorage에서 로드)
const categoryScores = {
'정서적 고갈': 35,
'비인격화(냉소)': 28,
'개인적 성취감 저하': 42,
'신체적/정신적 증상': 38,
'환경적 요인': 20
};
// 각 영역의 만점
const categoryMaxScores = {
'정서적 고갈': 50,
'비인격화(냉소)': 50,
'개인적 성취감 저하': 50,
'신체적/정신적 증상': 50,
'환경적 요인': 25
};
4단계: 차트 생성
이제 Chart.js로 막대 그래프를 그렸습니다.
const ctx = document.getElementById('categoryChart').getContext('2d');
const labels = Object.keys(categoryScores);
const data = Object.values(categoryScores);
const maxScores = labels.map(cat => categoryMaxScores[cat]);
new Chart(ctx, {
type: 'bar', // 막대 그래프
data: {
labels: labels,
datasets: [{
label: '현재 점수',
data: data,
backgroundColor: 'rgba(249, 115, 22, 0.7)',
borderColor: 'rgba(249, 115, 22, 1)',
borderWidth: 2
}, {
label: '만점',
data: maxScores,
backgroundColor: 'rgba(229, 231, 235, 0.5)',
borderColor: 'rgba(156, 163, 175, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
stepSize: 10
}
}
}
}
});
🎨 색상 선택 전략
- 현재 점수: 주황색 (rgba(249, 115, 22)) - 경고를 나타내는 색
- 만점: 회색 (rgba(229, 231, 235)) - 배경처럼 조용하게
- 투명도: 0.7로 설정해서 겹쳐도 보이도록
5단계: 툴팁 커스터마이징
막대에 마우스를 올리면 퍼센트도 같이 보여주고 싶었습니다.
options: {
// ... 기존 옵션들
plugins: {
tooltip: {
callbacks: {
label: function(context) {
const index = context.dataIndex;
const datasetLabel = context.dataset.label;
const value = context.parsed.y;
if (datasetLabel === '현재 점수') {
const max = maxScores[index];
const percentage = ((value / max) * 100).toFixed(1);
return \`\${datasetLabel}: \${value}점 (\${percentage}%)\`;
}
return \`\${datasetLabel}: \${value}점\`;
}
}
}
}
}
🎨 시각화 개선
기본 차트만으로는 부족하다고 느껴서 몇 가지를 더 추가했습니다.
위험 영역 강조 표시
70% 이상인 영역은 별도로 경고 메시지를 표시했습니다.
// 70% 이상인 영역 찾기
Object.entries(categoryScores).forEach(([category, score]) => {
const maxScore = categoryMaxScores[category];
const percentage = (score / maxScore) * 100;
if (percentage >= 70) {
// 빨간 경고 박스 표시
displayWarning(category, score, percentage);
}
});
개인적 성취감 저하 - 성장 정체 상태
충분히 잘해왔는데도 '내가 뭘 했지?'라는 생각이 드나요? 거창한 목표보다는...
⚠️ 겪은 문제들
문제 1: 라벨이 너무 길어서 잘림
"비인격화(냉소)", "개인적 성취감 저하" 같은 긴 텍스트가 X축에서 잘렸습니다.
해결:
scales: {
x: {
ticks: {
font: {
size: 11 // 폰트 크기 줄임
}
}
}
}
문제 2: 모바일에서 차트가 작음
PC에서는 괜찮았는데 모바일에서는 막대가 너무 얇아 보였습니다.
해결:
responsive: true 옵션과 함께 maintainAspectRatio: false로 설정해서 컨테이너 크기에 맞추도록 했습니다.
문제 3: 차트가 너무 복잡해 보임
처음에는 파이 차트, 레이더 차트 등 여러 차트를 고려했습니다.
해결:
막대 그래프가 가장 직관적이라는 결론. 단순함이 최고입니다.
📈 다른 차트 타입 실험
막대 그래프 외에 다른 것들도 시도해봤습니다:
❌ 파이 차트
각 영역의 비교가 어려움. 전체 합이 의미 없음
❌ 레이더 차트
멋있지만 직관적이지 않음. 노인층 사용자에게 어려움
✅ 막대 그래프
가장 직관적. 비교가 쉬움. 모든 연령대가 이해 가능
△ 라인 차트
시간 흐름 데이터가 아니라 부적합
🎓 배운 점
- 1️⃣ 단순함의 가치: 복잡한 차트보다 단순한 막대 그래프가 더 효과적이었습니다
- 2️⃣ 맥락이 중요: 차트만으로는 부족합니다. 해석과 가이드가 필요합니다
- 3️⃣ 색상 심리: 주황/빨강은 경고, 회색은 배경. 색상만으로도 의미 전달
- 4️⃣ 반응형은 필수: 모바일 사용자가 훨씬 많습니다
💡 마치며
Chart.js를 사용하면서 "데이터 시각화"의 중요성을 다시 한번 깨달았습니다. 같은 데이터도 어떻게 보여주느냐에 따라 사용자의 이해도가 완전히 달라지더군요.
다음에는 히스토리 기능을 추가해서 시간에 따른 변화를 라인 차트로 보여주고 싶습니다. "지난 3개월간 번아웃 지수가 어떻게 변했는지" 확인할 수 있다면 더 유용할 것 같아요.
⏳
다음 글 예고
사용자 경험을 높이는 로딩 애니메이션 구현하기