[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
---
|
||||
id: react-charts-library-comparison
|
||||
title: React Charts — Recharts / Visx / D3 / Tremor
|
||||
category: Coding
|
||||
status: draft
|
||||
source_trust_level: B
|
||||
verification_status: conceptual
|
||||
created_at: 2026-05-09
|
||||
updated_at: 2026-05-09
|
||||
tags: [react, charts, dataviz, vibe-coding]
|
||||
tech_stack: { language: "TS / React", applicable_to: ["Frontend"] }
|
||||
applied_in: []
|
||||
aliases: [Recharts, Visx, D3, Tremor, Nivo, Chart.js, dataviz]
|
||||
---
|
||||
|
||||
# React Charts
|
||||
|
||||
> **Recharts = 빠른 시작, 한정**. **Visx (Airbnb) = D3 위 React 컴포넌트, 유연**. **D3 직접 = 풀 컨트롤**. **Tremor / shadcn charts = dashboard UI 일관성**.
|
||||
|
||||
## 📖 핵심 개념
|
||||
- High-level: 차트 종류 직접 (Bar, Line). 빠른 시작.
|
||||
- Low-level: scale / axis / shape 조립. 유연.
|
||||
- Headless: 행동만, 스타일 너의 것.
|
||||
|
||||
## 💻 코드 패턴
|
||||
|
||||
### Recharts (간단)
|
||||
```tsx
|
||||
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
|
||||
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<LineChart data={data}>
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Line type="monotone" dataKey="value" stroke="#3b82f6" />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
```
|
||||
|
||||
→ Pros: 5분 setup. Cons: 복잡 customization 어려움, 큰 데이터 느림.
|
||||
|
||||
### Tremor (대시보드 UI)
|
||||
```tsx
|
||||
import { Card, AreaChart, Title, Metric, Flex, BadgeDelta } from '@tremor/react';
|
||||
|
||||
<Card>
|
||||
<Flex>
|
||||
<Title>Sales</Title>
|
||||
<BadgeDelta deltaType="moderateIncrease">+12%</BadgeDelta>
|
||||
</Flex>
|
||||
<Metric>$12,345</Metric>
|
||||
<AreaChart data={data} index="date" categories={['sales']} colors={['blue']} />
|
||||
</Card>
|
||||
```
|
||||
|
||||
→ Tailwind based. Dashboard 만들기 빠름.
|
||||
|
||||
### Visx (Airbnb, low-level + React)
|
||||
```tsx
|
||||
import { LinePath } from '@visx/shape';
|
||||
import { scaleLinear } from '@visx/scale';
|
||||
import { AxisBottom, AxisLeft } from '@visx/axis';
|
||||
import { GridRows, GridColumns } from '@visx/grid';
|
||||
|
||||
const xScale = scaleLinear({ domain: [0, 100], range: [0, width] });
|
||||
const yScale = scaleLinear({ domain: [0, 100], range: [height, 0] });
|
||||
|
||||
<svg width={width + 60} height={height + 40}>
|
||||
<g transform="translate(40, 10)">
|
||||
<GridRows scale={yScale} width={width} />
|
||||
<GridColumns scale={xScale} height={height} />
|
||||
<LinePath
|
||||
data={data}
|
||||
x={d => xScale(d.x)}
|
||||
y={d => yScale(d.y)}
|
||||
stroke="#3b82f6"
|
||||
strokeWidth={2}
|
||||
/>
|
||||
<AxisLeft scale={yScale} />
|
||||
<AxisBottom scale={xScale} top={height} />
|
||||
</g>
|
||||
</svg>
|
||||
```
|
||||
|
||||
→ Pros: D3 의 power + React 의 declarative. Cons: 학습 곡선.
|
||||
|
||||
### D3 직접 (max 컨트롤)
|
||||
```tsx
|
||||
import * as d3 from 'd3';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
function Chart({ data }: { data: { x: number; y: number }[] }) {
|
||||
const ref = useRef<SVGSVGElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const svg = d3.select(ref.current);
|
||||
const x = d3.scaleLinear().domain(d3.extent(data, d => d.x) as [number, number]).range([0, 400]);
|
||||
const y = d3.scaleLinear().domain([0, d3.max(data, d => d.y)!]).range([200, 0]);
|
||||
|
||||
const line = d3.line<typeof data[0]>().x(d => x(d.x)).y(d => y(d.y));
|
||||
|
||||
svg.append('path')
|
||||
.datum(data)
|
||||
.attr('d', line)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', '#3b82f6');
|
||||
}, [data]);
|
||||
|
||||
return <svg ref={ref} width={400} height={200} />;
|
||||
}
|
||||
```
|
||||
|
||||
→ React 와 D3 dual responsibility — declarative 깨질 수 있음.
|
||||
|
||||
### shadcn charts (Recharts wrapper, Tailwind theme)
|
||||
```tsx
|
||||
import { ChartContainer, ChartTooltip, ChartTooltipContent, ChartConfig } from '@/components/ui/chart';
|
||||
import { Bar, BarChart, XAxis } from 'recharts';
|
||||
|
||||
const config = {
|
||||
sales: { label: 'Sales', color: 'hsl(var(--chart-1))' },
|
||||
} satisfies ChartConfig;
|
||||
|
||||
<ChartContainer config={config}>
|
||||
<BarChart data={data}>
|
||||
<XAxis dataKey="month" />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
<Bar dataKey="sales" fill="var(--color-sales)" radius={4} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
```
|
||||
|
||||
→ Recharts power + shadcn theming + a11y.
|
||||
|
||||
### 큰 데이터 — canvas
|
||||
```tsx
|
||||
// React-vis-style 또는 직접 canvas
|
||||
import { Canvas } from '@react-three/fiber'; // 3D 차트
|
||||
// 또는 visx/visx-glyph + canvas renderer
|
||||
```
|
||||
|
||||
10K+ 점 = SVG 느림. Canvas 또는 WebGL.
|
||||
|
||||
### Animation
|
||||
```tsx
|
||||
// Recharts: animation 자동 (animationDuration)
|
||||
<Line dataKey="v" isAnimationActive={true} animationDuration={500} />
|
||||
|
||||
// Visx + framer-motion
|
||||
<motion.path d={pathD} initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} />
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준
|
||||
| 상황 | 추천 |
|
||||
|---|---|
|
||||
| 빠른 dashboard | Tremor |
|
||||
| 단순 차트 | Recharts |
|
||||
| Custom + Tailwind 일관성 | shadcn charts |
|
||||
| 복잡 / 유연 | Visx |
|
||||
| 풀 컨트롤 + 큰 데이터 | D3 + canvas |
|
||||
| 3D / WebGL | three.js / r3f |
|
||||
| Native mobile | Victory Native / react-native-skia |
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Recharts 로 10K 점**: 느림. Canvas.
|
||||
- **D3 + React 같이 DOM 조작**: race. D3 가 SVG 만들고 React 가 render layer.
|
||||
- **차트 안에 큰 ResponsiveContainer 매번 resize**: ResizeObserver throttle.
|
||||
- **Tooltip 매 hover 새 객체**: re-render. memoize.
|
||||
- **색 hard-code**: 다크모드 X. theme 사용.
|
||||
- **Axis 너무 많은 tick**: 가독성 낮음. format / count 제한.
|
||||
- **A11y 무시 — SVG only**: aria-label / 표 alternative.
|
||||
|
||||
## 🤖 LLM 활용 힌트
|
||||
- 시작 = Recharts / Tremor.
|
||||
- 큰 / 유연 = Visx.
|
||||
- shadcn charts 가 Tailwind 사용자에게 sweet spot.
|
||||
|
||||
## 🔗 관련 문서
|
||||
- [[Frontend_Design_Tokens]]
|
||||
- [[React_Animation_Performance]]
|
||||
- [[Frontend_A11y_Testing]]
|
||||
Reference in New Issue
Block a user