데이터 시각화란, 데이터를 선으로 연결하여 시각적으로 표현하는 것을 말한다.
대표적으로 차트. 그래프가 있다.
개요
이 글에서는 HTML5 Canvas 기반 렌더링에서 발생할 수 있는 성능 병목 문제와 이를 해결하기 위한 대표적인 최적화 전략을 소개합니다.
이와 함께, 복잡한 데이터 시각화 작업에는 왜 차트 라이브러리 사용이 유리한지 설명하고, 실무에서 자주 사용되는 주요 차트 라이브러리들의 종류와 특징을 비교합니다.
Canvas 렌더링
Canvas 렌더링은 HTML5의 <canvas> 요소를 사용해 자바스크립트로 픽셀 단위의 그래픽을 그리는 방식입니다.
주로 게임, 애니메이션, 실시간 시각화 등에 사용되며, 도형, 이미지, 텍스트 등을 자유롭게 조합할 수 있는 고성능 2D 그래픽 처리 도구입니다.
브라우저가 제공하는 canvas.getContext('2d') API를 통해 fillRect, arc, drawImage 같은 메서드로 화면에 직접 그림을 그리게 됩니다.
<canvas id="myCanvas" width="400" height="300" style="border:1px solid #000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 사각형 그리기
ctx.fillStyle = 'skyblue';
ctx.fillRect(20, 20, 100, 80);
</script>
Canvas 렌더링 한계
캔버스 렌더링에서는 beginPath, arc, fill, stroke 등의 메서드와 save, restore 명령어가 반복적으로 호출됩니다.
이러한 작업은 메인 스레드에서 실행되므로, 프레임당 수천~수십만 번 호출될 경우 성능 저하가 발생할 수 있습니다.
따라서 데이터가 많아질수록 병목 현상이 심해지며, 이를 방지하기 위한 대안이 등장했습니다.
렌더링 병목 현상 방지를 위한 주요 대안
1. 오프스크린 캔버스 (OffscreenCanvas) 사용
메인 스레드가 아닌 웹 워커(Worker)에서 캔버스를 렌더링하여, 메인 UI의 응답성 향상에 효과적입니다.
2. 레이어별 캔버스 분리
정적인 배경, 인터랙티브 요소 등 각 요소를 캔버스 레이어로 분리하면 전체 재렌더링을 피할 수 있습니다.
3. requestAnimationFrame으로 렌더링 최적화
브라우저의 리렌더링 타이밍에 맞춰 작업을 실행하므로, 프레임 드랍 없이 부드러운 애니메이션을 제공하게 도와줍니다.
4. 비트맵 캐싱
반복적으로 등장하는 객체는 Canvas에서 미리 렌더링해 이미지로 저장해두고, drawImage로 재사용하면 속도가 비약적으로 빨라집니다.
5. 그리기 최소화 및 조건부 렌더링
변경된 경우에만 조건부로 그리기 수행하게 합니다.
왜 차트 라이브러리를 왜 사용하나요?
Canvas나 SVG 기반으로 직접 시각화 로직을 구현하여 직접 Canvas 렌더링을 최적화하는 것도 중요하지만, 차트 같은 복잡한 시각화 작업은 검증된 라이브러리를 활용하는 것이 현명할 수 있습니다.
보통 시각화데이터는 보통 SVG(Scalable Vector Graphics)와 Canvas를 사용하여 다양한 그래픽 요소를 만들지만 렌더링과 스타일링 등 아름답고 고성능의 차트를 만들고 싶다면 Charts 라이브러리를 사용하는 방법도 고려할 수 있습니다.
JavaScript 차트 라이브러리 추천
1. chart.js

특징
- 즉시 사용 가능한 차트
- 뛰어난 구성
- 선택적 구성 기능으로 인한 커스터마이징
- 가장 사용자가 많다.
예시
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
</script>
React 차트 라이브러리 추천
1. recharts
- Recharts는 React 와 D3 로 구축된 재정의된 차트 라이브러리
- 장점
- React 구성 요소를 사용하여 간단히 배포하세요.
- 일부 D3 하위 모듈에만 의존하는 경량 기본 SVG 지원.
- 선언적 구성 요소, 차트 구성 요소는 순전히 표현(조회성)
- 장점
- React Component를 명확히 구분해줌
- lineChart는 x축, 툴팁, 그리드, 라인 항목 등

특징
- 즉시 사용 가능한 차트
- 뛰어난 구성
- 선택적 구성 기능으로 인한 커스터마이징
- 가장 사용자가 많다.
예시
import { LineChart, Line } from 'recharts';
const data = [{name: 'Page A', uv: 400, pv: 2400, amt: 2400}, ...];
const renderLineChart = (
<LineChart width={400} height={400} data={data}>
<Line type="monotone" dataKey="uv" stroke="#8884d8" />
</LineChart>
);
2. nivo

특징
- 즉시 사용 가능한 차트
- 커스텀이 어려움
예시
- @nivo/line
- @nivo/bar
import { ResponsiveLine } from '@nivo/line'
const MyResponsiveLine = ({ data /* see data tab */ }) => (
<ResponsiveLine
data={data}
margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
xScale={{ type: 'point' }}
yScale={{
type: 'linear',
min: 'auto',
max: 'auto',
stacked: true,
reverse: false
}}
yFormat=" >-.2f"
axisTop={null}
axisRight={null}
axisBottom={{
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: 'transportation',
legendOffset: 36,
legendPosition: 'middle',
truncateTickAt: 0
}}
axisLeft={{
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: 'count',
legendOffset: -40,
legendPosition: 'middle',
truncateTickAt: 0
}}
pointSize={10}
pointColor={{ theme: 'background' }}
pointBorderWidth={2}
pointBorderColor={{ from: 'serieColor' }}
pointLabel="data.yFormatted"
pointLabelYOffset={-12}
enableTouchCrosshair={true}
useMesh={true}
legends={[
{
anchor: 'bottom-right',
direction: 'column',
justify: false,
translateX: 100,
translateY: 0,
itemsSpacing: 0,
itemDirection: 'left-to-right',
itemWidth: 80,
itemHeight: 20,
itemOpacity: 0.75,
symbolSize: 12,
symbolShape: 'circle',
symbolBorderColor: 'rgba(0, 0, 0, .5)',
effects: [
{
on: 'hover',
style: {
itemBackground: 'rgba(0, 0, 0, .03)',
itemOpacity: 1
}
}
]
}
]}
/>
)
3. react-charts
https://react-charts.tanstack.com/

특징
- 즉시 사용 가능한 차트
- 커스텀이 어려움
예시
function App() {
const primaryAxis = React.useMemo(
(): AxisOptions<DailyStars> => ({
getValue: datum => datum.date,
}),
[]
)
const secondaryAxes = React.useMemo(
(): AxisOptions<DailyStars>[] => [
{
getValue: datum => datum.stars,
},
],
[]
)
return (
<Chart
options={{
data,
primaryAxis,
secondaryAxes,
}}
/>
)
}
4. victory
https://commerce.nearform.com/open-source/victory


특징
- 즉시 사용 가능한 차트
- 커스텀이 어려움
예시
const data2012 = [
{quarter: 1, earnings: 13000},
{quarter: 2, earnings: 16500},
{quarter: 3, earnings: 14250},
{quarter: 4, earnings: 19000}
];
const data2013 = [
{quarter: 1, earnings: 15000},
{quarter: 2, earnings: 12500},
{quarter: 3, earnings: 19500},
{quarter: 4, earnings: 13000}
];
const data2014 = [
{quarter: 1, earnings: 11500},
{quarter: 2, earnings: 13250},
{quarter: 3, earnings: 20000},
{quarter: 4, earnings: 15500}
];
const data2015 = [
{quarter: 1, earnings: 18000},
{quarter: 2, earnings: 13250},
{quarter: 3, earnings: 15000},
{quarter: 4, earnings: 12000}
];
function App() {
return (
<VictoryChart
domainPadding={20}
theme={VictoryTheme.material}
>
<VictoryAxis
tickValues={[1, 2, 3, 4]}
tickFormat={["Quarter 1", "Quarter 2", "Quarter 3", "Quarter 4"]}
/>
<VictoryAxis
dependentAxis
tickFormat={(x) => (`$${x / 1000}k`)}
/>
<VictoryStack
colorScale={"warm"}
>
<VictoryBar
data={data2012}
x="quarter"
y="earnings"
/>
<VictoryBar
data={data2013}
x="quarter"
y="earnings"
/>
<VictoryBar
data={data2014}
x="quarter"
y="earnings"
/>
<VictoryBar
data={data2015}
x="quarter"
y="earnings"
/>
</VictoryStack>
</VictoryChart>
)
}
render(<App/>);
5. react-vis
https://uber.github.io/react-vis/


특징
- 고수준 추상화보다 낮은 수준의 D3에 더 가까움
- 가파른 학습 곡선
예시
const data = [
{x: 0, y: 8},
{x: 1, y: 5},
{x: 2, y: 4},
{x: 3, y: 9},
{x: 4, y: 1},
{x: 5, y: 7},
{x: 6, y: 6},
{x: 7, y: 3},
{x: 8, y: 2},
{x: 9, y: 0}
];
...
<XYPlot height={200} width={200}>
<VerticalBarSeries data={data} />
</XYPlot>
<XYPlot height={200} width={200}>
<LineSeries data={data} />
</XYPlot>
<XYPlot height={200} width={200}>
<MarkSeries data={data} />
</XYPlot>
6. AG Charts
AG Charts는 AG-Grid에서 제공하는 차트 라이브러리입니다. AG Charts는 데이터를 시각적으로 표시할 수 있는 다양한 차트 컴포넌트를 제공하며, React뿐만 아니라 Angular, Vue와 같은 다른 프레임워크에서도 사용할 수 있습니다.
https://www.ag-grid.com/charts/?ref=blog.ag-grid.com

차트 라이브러리 비교
- JavaScript
| chart.js | D3.js | HighCharts | GoogleCharts | |
| 특징 |
|
|
|
|
| 라이센스 | MIT 라이센스 | MIT 라이센스, BSD 라이센스 | 상업용은 라이센스 구매가 필요 |
|
- React
| ReCharts | Victorys | Chart.js fo React | HighCharts for React | |
| 특징 |
|
|
|
|
| 라이센스 | MIT 라이센스 라이센스와 저작권 표시를 유지 |
MIT 라이센스 라이센스와 저작권 표시를 유지 |
MIT 라이센스 라이센스와 저작권 표시를 유지 |
상업용은 라이센스 구매가 필요 |

