reopt design
DocsExploreTemplatesCanvasToolsPricing
Login
Start
Overview
Start
Core Concepts
Core Concepts
Data model
Data model
Build & Operate
Production readiness
opt-charts · Charts
ChartContainer
ChartTooltip
ChartLegend
LineChart
BarChart
AreaChart
Sparkline
PieChart
ScatterChart
ComparisonChart
GaugeChart
FunnelChart
RetentionHeatmap
SankeyChart
PathFlowChart
CalendarHeatmap
WaterfallChart
BubbleChart
ComposedChart
RadarChart
RadialBarChart
Treemap
Histogram
BoxPlot
BulletChart
Heatmap
DataBar
GanttChart
Sunburst
CandlestickChart
TimeSeriesChart
TimeSeriesTooltip
LoadingChart
SmallMultiples
TraceWaterfall
VennDiagram
MetricsCard
TrendChart
EventSparkline
ReportWidget
Oopt-charts
reopt designreopt design

A design system for the AI era

  • Docs
  • Pricing
  • Releases
  • About
  • Contact
  • Terms of Service
  • Privacy Policy

reopt Inc.Business registration no. 217-88-02453contact@reopt.ai

© 2026 reopt Inc. All rights reserved.

Data model
  1. Docs
  2. /
  3. Data model
  4. /
  5. Data model

데이터 모델

차트를 고르기 전에 데이터 shape를 먼저 고정합니다. 공통 Cartesian 모델, 특수 차트 모델, formatter, empty state를 구현 기준으로 분류합니다.

reopt design · Updated Nov 1, 2026

개요시작하기핵심 개념데이터 모델슬라이드 예제Production readiness

1. 공통 Cartesian 모델

LineChart, BarChart, AreaChart는 같은 데이터 모델을 공유합니다. `dataKey`는 각 행의 numeric field를 가리키고, `name`은 tooltip과 legend에 표시되는 사람이 읽는 이름입니다.

ts
export interface ChartDataPoint {
  name: string;
  [key: string]: string | number;
}

export interface ChartSeriesDef {
  dataKey: string;
  name: string;
  color?: string;
  type?: "line" | "bar" | "area";
  stackId?: string;
}
tsx
const data = [
  { name: "Enterprise", won: 42, lost: 8, pipeline: 19 },
  { name: "Mid-market", won: 31, lost: 11, pipeline: 27 },
  { name: "SMB", won: 24, lost: 14, pipeline: 32 },
];

const series = [
  { dataKey: "won", name: "Won", color: "hsl(142, 71%, 45%)" },
  { dataKey: "lost", name: "Lost", color: "hsl(349, 89%, 60%)" },
  { dataKey: "pipeline", name: "Pipeline", color: "hsl(221, 83%, 53%)" },
] satisfies ChartSeriesDef[];

<BarChart
  data={data}
  series={series}
  stacked
  showLegend
  aria-label="세그먼트별 영업 상태"
/>;

2. 특수 차트 모델

분석형 차트는 의미가 다르므로 공통 타입으로 억지로 맞추지 않습니다. 데이터가 이미 아래 shape 중 하나라면 해당 컴포넌트를 바로 선택합니다.

ShapeComponents설계 메모
ChartDataPoint[] + ChartSeriesDef[]LineChart, BarChart, AreaChart, ComposedChart, ComparisonChart, TrendChartname이 기본 x축입니다. 시리즈의 dataKey는 숫자 필드를 가리키며 ComposedChart는 시리즈별 line/bar/area를 선택합니다.
PieChartDataPoint[] / RadialBarDataPoint[]PieChart, RadialBarChartname과 value로 구성비 또는 원형 진행률을 표현합니다. 진행률의 maxValue와 도넛 반경은 별도 옵션입니다.
ChartDataPoint[] + RadarSeriesDef[]RadarChartangleKey로 평가 항목을 지정하고 시리즈마다 숫자 값을 제공합니다.
ScatterSeriesDef[] / BubbleSeriesDef[]ScatterChart, BubbleChart시리즈별 숫자 좌표 배열을 가지며 xKey, yKey, zKey/sizeKey를 지정합니다.
number[] / BoxPlotDatum[]Histogram, BoxPlotHistogram은 values 표본과 bins를 받습니다. BoxPlot은 원시 values 또는 min ≤ q1 ≤ median ≤ q3 ≤ max와 outliers를 받습니다.
number[][] + xLabels / yLabelsHeatmap행과 열의 방향을 축 라벨에 맞춥니다. 크기는 sequential, 0 같은 기준점 대비 양극성은 diverging을 사용합니다.
RetentionRow[]RetentionHeatmapcohort와 (number | null)[] values입니다. 0은 관측값이며 null은 아직 관측되지 않은 기간입니다. 기본 값 범위는 0–100입니다.
CalendarHeatmapDatum[]CalendarHeatmapYYYY-MM-DD date와 count입니다. startDate/endDate로 포함할 날짜 범위를 고정합니다.
TreemapDataNode[] / SunburstNode[]Treemap, Sunburstname/value/children의 재귀 계층입니다. 두 차트 모두 루트 노드 배열을 받습니다.
VennSet[] + VennIntersection[]VennDiagram2–3개 집합과 교집합을 표현합니다. 교집합은 참조하는 집합의 크기를 넘을 수 없습니다.
SankeyNode[] + SankeyLink[]SankeyChart고유 node id와 source/target/value 링크입니다. 링크는 label이 아닌 id를 참조합니다. Deck 어댑터는 미등록 노드와 순환을 거부합니다.
PathFlowDataPathFlowChartsteps의 위치별 rows와 인접 단계 edges입니다. otherCount, dropOffCount, entryCount로 집계 밖 경로도 표현합니다.
FunnelDataPoint[]FunnelChartname/value/color 단계입니다. list·bars·horizontal·steps를 고르며 steps는 첫 단계 대비 크기와 이전 단계 대비 전환율을 구분합니다.
WaterfallDataPoint[]WaterfallChartvalue는 누적액에 더하는 증감입니다. isTotal은 현재 누적액을 다시 표시하며 자기 value를 더하지 않습니다. 시작 잔액은 일반 행으로 넣습니다.
TimeSeriesPoint[] + TimeSeriesDef[]TimeSeriesChartt는 epoch ms, ISO 문자열 또는 Date입니다. from/to, granularity, timeZone을 명시합니다. Deck JSON에는 Date 객체 대신 epoch ms 또는 ISO 문자열을 넣습니다.
SmallMultipleSeries[]SmallMultiples패널별 고유 id/name/data와 공통 dataKey를 사용합니다. sharedYAxis는 음수와 양수를 포함해 패널 간 척도를 맞춥니다.
GanttTask[] / TraceSpan[]GanttChart, TraceWaterfallGantt는 숫자 start/end 구간입니다. TraceSpan은 id/parentId/startMs와 endMs 또는 durationMs로 부모·자식 실행 구간을 표현합니다.
Candle[]CandlestickChartname/open/high/low/close입니다. low ≤ open·close ≤ high인 OHLC 행을 제공합니다.
value + range / BulletDatum[] / number[]GaugeChart, DataBar, BulletChart, SparklineGauge와 DataBar는 스칼라 값과 범위, BulletChart는 value/target/오름차순 ranges, Sparkline은 숫자 표본을 사용합니다.
MetricsCardProps / EventSparklineProps / ReportWidgetConfigMetricsCard, EventSparkline, ReportWidget지표·변화량·추세 표본 또는 type별 위젯 config입니다. ReportWidget은 9개 위젯 유형을 지원하며 35종 전체 슬라이드 선택기는 opt-deck 확장입니다.

3. Formatter와 설명 텍스트

opt-charts는 데이터 단위를 추측하지 않습니다. 통화, 퍼센트, retention period, cohort 이름은 소비자 앱에서 formatter로 주입합니다. 복잡한 차트는 시각적 label만으로 끝내지 말고 `aria-describedby`에 요약 문장을 연결합니다.

tsx
<LineChart
  data={data}
  series={series}
  aria-label="월별 매출"
  aria-describedby="revenue-chart-summary"
  tooltipOptions={{
    labelFormatter: (label) => `${label} 실적`,
    valueFormatter: (value, name) =>
      `${name}: ${Number(value).toLocaleString("ko-KR")}만원`,
  }}
  legendOptions={{
    formatter: (value) => <span className="font-medium">{value}</span>,
  }}
/>;

<p id="revenue-chart-summary" className="sr-only">
  1월부터 4월까지 매출과 비용이 모두 증가했고, 4월 매출이 가장 높습니다.
</p>

4. Empty state 정책

차트는 빈 데이터와 재조회 상태를 위한 공통 계약을 제공합니다. 첫 로딩, 기존 데이터 재조회, 빈 결과, API 오류를 구분하세요. API 오류 메시지와 재시도 동작은 데이터를 가져오는 패널에서 처리합니다.

컴포넌트현재 동작권장 처리
LineChart, BarChart, AreaChart, PieChart빈 데이터는 ChartEmptyState를 렌더링합니다. emptyState 또는 labels.empty로 내용을 바꿉니다.첫 로딩은 LoadingChart, 재조회는 이전 데이터와 loading을 함께 전달합니다.
FunnelChart, RetentionHeatmap, Heatmap빈 데이터에서도 ChartEmptyState를 보여줍니다. loading은 기존 데이터의 표시를 유지하며 aria-busy와 흐림 처리를 적용합니다.retention의 관측값 0과 미관측 null을 구분하고, API 오류의 재시도 UI는 부모 패널에서 제공합니다.
ReportWidget지표·게이지 외 유형의 빈 데이터는 labels.emptyChart, 지연 로딩은 labels.loadingChart로 안내합니다.보고서 카드의 제목과 크기를 유지하면서 제품 언어로 labels를 지정합니다.
tsx
import { AreaChart, LoadingChart } from "@reopt-ai/opt-charts";

// First load: reserve the plot's space. Refetch: keep the previous data visible.
function ChartPanel({ data, series, loading }: ChartPanelProps) {
  if (loading && data.length === 0) {
    return <LoadingChart variant="area" height={288} />;
  }
  return (
    <AreaChart
      data={data}
      series={series}
      height={288}
      loading={loading}
      labels={{ empty: "아직 표시할 데이터가 없습니다." }}
      aria-label="매출 추세"
    />
  );
}

5. 색상 할당

명시적 color가 최우선입니다. 기본 계열 색상은 seriesColor(index)가 테마의 --opt-chart-1부터 --opt-chart-16까지 할당하며 이후 계열은 CHART_CHROME.other 중립색을 사용합니다. 첫 색을 반복하지 않습니다. 범주 구분에는 categorical, 크기에는 sequential, 기준점 양쪽에는 diverging 도메인을 사용합니다. CHART_COLOR_PALETTE는 기존 5색 토큰 배열이며 기본 차트 전체를 5색으로 제한하는 계약이 아닙니다.

6. 슬라이드 데이터와 React props

React 컴포넌트에는 formatter와 클릭 콜백을 전달할 수 있습니다. opt-deck 확장에는 type/title/props 형식의 직렬화 가능한 JSON만 저장합니다. 함수, React 요소, Date 객체는 포함하지 않으며, 그래프 참조·행렬 크기·구간 순서 등은 유형별 파서로 검증합니다. 전체 설정 JSON 입력란에는 props만 붙여넣습니다.

행렬·Sankey·Waterfall 슬라이드 예제 보기
PreviousCore Conceptsopt-charts의 visuals와 shells 책임, ChartContainer, Recharts 접근성 계층, token 기반 색상 흐름Core Concepts
Go to Core Concepts
NextProduction readinessopt-charts 배포 전 responsive sizing, accessibility, data validation, performance, install smoke 체크리스트Build & Operate