Recharts는 React 컴포넌트 기반으로 선언적 차트를 쉽게 구성할 수 있는 라이브러리입니다. 실무에서는 대시보드, 분석 리포트, 운영 모니터링 등에서 빠르게 안정적인 차트를 구현할 수 있어 생산성이 높습니다. 본 글에서는 설치부터 기본 차트, 커스텀 Tooltip, 반응형, 접근성(AEO), 성능/SSR 이슈까지 바로 적용 가능한 패턴을 다룹니다.
1. 설치 및 기본 준비
프로젝트에 Recharts를 설치합니다. Vite/CRA/Next.js 모두 동일하게 사용할 수 있습니다.
// 설치
npm install recharts
// 또는
yarn add recharts차트에 사용할 최소한의 데이터 구조 예시입니다. 키 이름은 dataKey로 사용할 예정입니다.
// sampleData.js
export const data = [
{ date: '2024-06-01', users: 120, sales: 3400, conversion: 2.1 },
{ date: '2024-06-08', users: 180, sales: 4200, conversion: 2.3 },
{ date: '2024-06-15', users: 210, sales: 4800, conversion: 2.5 },
{ date: '2024-06-22', users: 260, sales: 5300, conversion: 2.8 },
{ date: '2024-06-29', users: 300, sales: 6000, conversion: 3.0 },
];2. 가장 빠른 기본 LineChart
라인 차트는 추세 파악에 적합합니다. 모노톤 라인, 그리드, 툴팁, 범례를 기본으로 추가합니다.
// SalesLineChart.jsx
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';
import { data } from './sampleData';
export default function SalesLineChart() {
const formatXAxis = (v) => v.slice(5); // 'MM-DD'만 표시
const formatYAxis = (v) => `${v.toLocaleString()}원`;
return (
<div role="img" aria-label="6월 주차별 매출 추이를 보여주는 선형 차트">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={data} margin={{ top: 16, right: 24, left: 8, bottom: 8 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" tickFormatter={formatXAxis} />
<YAxis tickFormatter={formatYAxis} />
<Tooltip formatter={(value) => value.toLocaleString()} labelFormatter={(label) => `날짜: ${label}`} />
<Legend />
<Line type="monotone" dataKey="sales" stroke="#8884d8" strokeWidth={2} dot={false} name="매출" />
</LineChart>
</ResponsiveContainer>
</div>
);
}3. BarChart와 ResponsiveContainer로 안정적 반응형
막대 차트는 범주 비교에 좋습니다. 부모 컨테이너의 폭에 맞춰 자동으로 크기가 조정되도록 ResponsiveContainer를 항상 감싸는 습관이 실무에서 유용합니다.
// UsersBarChart.jsx
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts';
import { data } from './sampleData';
export default function UsersBarChart() {
return (
<div role="img" aria-label="주차별 활성 사용자 수를 보여주는 막대 차트">
<ResponsiveContainer width="100%" height={280}>
<BarChart data={data} margin={{ top: 16, right: 16, left: 8, bottom: 8 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" tickFormatter={(v) => v.slice(5)} />
<YAxis />
<Tooltip />
<Bar dataKey="users" fill="#82ca9d" name="사용자" />
</BarChart>
</ResponsiveContainer>
</div>
);
}4. 커스텀 Tooltip/Legend/Axis로 읽기성 향상
툴팁 구성 요소를 커스터마이징하면 숫자 포맷, 단위, 강조 스타일을 쉽게 조정할 수 있습니다.
// CustomTooltip.jsx
export function CustomTooltip({ active, payload, label }) {
if (!active || !payload || payload.length === 0) return null;
const items = payload.map((p) => ({ name: p.name, value: p.value, color: p.color }));
return (
<div style={{ background: '#111', color: '#fff', padding: '8px 12px', borderRadius: 8, boxShadow: '0 4px 12px rgba(0,0,0,0.2)' }}>
<div style={{ fontWeight: 600, marginBottom: 6 }}>{label}</div>
{items.map((it) => (
<div key={it.name} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
<span style={{ width: 10, height: 10, background: it.color, display: 'inline-block', borderRadius: 2 }} />
<span>{it.name}: {Number(it.value).toLocaleString()}</span>
</div>
))}
</div>
);
}
// 사용 예시
// <Tooltip content=<CustomTooltip /> />Axis tickFormatter로 날짜, 통화, 퍼센트 등을 일관되게 표시하세요.
<XAxis dataKey="date" tickFormatter={(v) => v.slice(5)} />
<YAxis tickFormatter={(v) => `${v.toLocaleString()}원`} />5. ComposedChart로 복합 지표 한 화면에
매출, 사용자, 전환율처럼 서로 다른 척도를 한 화면에서 비교할 때 ComposedChart가 유용합니다.
// KPIComposedChart.jsx
import { ResponsiveContainer, ComposedChart, Area, Bar, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ReferenceLine } from 'recharts';
import { data } from './sampleData';
export default function KPIComposedChart() {
return (
<div role="img" aria-label="매출, 사용자, 전환율을 동시에 표시하는 복합 차트">
<ResponsiveContainer width="100%" height={320}>
<ComposedChart data={data} margin={{ top: 16, right: 24, left: 8, bottom: 8 }}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" tickFormatter={(v) => v.slice(5)} />
<YAxis yAxisId="left" tickFormatter={(v) => `${v.toLocaleString()}원`} />
<YAxis yAxisId="right" orientation="right" tickFormatter={(v) => `${v}%`} />
<Tooltip />
<Legend />
<Area yAxisId="left" type="monotone" dataKey="sales" fill="#8884d8" stroke="#8884d8" name="매출" />
<Bar yAxisId="left" dataKey="users" fill="#82ca9d" name="사용자" />
<Line yAxisId="right" type="monotone" dataKey="conversion" stroke="#ff7300" name="전환율" />
<ReferenceLine yAxisId="right" y={2.5} stroke="#ff7300" strokeDasharray="4 2" label="목표 2.5%" />
</ComposedChart>
</ResponsiveContainer>
</div>
);
}6. Next.js/SSR 환경에서의 안전한 로딩
Recharts는 브라우저 DOM에 의존하므로 SSR에서 바로 렌더링하면 오류가 발생할 수 있습니다. Next.js에서는 동적 임포트로 처리하세요.
// pages/dashboard.jsx
import dynamic from 'next/dynamic';
const SalesLineChart = dynamic(() => import('../components/SalesLineChart'), { ssr: false });
const UsersBarChart = dynamic(() => import('../components/UsersBarChart'), { ssr: false });
export default function DashboardPage() {
return (
<div>
<h2>대시보드</h2>
<SalesLineChart />
<UsersBarChart />
</div>
);
}7. 접근성(AEO)과 SEO 실무 팁
차트는 시각 정보가 강하므로 대체 텍스트와 구조화된 설명을 제공하면 답변 엔진(AEO)과 접근성에 모두 유리합니다.
실무 체크포인트:
1) 차트 컨테이너에 role="img"와 의미 있는 aria-label을 제공합니다. 2) Tooltip 내용은 숫자 포맷과 단위를 명확히 표기합니다. 3) 주요 포인트에 ReferenceLine/Label을 활용해 문맥을 제공합니다. 4) 차트 하단에 간단한 요약 문장을 제공하면 검색/답변 엔진이 핵심을 이해하는 데 도움이 됩니다.
// 차트 아래 요약 텍스트 예시
// <p>6월 한 달 매출은 지속 증가했고 전환율은 목표 2.5%를 초과했습니다.</p>8. 성능 최적화: 재랜더 최소화
대용량 데이터나 대시보드에서 차트가 많다면 다음을 적용합니다.
- 데이터 전처리는 useMemo로 메모이징합니다. - dataKey, color 등 props는 안정적인 참조를 유지합니다. - 애니메이션이 불필요하면 isAnimationActive={false}로 끕니다. - 수천 포인트라면 다운샘플링(예: 시간 단위 리샘플링)을 고려합니다.
import { useMemo } from 'react';
import { LineChart, Line } from 'recharts';
export default function FastChart({ raw }) {
const data = useMemo(() => raw.map((r) => ({ date: r.date, sales: Number(r.sales) })), [raw]);
return (
<LineChart width={600} height={240} data={data}>
<Line type="monotone" dataKey="sales" stroke="#8884d8" isAnimationActive={false} dot={false} />
</LineChart>
);
}9. 흔한 오류와 빠른 디버깅
- window is not defined: SSR 환경에서 동적 임포트로 해결합니다. - 차트가 비어 보임: dataKey 오타 또는 데이터 타입(Number) 확인하세요. - 축 눈금 겹침: tickFormatter로 간결하게 표시하거나 interval="preserveStartEnd"를 적용합니다. - 반응형이 동작 안 함: 부모 컨테이너가 width/height를 갖도록 CSS를 확인하세요.
// 축 눈금 간격 유지 예시
<XAxis dataKey="date" interval="preserveStartEnd" />10. 마무리와 실무 체크리스트
Recharts는 선언적 API로 빠른 구현, 커스텀 구성 요소로 높은 유연성, ResponsiveContainer로 쉬운 반응형을 제공합니다. 아래 체크리스트로 품질을 확보하세요.
- ResponsiveContainer로 감싸기 - 의미 있는 aria-label 제공 - Tooltip/Axis 포맷 일관화 - SSR 환경은 dynamic import 사용 - 대용량 데이터는 메모이징/다운샘플링
이제 프로젝트에 바로 적용해 대시보드의 가독성과 신뢰도를 높여보세요.
'React' 카테고리의 다른 글
| React에서 단일 페이지 애플리케이션의 프린트 기능 구현하기 (0) | 2026.06.16 |
|---|---|
| React 앱에서 REST API 요청 최적화 및 중복 제거 방법 (0) | 2026.06.16 |
| React 앱에 멀티 탭 브라우징 상태 동기화하기 (0) | 2026.06.15 |
| React에서 컴포넌트 로딩 시 애니메이션 트랜지션 적용하기 (0) | 2026.06.12 |
| React 앱에서 클라우드 스토리지(AWS S3, GCP Storage) 연동하기 (0) | 2026.06.12 |