Skip to content

필사 모드: 웹 데이터 시각화 라이브러리 2026 — D3·Plot·Visx·Recharts·ECharts·Vega-Lite를 한 번에 비교한다 (심층 가이드)

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — 차트 라이브러리는 왜 이렇게 많을까

처음 웹 차트를 처음 띄울 때 사람들이 한 번씩은 던지는 질문이 있다. **"그래서 뭘 써야 돼요?"** 답은 매번 같다. **"뭘 그리고 싶은데요?"**

이 질문이 짜증나 보여도, 그게 진짜 답이다. 2026년의 웹 차트 생태계는 한 차원으로 정리되지 않는다. 적어도 네 개의 축이 있다.

- **추상 수준** — 픽셀까지 손대고 싶은가, JSON 한 덩어리로 끝내고 싶은가.

- **프레임워크 친화도** — React인가, Vue/Svelte인가, 그냥 바닐라인가.

- **데이터 규모** — 점이 1,000개인가, 100만 개인가, 1억 개인가.

- **상호작용 깊이** — 정적 인포그래픽인가, 라이브 대시보드인가, 분석 UI인가.

이 네 축의 어디에 서느냐에 따라 같은 "막대 차트"도 D3로 짜면 80줄, Plot으로 짜면 3줄, Recharts로 짜면 12줄이 된다. **줄 수가 적은 게 좋은 게 아니다. 자유도가 적은 거다.**

2026년 5월 기준, 풍경을 한 줄로:

- **D3.js v7** — 여전히 모든 추상의 기반. npm 주간 다운로드 약 800만. 직접 쓰는 빈도는 줄었지만, 쓰는 모든 도구가 D3 위에 서 있다.

- **Observable Plot 0.7** — D3 메인테이너들이 만든 "그래머 오브 그래픽스" 레이어. ggplot2의 정신을 자바스크립트로 옮겼다.

- **Visx 3.x** — Airbnb의 React + D3 프리미티브. 활동성은 줄었지만 살아있고, 컴포넌트 위주 React 개발자에게 여전히 최적.

- **Recharts 2.15** — React 친화 기본값. 작은 대시보드의 가장 빠른 길.

- **Apache ECharts 6** — 2025년 후반에 6 메이저가 떨어졌다. Canvas·SVG 듀얼 렌더러, 거대한 차트 카탈로그, 중국·일본 엔터프라이즈 표준.

- **Vega-Lite 5.20** — JSON 한 덩어리 = 차트. 분석/리포트 자동 생성과 잘 맞는다.

- **Plotly.js 2.35** — 과학·금융용 인터랙티브 차트. 3D·지도까지.

- **Chart.js 4.5** — Canvas 기반, 가장 가볍게 시작하는 길.

- **AntV G2/G6 5** — 알리바바의 차트(G2)와 그래프/네트워크(G6) 패밀리.

- **Nivo 0.99** — React + D3 스타일링이 가장 예쁜 차트. 상업 사이트에 잘 어울린다.

- **Deck.gl 9 / regl 2** — WebGL/WebGPU로 수백만 점 그리는 GPU 가속 시각화.

이 글은 이 풍경을 **추상 사다리**로 정리한다 — 가장 낮은 곳(D3)부터 가장 높은 곳(Vega-Lite·Superset/Metabase)까지. 그리고 같은 차트를 네 라이브러리로 짜본 다음, **언제 뭘 써야 하는지** 결정 표를 남긴다.

1장 · 추상 사다리 — D3에서 Plot으로, Plot에서 래퍼로

차트 라이브러리를 고를 때 가장 먼저 봐야 하는 건 **추상 수준**이다. 같은 문제(데이터를 픽셀로 그리기)를 어느 층에서 푸느냐.

[ 가장 높음 ]

Superset / Metabase (SQL → 차트, 사용자 클릭으로 끝)

Vega-Lite (JSON 스펙) (선언형 그래머)

Recharts / Nivo / Chart.js (컴포넌트 기본값 차트)

Observable Plot (그래머 + JS API)

Visx / AntV G2 (D3 위 컴포넌트·언어 추상)

D3.js (스케일·축·셰이프·셀렉션)

Canvas 2D / SVG (브라우저 원시 API)

WebGL / WebGPU (GPU)

[ 가장 낮음 ]

이 사다리에서 **오를수록 빠르게 시작하지만, 자유도가 좁아진다.** 내려갈수록 모든 픽셀을 손에 쥐지만, 더 많은 줄을 쓴다.

실용 규칙 세 개:

1. **자기가 만들 차트가 라이브러리 갤러리에 있는 모양이면 위쪽 한두 칸에서 시작한다.** Recharts·Nivo·ECharts·Plot 정도면 80%의 대시보드가 끝난다.

2. **갤러리에 없으면 한 칸 내려간다.** "축이 두 개 있고, 위에 화살표가 떠다니고, 클릭하면 사이드 패널이 열린다" 같은 건 Plot이나 Visx로 짠다.

3. **그것도 안 되면 D3까지 내려간다.** Sankey·Force·Geo 같은 비표준 시각화나, "한 번에 50만 점 + 60fps 줌"처럼 성능이 극단인 경우.

남에게 보여줄 차트(블로그 도표·연구 리포트)는 **Plot으로 80%, D3로 20%** 처리한다. 제품 안의 대시보드는 **Recharts·ECharts로 80%, Visx·D3로 20%**.

2장 · D3.js — 모든 추상의 어머니

D3는 차트 라이브러리가 아니다. 정확히는, **데이터 → DOM 매핑 라이브러리**이고, 차트는 그 응용 중 하나일 뿐이다.

세 가지 핵심 추상을 기억하면 D3가 단번에 잡힌다.

스케일(Scale)

데이터 도메인(예: 0~1,000,000)을 픽셀 범위(예: 0~600)로 변환한다. 종류:

- `scaleLinear` · `scaleLog` · `scaleSqrt` · `scaleTime` — 연속형

- `scaleBand` · `scalePoint` · `scaleOrdinal` — 이산형

- `scaleSequential` · `scaleQuantize` — 색

const x = d3.scaleBand()

.domain(data.map(d => d.month))

.range([60, 740])

.padding(0.2)

const y = d3.scaleLinear()

.domain([0, d3.max(data, d => d.revenue)])

.range([460, 20])

셀렉션(Selection)과 조인(Join)

DOM 요소를 데이터에 묶는다. `d3.select` · `selectAll` · `.data()` · `.join()`.

const svg = d3.select('#chart').append('svg')

.attr('width', 800).attr('height', 480)

svg.selectAll('rect.bar')

.data(data)

.join('rect')

.attr('class', 'bar')

.attr('x', d => x(d.month))

.attr('y', d => y(d.revenue))

.attr('width', x.bandwidth())

.attr('height', d => 460 - y(d.revenue))

.attr('fill', '#4f46e5')

이게 D3 코드의 "심장"이다. 데이터가 바뀌면 `.join()` 한 줄이 enter/update/exit를 처리한다.

셰이프 제너레이터(Shape generator)

선·면·아크 path 문자열을 만든다. `d3.line` · `d3.area` · `d3.arc` · `d3.pie`. 모듈 단위로 임포트한다(트리셰이킹).

2026년에 D3를 직접 쓰는 경우

솔직히, **점점 줄고 있다.** 위쪽 한두 칸이 너무 좋아졌다. 그래도 D3를 직접 만져야 하는 순간:

- **비표준 시각화** — Sankey, Chord, Sunburst, Voronoi, Force-directed, Hexbin.

- **인터랙션이 차트의 본질** — 줌·드래그·러버밴드·브러시가 차트의 절반 이상.

- **성능을 직접 다뤄야 함** — Canvas 직접 그리기, 가상 스크롤, requestAnimationFrame 조율.

- **차트 라이브러리를 만든다** — Visx·Plot·Recharts 모두 내부적으로 D3 모듈을 쓴다.

D3의 함정도 하나. **버전 6/7부터 ES 모듈로 갈라졌다.** `d3-scale` · `d3-shape` · `d3-array`만 임포트하면 번들이 50KB대로 떨어진다. `import * as d3 from 'd3'`는 편하지만 250KB 가깝다.

3장 · Observable Plot — D3 위의 그래머 레이어

D3 메인테이너들이 만든 **고수준 API**. 한 줄 요약: **"R의 ggplot2를 자바스크립트로."**

ggplot2를 모른다면 "그래머 오브 그래픽스"가 뭔지부터. 차트를 **레이어(layer)·마크(mark)·스케일(scale)·인코딩(encoding)**으로 분해해서 조합한다. 막대도, 점도, 선도 다 "마크"라는 이름의 같은 추상이다.

같은 막대 차트를 D3 80줄 대신:

const chart = Plot.plot({

marginLeft: 60,

y: { grid: true, label: 'Revenue (USD)' },

x: { label: 'Month' },

marks: [

Plot.barY(data, { x: 'month', y: 'revenue', fill: '#4f46e5' }),

Plot.ruleY([0])

]

})

document.getElementById('chart').append(chart)

5줄이다. 그리고 이 5줄은 **D3 위에 그대로 깔려 있어서**, 필요하면 그 아래로 내려갈 수 있다. 격자·스케일·축·범례가 모두 합리적인 기본값으로 켜져 있고, `Plot.plot` 한 번에 인터랙션·면적·히트맵·박스플롯·지도까지 다 된다.

2026년의 Plot 위상

- 버전 **0.7**(2025년 후반). 1.0 전이지만 프로덕션에서 충분히 안정.

- **Observable Framework**(정적 사이트 → 데이터 페이지)와 함께 데이터 저널리즘·내부 대시보드의 표준에 가까워졌다.

- React/Vue/Svelte 어디서든 쓴다(반환이 DOM 노드라 그냥 `appendChild`).

- 인터랙션은 **`Plot.crosshair` · `Plot.tooltip` · `Plot.pointer`** 같은 인터랙션 마크로 처리.

Plot이 잘 안 맞는 경우

- 픽셀 단위로 다르게 그려야 하는 커스텀 시각화.

- 한 차트 안에 인터랙션이 매우 복잡한 경우(드래그 + 다중 선택 + 사이드 패널 동기).

- 100만 점 이상 — Canvas 모드(`Plot.dot` + `render: Plot.renderCanvas` 옵션)도 있지만, 본질은 SVG 기반.

**한 줄:** 블로그 도표·연구 리포트·데이터 저널리즘은 거의 다 Plot이면 끝난다.

4장 · Visx — Airbnb의 React + D3 프리미티브

Visx는 D3 모듈을 **React 컴포넌트로 재포장**한 것이다. **차트 라이브러리가 아니라 차트를 만드는 도구 모음.**

- `@visx/scale` — D3 스케일을 React 친화 인터페이스로.

- `@visx/shape` — Bar, Line, Area, Pie 등 path를 그리는 컴포넌트.

- `@visx/axis` · `@visx/grid` · `@visx/legend`.

- `@visx/tooltip` — 포지셔닝까지 처리한 툴팁 훅.

- `@visx/responsive` — `ParentSize`로 컨테이너 폭 자동 추적.

장점은 분명하다.

- **순수 React** — 가상 DOM 안에서 끝까지 산다. `useEffect` 없이.

- **트리셰이킹** — 필요한 것만 import.

- **타입스크립트** — 타입이 정확하다.

function RevenueChart({ data, width = 800, height = 480 }) {

const xScale = scaleBand({

domain: data.map(d => d.month),

range: [60, width - 20],

padding: 0.2,

})

const yScale = scaleLinear({

domain: [0, Math.max(...data.map(d => d.revenue))],

range: [height - 30, 20],

})

return (

{data.map(d => (

key={d.month}

x={xScale(d.month)}

y={yScale(d.revenue)}

width={xScale.bandwidth()}

height={(height - 30) - yScale(d.revenue)}

fill="#4f46e5"

/>

))}

)

}

2026년의 Visx 위상

솔직히 한마디 해야 한다. **활동성은 둔화됐다.** 메이저 릴리스가 뜸하고, 이슈 처리 속도도 떨어졌다. 그래도:

- 아직 **유지보수는 살아있다**(2025년 후반에도 패치 릴리스가 나왔다).

- React로 D3 프리미티브가 필요한 사람에게는 여전히 1순위.

- Airbnb 내부에서 쓰니까 사라지진 않는다.

**한 줄:** "Recharts/Nivo가 너무 답답하고, D3로 직접 가긴 싫다"의 정확한 자리.

5장 · Recharts — React 친화 기본값의 왕

Recharts는 **"빠르게 시작하고 충분히 멀리 간다"**의 대명사다. 2026년 5월 기준 **v2.15**. v3 베타가 있긴 한데 프로덕션은 2.15가 표준.

같은 막대 차트:

function RevenueChart({ data }) {

return (

)

}

12줄. 반응형·툴팁·축·격자가 다 켜져 있다. 80%의 SaaS 대시보드는 여기서 끝.

Recharts가 정말 강한 지점

- **React 컴포넌트로 깔끔하게 모인다** — 상태가 React로 들어오고 나간다.

- **합성(composition)** — `Bar` + `Line` + `Area`를 한 차트에 섞는 게 자연스럽다.

- **반응형** — `ResponsiveContainer` 한 줄.

- **TypeScript** 타입 정의가 합리적.

Recharts의 약점

- **SVG 기반** — 5천 개 이상이면 살짝 끈적해지고, 1만 개 이상은 무겁다.

- **고급 인터랙션은 한계** — 줌·브러시·다중 선택을 깊게 들어가면 Plot/Visx로 가야 한다.

- **시각적으로 평범** — 디자인 톤은 디자이너의 손이 필요하다.

**한 줄:** 사내 대시보드·BI 위젯·블로그 차트라면 Recharts부터 시작하라. 거기서 안 풀리면 한 칸 내려간다.

6장 · Apache ECharts 6 — 엔터프라이즈의 야수

2025년 11월에 떨어진 **ECharts 6**은 단순한 차트 라이브러리가 아니라 **시각화 플랫폼**에 가깝다. Apache 재단 정식 프로젝트.

특징을 빠르게:

- **Canvas + SVG 듀얼 렌더러** — 같은 옵션 객체로 둘 다 그린다. 대용량은 Canvas, 인쇄/벡터는 SVG.

- **거대한 차트 카탈로그** — Bar/Line/Scatter는 기본, Sankey·Tree·Treemap·Sunburst·Funnel·Gauge·Radar·Parallel·BoxPlot·Heatmap·Calendar·Graph·Map(GeoJSON)·3D(echarts-gl)까지.

- **선언적 옵션** — JSON 한 덩어리로 차트가 끝난다(Vega-Lite와 비슷한 정신).

- **반응형** — `resize` 한 줄.

- **WebGL 백엔드** — `echarts-gl`로 100만 점 산점도·3D 지도.

같은 막대 차트:

echarts.use([BarChart, GridComponent, TooltipComponent, CanvasRenderer])

const chart = echarts.init(document.getElementById('chart'))

chart.setOption({

xAxis: { type: 'category', data: data.map(d => d.month) },

yAxis: { type: 'value' },

tooltip: { trigger: 'axis' },

series: [{ type: 'bar', data: data.map(d => d.revenue), itemStyle: { color: '#4f46e5' } }],

})

ECharts가 강한 이유

- **차트 종류** — Bar/Line만 그릴 거면 Recharts가 낫다. **Sunburst·Sankey·Radar·Map·Calendar Heatmap이 한 라이브러리에 다 있는 곳은 ECharts가 거의 유일.**

- **대용량 처리** — Canvas 기본 + Progressive Rendering으로 50만 점 산점도가 자연스럽게 돈다.

- **테마 시스템** — JSON 테마로 한 번에 톤 갈아끼우기.

- **i18n** — 처음부터 다국어 전제.

ECharts의 약점

- **번들 사이즈** — 풀 빌드는 1MB가 넘는다. **모듈 분리 import**가 필수.

- **React 친화도** — 직접 init/dispose를 손으로 관리해야 한다. `echarts-for-react` 같은 래퍼가 있긴 함.

- **API 표면이 거대** — 옵션 객체가 깊다. 옵션 한 줄 차이로 결과가 크게 달라진다.

**한 줄:** "차트 종류가 폭주하는 BI" 또는 "데이터가 많고 인터랙션이 풍부해야 하는 대시보드"라면 ECharts.

7장 · Vega-Lite — JSON 한 덩어리가 차트가 된다

워싱턴 대학에서 시작된 **선언형 그래머**. JSON 하나로 차트를 정의한다.

vegaEmbed('#chart', {

$schema: 'https://vega.github.io/schema/vega-lite/v5.json',

data: { values: data },

mark: { type: 'bar', color: '#4f46e5' },

encoding: {

x: { field: 'month', type: 'ordinal' },

y: { field: 'revenue', type: 'quantitative' },

},

})

이게 끝이다. 그리고 이 JSON 스펙은 **버전 관리 가능하고, 사람이 읽고 쓰기 좋고, 자동 생성하기도 쉽다.**

어디서 빛나는가

- **분석 리포트 자동 생성** — LLM이 데이터 보고 JSON을 뱉으면 그게 곧 차트. Vega-Lite는 LLM 시대에 의외로 잘 맞는 포맷이다.

- **데이터 저널리즘** — 차트의 "스펙"을 코드와 분리해서 관리.

- **Jupyter/Altair 연동** — 파이썬 Altair가 같은 스펙을 뱉는다. 노트북에서 그린 차트를 그대로 웹으로 이식.

약점

- **인터랙션 깊이** — 기본 selection 문법이 있지만, "차트 클릭하면 외부 React 상태가 바뀌어야 함" 같은 통합에는 손이 든다.

- **번들** — Vega + Vega-Lite + vega-embed면 가볍지 않다.

**한 줄:** 차트의 "데이터/규격"을 시스템적으로 다루고 싶다면 Vega-Lite.

8장 · 그 외 — Plotly, Chart.js, AntV, Nivo

빠르게 한 줄씩.

- **Plotly.js 2.35** — 과학/금융 인터랙티브 차트의 클래식. 3D·Geo·Financial(OHLC, Candlestick)이 강하다. 번들이 무거운 게 단점(MathJax 빼고도 700KB+). `plotly.js-basic-dist`로 부분 임포트가 답.

- **Chart.js 4.5** — Canvas 기반. 가볍고 친절하지만 차트 종류가 적다. 작은 프로젝트의 첫 라이브러리로 무난.

- **AntV G2 5 / G6 5** — 알리바바의 차트 G2와 그래프/네트워크 G6. 그래프 시각화는 G6가 D3-Force보다 편하다. 중국·일본권에서 강세.

- **Nivo 0.99** — React + D3로 만든, **가장 예쁜 기본값**을 가진 차트. 상업 사이트·랜딩 페이지에 잘 어울린다. 단점: 번들이 크고, 커스터마이즈 깊이는 Recharts/Visx보다 좁다.

9장 · 같은 막대 차트를 네 라이브러리로 — 한눈에

월별 매출(`[{month: 'Jan', revenue: 12400}, ...]`)을 막대로 그린다. 같은 데이터, 네 가지 접근.

D3 (저수준)

const width = 800, height = 480, margin = { top: 20, right: 20, bottom: 30, left: 60 }

const svg = d3.select('#chart').append('svg').attr('width', width).attr('height', height)

const x = d3.scaleBand().domain(data.map(d => d.month))

.range([margin.left, width - margin.right]).padding(0.2)

const y = d3.scaleLinear().domain([0, d3.max(data, d => d.revenue)]).nice()

.range([height - margin.bottom, margin.top])

svg.append('g').attr('transform', `translate(0,${height - margin.bottom})`).call(d3.axisBottom(x))

svg.append('g').attr('transform', `translate(${margin.left},0)`).call(d3.axisLeft(y))

svg.selectAll('rect.bar').data(data).join('rect')

.attr('class', 'bar')

.attr('x', d => x(d.month))

.attr('y', d => y(d.revenue))

.attr('width', x.bandwidth())

.attr('height', d => y(0) - y(d.revenue))

.attr('fill', '#4f46e5')

자유도 100. 줄 수 25. 인터랙션 따로 추가.

Observable Plot (그래머)

const chart = Plot.plot({

marginLeft: 60,

y: { grid: true, label: 'Revenue (USD)' },

marks: [

Plot.barY(data, { x: 'month', y: 'revenue', fill: '#4f46e5', tip: true }),

Plot.ruleY([0]),

],

})

document.getElementById('chart').append(chart)

자유도 70. 줄 수 8. 툴팁 한 옵션.

Recharts (React 컴포넌트)

function RevenueChart({ data }) {

return (

)

}

자유도 60. 줄 수 12. React 합성 친화.

ECharts (선언형 옵션)

const chart = echarts.init(document.getElementById('chart'))

chart.setOption({

grid: { left: 60, right: 20, top: 20, bottom: 30 },

xAxis: { type: 'category', data: data.map(d => d.month) },

yAxis: { type: 'value', name: 'Revenue (USD)' },

tooltip: { trigger: 'axis' },

series: [{ type: 'bar', data: data.map(d => d.revenue), itemStyle: { color: '#4f46e5' } }],

})

window.addEventListener('resize', () => chart.resize())

자유도 80. 줄 수 11. 옵션 객체 한 덩어리.

줄 수가 다 비슷한데, 뭐가 다른가

줄 수만 보면 큰 차이가 없다. 진짜 차이는:

- **D3** — 데이터가 바뀌었을 때, 마우스 오버 했을 때, 줌 했을 때, **모든 동작을 손으로 짠다.**

- **Plot** — 한 차트 단위. 인터랙션은 옵션으로. 외부 상태와의 통합은 약함.

- **Recharts** — React 상태로 모든 게 흐른다. `state.month`가 바뀌면 즉시 다시 그린다.

- **ECharts** — `chart.setOption()` 한 번으로 갈아끼운다. React 안에선 `useEffect`로 동기화 직접.

차트가 **앱의 한 구성요소**라면 Recharts/Visx, **데이터 → 그림이 본질**이라면 Plot/ECharts/D3.

10장 · 대용량 데이터 — Canvas, WebGL, Deck.gl, regl

여기부터는 다른 게임이다. **점 1만 개까지는 SVG로도 된다. 10만 개부터는 Canvas. 100만 개부터는 WebGL.**

왜 SVG가 느려지는가

SVG는 각 점이 **DOM 노드**다. 점 10만 개 = DOM 10만. 브라우저의 레이아웃·페인트 비용이 노드 수에 선형으로 따라온다. 5천~1만 노드 근방에서 인터랙션이 끈적해지기 시작하고, 10만에서는 페이지 자체가 무거워진다.

Canvas 2D — 첫 단계

Canvas는 한 노드(`canvas` 엘리먼트) 안에 픽셀을 그린다. 점이 100만 개여도 DOM은 한 개. 단점은 **히트 테스트(어느 점에 마우스가 올라갔나)를 직접 짜야 한다는 것**.

라이브러리 별 Canvas 모드:

- **D3** — `canvas.getContext('2d')`로 직접 그리기. D3 스케일·셰이프는 그대로 쓴다.

- **Plot** — `Plot.dot(..., { render: Plot.renderCanvas })` 형식의 Canvas 마크.

- **Chart.js / ECharts** — 기본이 Canvas.

- **Recharts / Visx** — 기본 SVG. Canvas 모드는 없거나 제한적.

WebGL — 두 번째 단계

GPU로 점을 그린다. 100만 점도 가볍게.

- **regl 2.x** — WebGL을 functional하게 감싼 얇은 레이어. D3·Plot과 함께 쓰면 "스케일은 JS, 그리기는 GPU"가 깔끔.

- **Deck.gl 9** — Uber의 GPU 시각화 프레임워크. 지도(MapboxGL/MapLibre/Google Maps) 위 1억 점, 3D 빌딩, 히트맵, 트레이일. 데이터 시각화 + 지도가 가장 자연스러운 곳.

- **PixiJS / Three.js + 인스턴싱** — 일반 시각화는 아니지만, 산점도 100만 점에 쓰는 경우가 있다.

WebGPU — 다음 단계

2026년 1월에 WebGPU가 모든 메이저 브라우저에서 Baseline이 됐다. 시각화 라이브러리들은 천천히 따라가는 중.

- **Deck.gl**은 9.x에서 WebGPU 렌더러를 실험적으로 제공.

- **regl-gpu**가 일부 프로젝트에서 쓰임.

- 본격 채택은 2026년 말~2027년 사이.

100만 점 산점도, 무엇으로 그리는가

선택 흐름:

1. **지도 위라면 Deck.gl** — 의심 없이.

2. **지도가 아니고 산점만이라면 regl + D3 스케일** — 100~300줄로 다 짠다.

3. **빠르게 시작하고 싶고 정해진 차트 패턴이라면 ECharts 6 + Progressive Rendering** — 옵션 한 줄.

4. **Three.js를 이미 쓰고 있다면 InstancedMesh**.

11장 · 결정 프레임워크 — 언제 무엇을 쓰는가

표 하나에 정리한다.

| 시나리오 | 1순위 | 2순위 | 메모 |

|---------|------|-------|------|

| React 앱의 사내 대시보드 (점 < 5,000) | Recharts | Nivo | 합성·반응형이 자연스럽다 |

| Vue/Svelte/바닐라 대시보드 | ECharts | Plot | 프레임워크 중립 |

| 블로그 도표·연구 리포트 | Plot | ECharts | 5줄로 끝, 인쇄 깔끔 |

| 분석/탐색 UI (인터랙션 깊음) | Visx | D3 직접 | React 합성 + 자유도 |

| BI 위젯, 차트 종류 폭주 | ECharts 6 | Plotly | Sankey/Sunburst/Calendar |

| Sankey·Force·Chord 등 비표준 | D3 직접 | AntV G6 | 라이브러리 갤러리에 없음 |

| 지도 위 점/히트맵 | Deck.gl | Mapbox GL | GPU 가속 + 지도 |

| 100만 점 산점도 | regl + D3 | ECharts (Canvas) | DOM 한 개로 GPU |

| 과학/금융 (3D, OHLC) | Plotly | ECharts | 도메인 특화 |

| JSON 스펙으로 자동 생성 | Vega-Lite | Plot | LLM 친화 |

| 그래프/네트워크 | AntV G6 | D3-Force | G6의 알고리즘 카탈로그 |

| 데모/포트폴리오 | Nivo | Plot | 보기 좋음 우선 |

| 시스템적 데이터 셀프서비스 | Superset/Metabase | Lightdash | 사용자 클릭 = 차트 |

12장 · 안티패턴 — 실무에서 자주 보는 사고

자주 보는 잘못 다섯 개.

1. **5천 점 라이브 산점도를 Recharts(SVG)로** — Canvas/ECharts로 바꾸면 즉시 살아난다.

2. **Plotly 풀 빌드를 한 차트 그리려고 import** — `plotly.js-basic-dist`나 ECharts로 도망.

3. **D3로 막대 차트를 80줄 짜기** — Plot/Recharts 5~12줄이면 끝나는 일.

4. **ECharts를 React에서 init·dispose 누락** — 메모리 리크. `useEffect` 정리 함수 필수.

5. **여러 차트 라이브러리를 한 페이지에서 섞기** — 번들이 폭주, 디자인 톤이 불일치. **하나만 골라 끝까지 간다.**

13장 · BI 소비자 측 — Superset, Metabase, Lightdash

마지막 한 갈래. **차트를 직접 짜지 않는** 길.

- **Apache Superset** — 차트 종류 60종+, ECharts 기반, 무료 셀프호스트. 단점: 운영이 무겁다.

- **Metabase** — 가장 친절한 셀프서비스 BI. 비기술 사용자가 쿼리 없이 차트를 만든다. 오픈코어 + 클라우드.

- **Lightdash** — dbt 위에 올린 BI. 메트릭 정의를 dbt에 두고 그걸 시각화. 데이터 엔지니어링 친화.

- **Grafana** — 시계열·관측성에 특화. 시각화 라이브러리이기도 하다(공개 패널).

데이터팀이 차트를 코드로 짜는 시대는 점점 끝나가고 있다. **개발자가 짤 차트는 줄어들고, BI 도구가 짤 차트는 늘어난다.** 그게 2026년의 큰 그림이다.

에필로그 — 사다리의 어디에 설지

웹 데이터 시각화는 **사다리**다. 위쪽으로 갈수록 빠르지만 좁고, 아래로 갈수록 느리지만 자유롭다. 2026년의 풍경에서 기억할 한 줄.

- **위쪽 80%** — Recharts(React), ECharts(범용), Plot(블로그/리포트)이면 거의 다 된다.

- **중간 15%** — 인터랙션이 깊어지면 Visx, 차트가 비표준이면 D3.

- **아래쪽 5%** — 100만 점·지도 위 시각화는 Deck.gl / regl / WebGL/WebGPU.

이 비율은 라이브러리 인기와도 거의 비례한다. 그리고 그 가운데, **D3는 직접 보이지 않게 모든 것의 아래에 깔려 있다.** 라이브러리 하나를 고를 때마다, 그 라이브러리가 D3 모듈을 어떻게 쓰는지를 한 번 들여다보는 것이 다음 차트 라이브러리를 고를 때의 안목이 된다.

12개 체크리스트

1. 차트가 React 컴포넌트로 자연스럽게 합성되는가?

2. 데이터가 5,000점을 넘어가면 SVG에서 Canvas/WebGL로 옮겼는가?

3. ECharts/Plotly 같은 거대 라이브러리는 모듈 분리 import를 썼는가?

4. 같은 데이터에 차트 라이브러리가 두 개 이상 섞여 있지 않은가?

5. 반응형은 ResizeObserver(또는 라이브러리 기본값)로 잡혔는가?

6. 색 팔레트가 색맹 친화(viridis/cividis 등)인가?

7. 0부터 시작하지 않는 y축이 사용자에게 명시되는가?

8. 툴팁/포커스는 키보드로도 접근 가능한가?

9. 차트의 원본 데이터가 CSV/JSON으로 다운로드 가능한가?

10. 인쇄/PDF에서 깨지지 않는 SVG 모드가 준비됐는가?

11. 차트 라이브러리의 트리쉐이킹이 번들 분석기에서 확인됐는가?

12. 다국어(라벨/날짜/숫자 포맷)가 처음부터 들어갔는가?

다음 글 예고

다음 글 후보: **D3 + WebGL 산점도 100만 점 60fps 만들기**, **Vega-Lite로 LLM이 차트를 직접 그리게 하기**, **Observable Framework로 정적 데이터 페이지 워크플로**.

> "차트는 데이터의 마지막 한 마디다. 그 한 마디를 어느 사다리에서 외칠지가, 글의 어조를 결정한다."

— 웹 데이터 시각화 라이브러리 2026, 끝.

참고 / References

- D3.js — https://d3js.org/

- Observable Plot — https://observablehq.com/plot/

- Observable Framework — https://observablehq.com/framework/

- Visx (Airbnb) — https://airbnb.io/visx/

- Recharts — https://recharts.org/

- Apache ECharts — https://echarts.apache.org/

- Vega-Lite — https://vega.github.io/vega-lite/

- Plotly.js — https://plotly.com/javascript/

- Chart.js — https://www.chartjs.org/

- AntV G2 — https://g2.antv.antgroup.com/

- AntV G6 — https://g6.antv.antgroup.com/

- Nivo — https://nivo.rocks/

- Deck.gl — https://deck.gl/

- regl — https://github.com/regl-project/regl

- Apache Superset — https://superset.apache.org/

- Metabase — https://www.metabase.com/

- Lightdash — https://www.lightdash.com/

- Grafana — https://grafana.com/

- A Layered Grammar of Graphics (Hadley Wickham) — https://vita.had.co.nz/papers/layered-grammar.html

현재 단락 (1/325)

처음 웹 차트를 처음 띄울 때 사람들이 한 번씩은 던지는 질문이 있다. **"그래서 뭘 써야 돼요?"** 답은 매번 같다. **"뭘 그리고 싶은데요?"**

작성 글자: 0원문 글자: 13,963작성 단락: 0/325