실무 대시보드에서 빠르게 신뢰성 있는 차트를 붙여야 한다면 Highcharts는 훌륭한 선택입니다. React에서 공식 래퍼를 사용하면 설정만으로 라인, 컬럼, 영역, 파이 차트를 쉽게 구현할 수 있습니다. 이 글은 설치부터 동적 업데이트, 반응형, 내보내기, 접근성, SSR(Next.js) 이슈까지 실무 팁 중심으로 정리합니다. 상업적 사용은 라이선스를 확인하시기 바랍니다.
1. 설치
# npm
yarn add highcharts highcharts-react-official
# or
yarn add highcharts highcharts-react-official
2. 가장 빠른 라인 차트 예제
import React, { useMemo } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
export default function LineChartBasic() {
const options = useMemo(() => ({
chart: { type: 'line', height: 300 },
title: { text: '월간 가입자 추이' },
xAxis: { categories: ['1월','2월','3월','4월','5월','6월'] },
yAxis: { title: { text: '인원' } },
series: [{ name: '가입자', data: [120, 200, 180, 260, 300, 420] }],
credits: { enabled: false },
legend: { enabled: true }
}), [])
return <HighchartsReact highcharts={Highcharts} options={options} />
}
옵션 객체는 useMemo로 메모이제이션하여 불필요한 재렌더와 차트 재생성을 줄입니다.
3. 옵션 최적화 포인트
실무에서 성능 이슈는 대부분 옵션/데이터 참조가 매 렌더마다 새로 생성되면서 발생합니다. 다음을 지킵니다.
- options, series 데이터 배열에 useMemo를 사용합니다.
- 이벤트 핸들러와 formatter는 화살표 함수 대신 function 키워드를 사용해 Highcharts의 this 컨텍스트를 보장합니다.
- 고빈도 업데이트는 차트 인스턴스 API로 mutate하는 것이 효율적입니다.
4. 동적 데이터 업데이트: 상태 기반
import React, { useEffect, useMemo, useState } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
export default function LiveLineChart() {
const [data, setData] = useState([5, 7, 3, 6, 9, 4])
useEffect(() => {
const id = setInterval(() => {
setData(d => [...d.slice(1), Math.round(Math.random() * 10)])
}, 1500)
return () => clearInterval(id)
}, [])
const options = useMemo(() => ({
chart: { animation: false, height: 280 },
title: { text: '실시간 지표' },
xAxis: { categories: Array.from({ length: data.length }, (_, i) => `${i + 1}`) },
series: [{ type: 'line', name: '값', data }],
credits: { enabled: false }
}), [data])
return <HighchartsReact highcharts={Highcharts} options={options} />
}
5. 동적 데이터 업데이트: 차트 인스턴스 API
고빈도 업데이트라면 차트 인스턴스를 직접 갱신하는 것이 비용이 낮습니다.
import React, { useEffect, useRef } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
export default function LiveWithInstance() {
const chartRef = useRef(null)
const options = {
chart: { type: 'line', height: 260 },
title: { text: '고빈도 업데이트' },
series: [{ name: 'CPU', data: Array.from({ length: 20 }, () => 0) }],
credits: { enabled: false }
}
useEffect(() => {
const id = setInterval(() => {
const chart = chartRef.current?.chart
if (!chart) return
const series = chart.series[0]
series.addPoint(Math.round(Math.random() * 100), true, true) // shift=true
}, 500)
return () => clearInterval(id)
}, [])
return (
<HighchartsReact
highcharts={Highcharts}
options={options}
allowChartUpdate={false}
ref={chartRef}
/>
)
}
6. 컬럼 차트 예제
import React, { useMemo } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
export default function ColumnChart() {
const options = useMemo(() => ({
chart: { type: 'column', height: 300 },
title: { text: '부서별 매출' },
xAxis: { categories: ['영업','마케팅','개발','운영'] },
yAxis: { title: { text: '백만원' } },
plotOptions: { column: { borderRadius: 4, pointPadding: 0.1 } },
series: [{ name: '2026', data: [420, 310, 560, 280], colorByPoint: true }],
credits: { enabled: false }
}), [])
return <HighchartsReact highcharts={Highcharts} options={options} />
}
7. 반응형, 툴팁, 데이터 레이블
const options = {
chart: { type: 'line' },
title: { text: '모바일 대응' },
tooltip: {
shared: true,
formatter: function () {
if (this.points) {
const header = `<b>${this.x}</b>`;
const lines = this.points.map(p => `${p.series.name}: ${p.y}`)
return [header, ...lines].join('<br/>')
}
return `${this.x}: ${this.y}`
}
},
dataLabels: { enabled: false },
responsive: {
rules: [{
condition: { maxWidth: 480 },
chartOptions: {
legend: { enabled: false },
yAxis: { title: { text: '' } },
chart: { height: 220 }
}
}]
},
credits: { enabled: false }
}
8. 내보내기와 접근성 활성화
import Highcharts from 'highcharts'
import exporting from 'highcharts/modules/exporting'
import accessibility from 'highcharts/modules/accessibility'
exporting(Highcharts)
accessibility(Highcharts)
const options = {
exporting: { enabled: true }, // PNG, JPG, PDF, SVG
accessibility: { enabled: true },
credits: { enabled: false }
}
9. 다크 테마 적용
import Highcharts from 'highcharts'
import darkTheme from 'highcharts/themes/dark-unica'
darkTheme(Highcharts) // 앱 초기 구동 시 1회 적용
// 런타임 테마 토글은 setOptions로 색상을 재적용하는 방식이 안전합니다.
Highcharts.setOptions({
chart: { backgroundColor: 'transparent' },
title: { style: { color: '#fff' } },
xAxis: { labels: { style: { color: '#ddd' } } },
yAxis: { labels: { style: { color: '#ddd' } } }
})
10. Next.js에서 SSR 이슈 해결
Highcharts는 window에 의존하므로 SSR에서 에러가 납니다. 클라이언트 전용으로 동적 로드합니다.
'use client'
import React from 'react'
import dynamic from 'next/dynamic'
import Highcharts from 'highcharts'
const HighchartsReact = dynamic(() => import('highcharts-react-official'), { ssr: false })
export default function ChartInNext() {
const options = { title: { text: 'Next.js + Highcharts' }, series: [{ data: [1,2,3] }], credits: { enabled: false } }
return <HighchartsReact highcharts={Highcharts} options={options} />
}
11. 대용량 데이터 성능: Boost 모듈
import Highcharts from 'highcharts'
import boost from 'highcharts/modules/boost'
boost(Highcharts)
const options = {
series: [{ type: 'line', data: bigArray, boostThreshold: 5000 }],
plotOptions: { series: { turboThreshold: 0 } },
credits: { enabled: false }
}
12. API로 서버 데이터 연결
import React, { useEffect, useMemo, useState } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
export default function FetchChart() {
const [seriesData, setSeriesData] = useState([])
useEffect(() => {
let alive = true
fetch('/api/metrics')
.then(r => r.json())
.then(json => { if (alive) setSeriesData(json.points) })
.catch(console.error)
return () => { alive = false }
}, [])
const options = useMemo(() => ({
title: { text: 'API 지표' },
series: [{ name: 'metric', data: seriesData }],
credits: { enabled: false }
}), [seriesData])
return <HighchartsReact highcharts={Highcharts} options={options} />
}
13. 체크리스트: 실무 팁
- 옵션/데이터는 useMemo로 고정합니다.
- 고빈도 업데이트는 allowChartUpdate=false + chart API 사용을 고려합니다.
- 툴팁 formatter, 데이터 라벨 등은 function() { ... }로 작성합니다.
- Boost 모듈로 5k+ 포인트를 처리합니다.
- Next.js는 dynamic import로 SSR을 비활성화합니다.
- 차트 컨테이너가 display:none이면 크기 계산 실패하니, 탭 전환 시 reflow 처리를 합니다.
- credits는 비활성화하여 UI를 정돈합니다.
14. 자주 겪는 오류
- ReferenceError: window is not defined → SSR 비활성화 필요.
- 차트가 계속 리렌더 → options/series 참조가 매번 새로 생성됨. useMemo로 해결.
- 툴팁에서 this가 undefined → formatter 화살표 함수 사용 지양.
- 빈 컨테이너 높이 0 → 부모 요소에 명시적 height 또는 차트 height 설정.
Highcharts는 옵션만 알면 바로 실전에 투입할 수 있습니다. 위 스니펫을 베이스로 라인업을 만들고, 모듈(Exporting, Accessibility, Boost)을 필요할 때 켠다는 전략이 가장 빠릅니다.
'React' 카테고리의 다른 글
| React에서 Progressive Image Loading 구현하기 (0) | 2026.05.11 |
|---|---|
| React 앱에서 애니메이션을 위해 Framer Motion 활용하기 (0) | 2026.05.11 |
| React 컴포넌트를 Storybook에서 문서화하고 테스트하기 (1) | 2026.05.08 |
| React 앱에서 데이터 페칭 시 Skeleton UI 구현하기 (0) | 2026.05.07 |
| React에서 서버 사이드 렌더링(SSR)과 클라이언트 사이드 렌더링(CSR) 차이 분석 (0) | 2026.05.07 |