DataGrid
DataGrid - 운영 모니터링
읽기 전용 운영 테이블에서 상태 가시성과 수치 컬럼 가독성을 높이는 패턴입니다.
reopt designUpdated
1. 라이브 예제
상태 배지 + 정렬된 수치 컬럼 중심의 운영 모니터링 뷰. 읽기 전용으로 빠르게 탐색합니다.
Last commit: -
Member 1
Seoul
Blocked
30
Member 2
Tokyo
Active
43
Member 3
Singapore
Active
56
Member 4
Berlin
Active
69
Member 5
Seoul
Active
82
Member 6
Tokyo
Blocked
95
Member 7
Singapore
Active
108
Member 8
Berlin
Active
121
Member 9
Seoul
Active
134
Member 10
Tokyo
Active
147
Member 11
Singapore
Blocked
160
Member 12
Berlin
Active
173
Member 13
Seoul
Active
186
Member 14
Tokyo
Active
199
Member 15
Singapore
Active
212
Member 16
Berlin
Blocked
225
Member 17
Seoul
Active
238
Member 18
Tokyo
Active
251
Member 19
Singapore
Active
264
Member 20
Berlin
Active
277
2. 설계 포인트
- 운영 화면은 기본적으로 읽기 전용(`editable: false`)으로 유지합니다.
- 상태 컬럼은 `renderCell`로 배지를 적용해 스캔 속도를 높입니다.
- 지표 컬럼은 `align: "right"`를 사용해 숫자 비교를 쉽게 만듭니다.
3. 실시간 뷰포트 연동 패턴
운영 화면에서는 헤더 메뉴 액션과 뷰포트 이벤트를 정렬/지연 로딩 로직과 연결하는 패턴이 중요합니다.
tsx
import * as React from "react";
import { DataGrid, type DataGridColumn } from "@reopt-ai/opt-datagrid";
interface OpsRow {
id: number;
service: string;
latencyMs: number;
}
const columns: DataGridColumn<OpsRow>[] = [
{ id: "service", title: "Service", getValue: (row) => row.service },
{
id: "latency",
title: "Latency (ms)",
align: "right",
getValue: (row) => String(row.latencyMs),
},
];
function OpsGrid() {
const [sort, setSort] = React.useState<"sort-asc" | "sort-desc" | null>(null);
const [windowInfo, setWindowInfo] = React.useState("r0-r0");
const rows = React.useMemo<OpsRow[]>(
() => [
{ id: 1, service: "API", latencyMs: 34 },
{ id: 2, service: "Worker", latencyMs: 81 },
{ id: 3, service: "Billing", latencyMs: 52 },
],
[],
);
const sortedRows = React.useMemo(() => {
if (!sort) return rows;
return [...rows].sort((a, b) =>
sort === "sort-asc" ? a.latencyMs - b.latencyMs : b.latencyMs - a.latencyMs,
);
}, [rows, sort]);
return (
<section>
<p>Visible window: {windowInfo}</p>
<DataGrid
rows={sortedRows}
columns={columns}
onHeaderMenuAction={(colIndex, action) => {
if (colIndex === 1) {
setSort(action === "clear-sort" ? null : action);
}
}}
onVisibleRegionChanged={(region) => {
setWindowInfo(`r${region.startRow + 1}-r${region.endRow}`);
}}
/>
</section>
);
}4. 코드 예제
tsx
import { DataGrid, type DataGridColumn } from "@reopt-ai/opt-datagrid";
interface ServiceRow {
id: number;
service: string;
region: string;
status: string;
latencyMs: number;
cpu: number;
}
const columns: DataGridColumn<ServiceRow>[] = [
{ id: "service", title: "Service", width: 220, editable: false, getValue: (row) => row.service },
{ id: "region", title: "Region", width: 140, editable: false, getValue: (row) => row.region },
{
id: "status",
title: "Status",
width: 120,
editable: false,
getValue: (row) => row.status,
renderCell: ({ value }) => (
<span className={value === "Active" ? "badge-green" : "badge-red"}>{value}</span>
),
},
{ id: "latency", title: "Latency (ms)", width: 140, align: "right", editable: false, getValue: (row) => String(row.latencyMs) },
{ id: "cpu", title: "CPU (%)", width: 120, align: "right", editable: false, getValue: (row) => String(row.cpu) },
];