reopt designreopt design
DocsExploreToolsPricingBuilder
시작하기
시작하기
Playground
핵심 개념
핵심 개념
DataGrid
DataGrid 개요
편집형 데이터 입력
운영 모니터링
대규모 데이터
원격 연동 계약
마이그레이션 플레이북
앱 조합 가이드
컬럼 설계 플레이북
구축·운영
Skills
릴리즈 노트
레퍼런스
Hook 레퍼런스
타입 레퍼런스
Oopt-datagrid
reopt designreopt design

AI 시대를 위한 디자인 시스템

  • 문서
  • 가격
  • 릴리즈 노트
  • GitHub
  • 서비스 약관
  • 개인정보처리방침

© 2026 reopt-ai. All rights reserved.

핵심 개념
  1. 문서
  2. /
  3. 핵심 개념
  4. /
  5. 핵심 개념

핵심 개념

컬럼 정의, 셀 편집 파이프라인, 가상화 모델, 선택/클립보드 아키텍처

reopt design · 업데이트 2026년 6월 26일

시작하기핵심 개념개요편집형 데이터 입력운영 모니터링대규모 데이터원격 연동 계약마이그레이션 플레이북앱 조합 가이드컬럼 설계 플레이북Skills릴리즈 노트Hook 레퍼런스타입 레퍼런스

1. 컬럼 정의

DataGridColumn<Row, Value>는 하나의 컬럼을 정의하는 핵심 인터페이스입니다. 표시, 편집, 레이아웃을 모두 이 객체 안에서 선언합니다.

속성필수설명
idO유니크 식별자. 정렬/클립보드/캐시에서 키로 사용
titleO헤더에 표시되는 텍스트
getValueO(row: Row) => Value — 셀 표시 값 추출
setValue편집 시(row: Row, value: Value) => Row — 불변 업데이트 반환
width / minWidth / maxWidth픽셀 단위 너비. 기본값 150px, 리사이즈 범위 제한
resizable드래그 리사이즈 허용 여부 (기본 true)
align"left" | "center" | "right"
group같은 group 값을 가진 컬럼끼리 헤더를 합침
tsx
const columns: DataGridColumn<Product>[] = [
  {
    id: "name",
    title: "상품명",
    getValue: (row) => row.name,
    width: 200,
    minWidth: 120,
    resizable: true,
  },
  {
    id: "price",
    title: "가격",
    getValue: (row) => row.price,
    align: "right",
    width: 100,
    group: "금액",
  },
  {
    id: "tax",
    title: "세금",
    getValue: (row) => row.price * 0.1,
    align: "right",
    width: 100,
    group: "금액",
  },
];

2. 셀 편집 파이프라인

사용자 입력이 최종 데이터에 반영되기까지 5단계 파이프라인을 거칩니다. 각 단계에서 변환, 검증, 거부가 가능합니다.

text
User Input
  → parseInput(raw)          // 문자열 → 타입 변환 (예: "42" → 42)
  → validateValue(parsed)    // 유효성 검증, 에러 메시지 반환
  → setValue(row, validated)  // 불변 Row 업데이트 반환
  → onCellsEdited(changes)   // 배치 편집 인터셉트 (paste/delete 포함)
  → onRowsChange(newRows)    // 최종 상태 업데이트

빌트인 에디터 종류

kind용도주요 옵션
text단일 행 텍스트maxLength, placeholder
textarea여러 줄 텍스트rows, maxLength
number숫자 입력min, max, step, decimals
select드롭다운 선택options, allowEmpty
checkbox불리언 토글indeterminate
date날짜 선택format, minDate, maxDate
async-combobox비동기 검색 + 선택loadOptions, debounceMs
custom커스텀 편집기 컴포넌트component, provideEditor
tsx
{
  id: "price",
  title: "가격",
  getValue: (row) => row.price,
  setValue: (row, value) => ({ ...row, price: value as number }),
  editable: true,
  editor: { kind: "number", min: 0, max: 999999, step: 100, decimals: 0 },
  // 문자열 입력을 숫자로 변환
  parseInput: (raw) => Number(raw.replace(/,/g, "")),
  // 음수 값 거부
  validateValue: (val) =>
    val < 0 ? { valid: false, message: "음수 불가" } : { valid: true },
}

3. 가상화 모델

DataGrid는 행(row)과 열(column) 모두 가상화하여 수만 행 이상의 데이터에서도 일정한 렌더링 성능을 유지합니다.

옵션기본값설명
rowBufferPx300뷰포트 위/아래에 미리 렌더링할 픽셀 버퍼. 스크롤 시 빈 영역 방지
columnOverscan2뷰포트 좌/우에 추가 렌더링할 컬럼 수
maxRenderedRows500한 번에 렌더링할 최대 행 수 상한. 비정상 스크롤 방지용
scrollUpdateModerafsync — 매 스크롤 이벤트마다 동기 업데이트. raf — requestAnimationFrame으로 배치 처리
valueCachefalsetrue 시 getValue 결과를 캐시. 스크롤/선택 중 재계산 방지
valueCacheStrategyrow-refrow-ref — 객체 레퍼런스로 invalidation. row-id — getRowId 기반 (sort/reorder에 안정적)
rendererRefreshModeautoauto — 값 변경 시 자동 리렌더. manual — 컬럼별 refreshCellRenderer 콜백으로 제어
tsx
<DataGrid
  columns={columns}
  rows={rows}
  height={600}
  getRowId={(row) => row.id}
  // 가상화 튜닝
  rowBufferPx={400}
  columnOverscan={3}
  maxRenderedRows={300}
  scrollUpdateMode="raf"
  // 값 캐시
  valueCache
  valueCacheStrategy="row-id"
/>

4. 선택 모델

DataGridSelection은 시작 셀(start)과 끝 셀(end)로 정의되는 직사각형 영역입니다. 행 선택과 컬럼 선택은 별도 모드로 제어합니다.

옵션값설명
rowSelectnone | single | multi행 선택 모드. multi에서 Shift+Click 범위 선택, Ctrl+Click 토글
columnSelectboolean헤더 클릭으로 전체 컬럼 선택 허용
rowMarkersnone | number | checkbox | both왼쪽 행 마커 표시 유형. checkbox는 multi-select 전용
tsx
const [selection, setSelection] = useState<DataGridSelection>();

<DataGrid
  columns={columns}
  rows={rows}
  height={400}
  rowSelect="multi"
  rowMarkers="checkbox"
  columnSelect
  selection={selection}
  onSelectionChange={setSelection}
/>

5. 클립보드

복사(Copy)와 붙여넣기(Paste)는 TSV(Tab-Separated Values) 형식을 기본으로 사용합니다. 스프레드시트 앱과의 호환이 자연스럽게 동작합니다.

- Copy: serializeValue(value) → 클립보드 TSV 텍스트

- Paste: 클립보드 TSV → deserializeValue(text) → validateValue → setValue

- Cross-column paste: coercePasteValue로 다른 타입의 컬럼에 붙여넣기 변환 가능

tsx
const columns: DataGridColumn<Row>[] = [
  {
    id: "status",
    title: "상태",
    getValue: (row) => row.status,
    setValue: (row, val) => ({ ...row, status: val as string }),
    editable: true,
    // 복사 시 한글 라벨로 직렬화
    serializeValue: (val) =>
      val === "active" ? "활성" : val === "paused" ? "일시정지" : "비활성",
    // 붙여넣기 시 역변환
    deserializeValue: (text) =>
      text === "활성" ? "active" : text === "일시정지" ? "paused" : "inactive",
  },
];

<DataGrid
  columns={columns}
  rows={rows}
  height={400}
  copyHeaders          // 복사 시 헤더 행 포함
  maxPasteCells={5000} // 붙여넣기 최대 셀 수 제한
  onCopy={(ctx) => {
    console.log("복사:", ctx.selection, ctx.cells);
  }}
  onPaste={(ctx) => {
    // false 반환 시 붙여넣기 취소
    if (ctx.cells.length > 1000) return false;
    return true;
  }}
/>

6. Row Identity

getRowId는 각 행의 안정적인 식별자를 반환합니다. 지정하지 않으면 배열 인덱스가 사용되지만, 정렬이나 필터링 시 캐시 무효화와 키 충돌이 발생합니다.

권장: 실무 프로젝트에서는 반드시 getRowId를 지정하세요. 정렬, Undo/Redo, Remote Sync, Value Cache 모두 getRowId에 의존합니다.

valueCacheStrategyinvalidation 기준적합한 경우
row-ref객체 레퍼런스 (===)정렬/필터 없이 배열 순서가 고정인 경우
row-idgetRowId 반환값정렬, 필터, 재정렬이 빈번한 경우 (권장)
tsx
// DB의 PK나 UUID를 안정적인 식별자로 사용
<DataGrid
  columns={columns}
  rows={rows}
  getRowId={(row) => row.uuid}
  valueCache
  valueCacheStrategy="row-id"
  height={400}
/>
Previous시작하기패키지 설치, .npmrc 설정, 첫 DataGrid 렌더링까지의 빠른 시작 가이드시작하기
시작하기 페이지로 이동
NextDataGrid 개요편집형, 운영 모니터링형, 대규모 데이터 시나리오로 나눈 DataGrid 실전 가이드DataGrid