35종 차트 타입과 줌·드릴다운·주석 그리기·차트 동기화를 헤드리스 코어(ChartCore)에서 처리하는 멀티 프레임워크 차트 라이브러리입니다. React, Vue 3, Vue 2.7, Svelte 5, 순수 JS CDN을 지원하며 약 250KB로 가볍습니다.
35종 차트 타입을 React·Vue·Svelte·순수 JS 어디서든 똑같이 그리는, 헤드리스 차트 라이브러리.
moda-chart는 스케일 계산·인터랙션·이벤트 등 모든 로직을 순수 TypeScript 코어(ChartCore)에 두고, 각 프레임워크 어댑터는 얇은 반응형 바인딩만 담당합니다. 모든 렌더러가 같은 DOM 계약(.mc-*)을 만들어 결과가 항상 같습니다.
줌/네비게이터/드릴다운/주석 그리기/차트 동기화처럼 상용 차트에서 유료인 기능을 포함하고, 내장 세계 지도·스파크라인까지 — 번들 약 250KB로 가볍습니다.
CDN에서 불러온 실제 코어로 동작합니다. 라인·막대·파이부터 캔들스틱· 생키·선버스트·세계 지도까지 전 차트 타입을 전환해 볼 수 있고, 범례·툴팁·줌·브러시·네비게이터·포인트 선택·우클릭 메뉴·드릴다운· 주석 그리기(추세선/피보나치/구간 측정)를 직접 써볼 수 있습니다. 아래 패널에는 지금 설정을 재현하는 코드가 실시간으로 표시됩니다.
| 사용 환경 | 패키지 | 비고 |
|---|---|---|
| React | @moda-chart/react | ChartView 컴포넌트 + useChartCore 훅 (useSyncExternalStore) |
| Vue 3 | @moda-chart/vue | useChart + ChartView, shallowRef 기반 반응형 |
| Vue 2.7 | @moda-chart/vue2 | Vue 3과 동일한 Composition API 사용법 |
| Svelte 5 | @moda-chart/svelte | readable 스토어 연동 + ChartView |
| 순수 JS / CDN | moda-chart.js | 빌드 도구 없이 <script> 한 줄, window.ModaChart |
| 프레임워크 없음 | @moda-chart/core | 헤드리스 코어 ChartCore + mountChart 직접 사용 |
npm i @moda-chart/react # Reactnpm i @moda-chart/vue # Vue 3npm i @moda-chart/vue2 # Vue 2.7npm i @moda-chart/svelte # Svelte 5npm i @moda-chart/core # 헤드리스 코어만https://chart.modaolive.com/moda-chart.jshttps://chart.modaolive.com/style.cssnpm i @moda-chart/react처럼 어댑터를 설치하거나, CDN <script> 한 줄로 코어를 로드합니다.
type과 series·categories만 넘기면 됩니다. points·ohlc·tree·links처럼 타입별 데이터 필드는 필요할 때 추가합니다.
어댑터는 <ChartView> 하나면 끝. vanilla는 mountChart(el, options)가 DOM과 인터랙션을 전부 배선합니다.
// npm i @moda-chart/react
import { ChartView, useChartCore } from "@moda-chart/react";
import "@moda-chart/react/styles.css";
function App() {
const { chart, snapshot } = useChartCore({
type: "line",
series: [
{ name: "매출", values: [12, 24, 16, 30] },
{ name: "비용", values: [8, 14, 12, 20] },
],
categories: ["1월", "2월", "3월", "4월"],
legend: { position: "top" },
tooltip: { mode: "shared" },
zoom: true,
});
return <ChartView chart={chart} />;
}
// 이후 변경은 chart.setData / chart.setType 같은 코어 메서드로| 기능 | 켜는 법 | API |
|---|---|---|
| 직교 차트 | type: "line"|"step"|"spline"|"area"|"bar"|"stacked-bar"|"percent-stacked-bar"|"waterfall"|"histogram"|"range-bar"|"range-area"|"population-pyramid" | chart.setType(type) 런타임 전환 |
| 원형·극좌표 | "pie"|"donut"|"nightingale"|"radial-bar"|"radial-column"|"radar"|"radar-area" | categories = 각도, values = 반지름 |
| 분포·재무 | "scatter"|"bubble"|"heatmap"|"candlestick"|"ohlc"|"boxplot" | points {x,y,z} / ohlc / box / 시리즈 행렬 |
| 흐름·계층 | "funnel"|"cone-funnel"|"pyramid"|"sankey"|"chord"|"sunburst"|"treemap"|"organization"|"wordcloud" | series.tree / links / chord.matrix |
| 게이지·지도 | "gauge"|"linear-gauge"|"pictogram"|"map" | gauge:{min,max,target} / map:{topology} + 내장 WORLD_TOPOLOGY |
| 시리즈 혼합 | series[].type 개별 지정 | line + bar 콤보 차트 |
| 수평 방향 | direction: "horizontal" (bar 계열) | 값 축이 x축으로 전환 |
| 기능 | 켜는 법 | API |
|---|---|---|
| 카테고리 축 | categories: string[] / number[] / Date[] | string=band, number=linear, Date=time 자동 |
| 데이터 교체 | — | chart.setData(series, categories) |
| 포인트 갱신 | — | chart.updatePoint(...) — 게이지 등 실시간 갱신 |
| 포인트별 스타일 | series[].itemStyle: (ctx) => ({color?, name?}) | AG Charts itemStyler 해당 |
| 에러바·추세선 | series[].errors / series[].trend | trend: { type: "linear"|"movingAverage" } |
| 그룹 카테고리 | categories: [[그룹, 리프], …] 튜플 | 두 번째 틱 행 렌더 |
| 기능 | 켜는 법 | API |
|---|---|---|
| 범례 | legend: true | { position } | 클릭 토글 + hover dimming / toggleLegend / hoverLegend |
| 범례 체크박스 | legend: { checkboxes: true } | legendCheck 이벤트 { id, checked } |
| 툴팁 | tooltip: "point"|"shared"|{ mode, format, render } | shared는 크로스헤어 포함, render로 HTML 커스텀 |
| 줌·팬 | zoom: true | { wheel, pan, axes, select } | setZoomWindow / resetZoom — x/y/xy 축 선택 |
| 브러시 선택 | brush: true — 드래그 범위 선택 | selectionChange 이벤트 / setSelection |
| 네비게이터·스크롤바 | navigator: true | scrollbar: true | 미니맵 또는 얇은 줌 스트립으로 창 제어 |
| 드릴다운 | drilldown: { "라벨": 하위레벨 } | drillDown/drillUp/drillUpAll + ‹Back 버튼 |
| 포인트 선택 | allowPointSelect: true | selectPoint / clearSelected, .mc-selected |
| 컨텍스트 메뉴 | contextMenu: true | { items } | 내장 줌리셋/SVG·PNG 내보내기 + 커스텀 항목 menuAction |
| 차트 동기화 | sync: "그룹키" | 같은 키 차트끼리 hover·줌 공유 |
| 터치 핀치 줌 | 자동 (zoom 활성 시) | 두 손가락 간격으로 중점 앵커 줌 |
| 기능 | 켜는 법 | API |
|---|---|---|
| 주석 그리기 | drawing: true + chart.setDrawMode(tool) | line/hline/vline/rect/channel/fibonacci/measure + getDrawings |
| SVG·PNG 저장 | contextMenu 내장 또는 직접 호출 | downloadSVG / downloadPNG export |
| 스파크라인 | — | mountSparkline — 축 없는 미니 차트 |
| 상태 저장·복원 | — | getState / setState — 줌·숨김·주석 왕복 |
| 키보드 탐색 | 자동 — 포인트 포커스 이동 | aria-pressed 등 접근성 속성 포함 |
| 테마 | --chart-* CSS 변수 + 팔레트 순환 | .mc-* 클래스 DOM 계약으로 커스텀 |
| 인쇄 이벤트 | 자동 | beforePrint / afterPrint 이벤트 |
포인트 클릭으로 하위 레벨 데이터로 내려가기 — ‹Back 버튼 자동 제공
new ChartCore({
type: "bar",
series: [{ name: "월별", values: [12, 24, 16] }],
categories: ["1월", "2월", "3월"],
drilldown: {
"1월": {
series: [{ name: "1월 주별", values: [3, 4, 2, 3] }],
categories: ["1주", "2주", "3주", "4주"],
title: "1월 주별 매출",
},
},
});
chart.drillUp(); // 한 레벨 복귀추세선·피보나치 되돌림·구간 측정까지 — AG Charts 유료급 기능
chart.setDrawMode("fibonacci"); // 드래그 → 0~100% 되돌림 레벨
chart.setDrawMode("channel"); // 평행 채널 + 음영 밴드
chart.setDrawMode("measure"); // Δx/Δy 자동 라벨
chart.getDrawings(); // DrawingInput[] (데이터 좌표)
chart.clearDrawings();
chart.setDrawMode(null); // 해제 (Esc도 가능)setData는 멱등 — 같은 참조 재호출은 무시되어 반응형 루프 안전
setInterval(() => {
series[0].values.push(rand()); series[0].values.shift();
chart.setData(series, categories); // 참조가 새 배열이면 리렌더
}, 1000);
// 게이지처럼 단일 포인트만 바꿀 때
chart.updatePoint(seriesId, 0, nextValue);같은 그룹키 차트끼리 hover·줌을 공유 — 대시보드 다중 차트용
mountChart(elA, { type: "line", series, categories, sync: "dash" });
mountChart(elB, { type: "bar", series, categories, sync: "dash" });
// 한쪽에서 줌/호버하면 다른 쪽에도 같은 도메인 기준으로 전파
// (전파된 변경은 다시 전파되지 않아 루프 없음)ohlc 데이터로 상승/하락 캔들 — 색은 --chart-up/down-color 변수
new ChartCore({
type: "candlestick",
categories: ["10/1", "10/2", "10/3"],
series: [{
name: "주가",
ohlc: [
[100, 108, 97, 105], // [open, high, low, close]
[105, 110, 101, 103],
[103, 112, 102, 111],
],
}],
});내장 Natural Earth 110m 지형 — 코드만으로 조인, 축 없는 지역 차트
import { WORLD_TOPOLOGY } from "@moda-chart/core"; // CDN은 window.ModaChart.WORLD_TOPOLOGY
new ChartCore({
type: "map",
series: [{
name: "국가별 사용자",
mapData: { KOR: 92, JPN: 64, USA: 88, DEU: 40 },
}],
map: { topology: WORLD_TOPOLOGY, projection: "mercator" },
});
// 조인 안 된 지역은 .mc-map-no-data, 우하단에 그라데이션 범례가이드 문서(차트 타입 전체 표, 인터랙션, 테마 변수, 마이그레이션 매핑)는 공개 릴리즈 레포에서 관리됩니다.
park-taejoon/moda-chart-releases