! 제품 버전을 정확하게 입력해 주세요.
제품 버전이 정확하게 기재되어 있지 않은 경우,
최신 버전을 기준으로 안내 드리므로
더욱 빠르고 명확한 안내를 위해
제품 버전을 정확하게 입력해 주세요!

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유 > 블로그 & Tips

본문 바로가기

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유

페이지 정보

작성자 GrapeCity 작성일 2021-11-29 11:59 조회 3,630회 댓글 0건

본문

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유


대부분의 프론트엔드 개발자는 데이터 기반 애플리케이션 프로젝트를 새로 시작하는 시나리오에 익숙합니다. 누구나 디자인은 최대한 단순하고 직관적이어야 한다고 생각합니다. 대표적인 예로 두세 개의 열과 행으로 구성된 간단한 표를 들 수 있습니다. 하지만 간단한 표만으로 충분하지 않다는 것은 분명합니다. 관련자에게는 페이징 및 필터링과 같은 더 많은 요구 사항이 있습니다. 디자이너는 사용자 맞춤형 설정과 사용자 정의 가능성을 요구합니다. 이때 개발자는 기존 데이터 그리드 형태의 지원을 모색해야 합니다.

이 블로그에서는 데이터 그리드를 React 애플리케이션에 통합하는 방법을 알아보고 파일 내보내기에서 API 및 데이터베이스와의 연결에 이르기까지 데이터를 그리드에 통합하는 것에 대한 몇 가지 모범 사례를 살펴보겠습니다.


데이터 그리드 특징


데이터 그리드와 데이터 표 비교

가장 기본적인 형태의 데이터 그리드는 데이터가 행과 열로 표시되는 표처럼 보일 수 있습니다. 하지만 스크롤과 같은 기본적인 기능부터 이미 차이점이 드러납니다. 표는 일반적으로 열 정의를 표시하는 상단 고정 메뉴 이상의 기능을 제공하지 않지만, 데이터 그리드는 훨씬 더 정교합니다. 동일한 패턴이 우선순위가 있는 열 정렬과 데이터 선택에 계속 적용됩니다. 이제 데이터 선택은 행이 아닌 셀 기반으로 이루어집니다.

많은 데이터 그리드에서 제공하는 중요한 또 다른 기능은 데이터 내보내기 기능입니다. 가장 단순한 사례에서 이 기능은 데이터를 클립보드에 복사하는 것과 같습니다. 그러나 일부 요구 사항에는 데이터를 CSV 문서 또는 Excel XLSX 파일로 내보내기 등이 포함될 수 있습니다.

일반적으로 데이터 그리드는 생산성을 높일 수 있는 Excel과 같은 표준 스프레드시트 애플리케이션과의 상호 운용성을 지원합니다. 데이터 그리드는 실시간 업데이트 및 백엔드 지원 협업 기술과 함께 번들로 제공되어 탁월한 데이터 조작 능력을 발휘합니다. Microsoft가 Power BI 도구와 같은 거의 모든 온라인 데이터 편집 도구에서 Excel 365 엔진을 사용하는 것은 우연이 아닙니다.

데이터 그리드를 표와 확실히 차별화하는 것으로 사용자 정의 셀 렌더링과 서식 기능을 들 수 있습니다. 여기서 특정 셀에 표시되는 기타 풍부한 시각화 또는 차트를 생각해볼 수 있습니다. 또 다른 예로 스파크라인과 같은 빠른 시각적 힌트를 들 수 있습니다.

마지막으로, 접근성 기능에 대한 수요가 크다는 점입니다. 데이터 그리드는 기본 스프레드시트 애플리케이션의 기능에 근접하거나 능가하는 셀 강조 표시, 터치 지원, 오버레이 아이콘, 키보드 탐색을 지원합니다.

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유


React에서 데이터 그리드 구현

React 에코시스템에는 다수의 실행 데이터 그리드 컴포넌트가 포함되어 있습니다. 이 컴포넌트를 이용해 몇 줄의 코드로 미리 패키지된 모든 기능에 액세스할 수 있습니다. 사용 가능한 솔루션에 관해 알아보기 전에 처음부터 적절한 데이터 그리드를 구현하는 방법을 살펴보겠습니다.

모든 데이터 그리드는 중심에 표가 있으므로 표부터 살펴보겠습니다. React에는 다음과 같이 표를 디자인하는 두 가지 기본적인 방식이 있습니다.

  1. 일반적인 HTML 추상화 계층을 따라 하위 요소 TableHeader, TableFooter, TableRow, TableCell을 사용해 TableContainer 같은 컴포넌트 생성

  2. 대상 렌더링 조정을 위해 렌더링 속성과 기타 특수 속성을 사용하는 단일 표 컴포넌트 보유

첫 번째 옵션은 단순하면서도 일관된 스타일의 표를 만드는 탁월한 접근 방식이지만, 렌더링 속성이 포함된 표 컴포넌트인 두 번째 옵션은 수많은 표현 로직을 추상화 계층으로 전환하여 훨씬 더 많은 작업을 수행할 수 있습니다. 따라서 이것이 기존 솔루션에서 일반적으로 선택하는 방법입니다.

아래와 같이 오류 처리 및 기타 흥미로운 기능 없이 첫 번째 접근 방식을 간단히 구현한 사례를 살펴보겠습니다.

import * as React from "react";
​
const TableContainer = ({ striped, children }) => (
<table className={striped ? "table-striped" : ""}>{children}</table>
);
​
const TableHeader = ({ children }) => <thead>{children}</thead>;
​
const TableBody = ({ children }) => <tbody>{children}</tbody>;
​
const TableRow = ({ children }) => <tr>{children}</tr>;
​
const TableCell = ({ children }) => <td>{children}</td>;
​
const MyTable = () => (
<TableContainer striped>
  <TableHeader>
    <TableRow>
      <TableCell>ID</TableCell>
      <TableCell>Name</TableCell>
      <TableCell>Age</TableCell>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>1</TableCell>
      <TableCell>Foo</TableCell>
      <TableCell>21</TableCell>
    </TableRow>
    <TableRow>
      <TableCell>2</TableCell>
      <TableCell>Bar</TableCell>
      <TableCell>29</TableCell>
    </TableRow>
  </TableBody>
</TableContainer>
);


요점은 TableContainer와 같은 개별 컴포넌트가 자체 속성을 통해 다른 모든 옵션을 노출할 수 있다는 것입니다. 따라서 MyTable 컴포넌트는 모호한 클래스 이름이나 이상한 속성을 사용하는 대신 자체 속성을 직접 사용할 수 있습니다.

아래와 같이 두 번째 접근 방식을 따르면 앞에서 본 예시와는 약간 달라집니다.

import * as React from "react";
​
const Table = ({ striped, columns, data, keyProp }) => (
<table className={striped ? "table-striped" : ""}>
  <thead>
    <tr>
      {columns.map((column) => (
        <th key={column.prop}>{column.label}</th>
      ))}
    </tr>
  </thead>
  <tbody>
    {data.map((row) => (
      <tr key={row[keyProp]}>
        {columns.map((column) => (
          <td key={column.prop}>{row[column.prop]}</td>
        ))}
      </tr>
    ))}
  </tbody>
</table>
);
​
const MyTable = () => (
<Table
  striped
  keyProp="id"
  columns={[
    { label: "ID", prop: "id" },
    { label: "Name", prop: "name" },
    { label: "Age", prop: "age" },
  ]}
  data={[
    { id: 1, name: "Foo", city: "", age: 21 },
    { id: 2, name: "Bar", city: "", age: 29 },
  ]}
/>
);


보시다시피 표 컴포넌트의 로직은 훨씬 더 추상화되어 있고 렌더링 비용도 더 많이 듭니다. 하지만 useMemo와 같은 기술을 사용해 부분을 캐싱하는 등의 방법으로 이러한 단점을 훌륭하게 해결하고 최적화할 수 있습니다.

이 접근 방식의 가장 큰 이점은 데이터 기반 측면입니다. 표를 완전히 직접 구성하는 대신 일부 데이터를 삽입하고 렌더링된 표를 다시 가져올 수 있습니다.

동일한 원리를 활용해 이 버전에서 전체 데이터 그리드 컴포넌트로 이동할 수 있습니다. 그러나 많은 UI 라이브러리를 사용할 수 있는 오늘날, 사내에서 자체 데이터 그리드를 개발하는 데 시간을 투자할 이유가 별로 없습니다.


까다로운 작업을 처리하는 데이터 그리드

여전히 HTML 표의 한계에 갇혀 있으면서도 표를 프로그래밍 방식으로 구성하는 데 시간을 낭비하는 대신 데이터 그리드 컨트롤을 통합하는 것이 최선의 선택입니다. 선택할 수 있는 탁월한 여러 오픈 소스는 다음과 같습니다.

  • React 가상화

  • React 데이터 그리드

  • React 테이블

오픈 소스 프로젝트의 경우와 마찬가지로 일반적으로 제작자의 특정 요구에 적합한 다른 많은 제품이 있습니다.

오픈 소스 옵션이 매력적인 반면, Wijmo와 같은 상업용 제품은 React 데이터 그리드 컴포넌트에 확실한 이점을 제공합니다. Wijmo UI React 라이브러리에 포함된 FlexGrid는 React를 위한 최고의 플러그 앤 플레이 데이터 그리드입니다.

한 가지 장점은 데이터 그리드에 기본적으로 포함된 광범위한 기능 집합입니다. 지원과 지속적인 개발 약속이라는 장점도 있습니다.


기본 React 데이터 그리드 컨트롤 작동

먼저 시각적 힌트를 비롯한 일부 데이터를 나타내는 간단한 데이터 그리드 시각화를 살펴보겠습니다. 아래 표와 같이 익숙한 데이터 집합의 종류를 나타내는 임의 날짜와 개수 데이터를 몇 가지 사용하겠습니다.

 년

1월

2월 

3월 

4월 

5월 

6월 

 2016

 20

108 

45 

10 

105 

48 

 2017

 48

10 

78 

74 

 2018

 12

102 

10 

100 

 2019

 1

20 

40 

60 



React 데이터 그리드에서는 페이지 코드가 다음과 같이 표시됩니다.

import React from "react";
import ReactDataGrid from "react-data-grid";
import { Sparklines, SparklinesLine, SparklinesSpots } from "react-sparklines";
​
const Sparkline = ({ row }) => (
<Sparklines
  data={[row.jan, row.feb, row.mar, row.apr, row.may, row.jun]}
  margin={6}
  height={40}
  width={200}
>
  <SparklinesLine
    style={{ strokeWidth: 3, stroke: "#336aff", fill: "none" }}
  />
  <SparklinesSpots
    size={4}
    style={{ stroke: "#336aff", strokeWidth: 3, fill: "white" }}
  />
</Sparklines>
);
​
const columns = [
{ key: "year", name: "Year" },
{ key: "jan", name: "January" },
{ key: "feb", name: "February" },
{ key: "mar", name: "March" },
{ key: "apr", name: "April" },
{ key: "may", name: "May" },
{ key: "jun", name: "June" },
{ name: "Info", formatter: Sparkline },
];
​
const rows = [
{ year: 2016, jan: 20, feb: 108, mar: 45, apr: 10, may: 105, jun: 48 },
{ year: 2017, jan: 48, feb: 10, mar: 0, apr: 0, may: 78, jun: 74 },
{ year: 2018, jan: 12, feb: 102, mar: 10, apr: 0, may: 0, jun: 100 },
{ year: 2019, jan: 1, feb: 20, mar: 3, apr: 40, may: 5, jun: 60 },
];
​
export default function ReactDataGridPage() {
return (
  <ReactDataGrid
    columns={columns}
    rowGetter={(i) => rows[i]}
    rowsCount={rows.length}
  />
);
}


차트와 기타 그래픽을 표시하려면 타사 라이브러리를 사용해야 합니다. 위와 같은 경우 스파크라인을 보여드리기 위해 React 스파크라인을 설치했습니다. 열은 개체를 사용하여 정의됩니다. 스파크라인의 경우 지원 필드가 없는 사용자 정의 포맷터로 돌아갑니다.

결과 그리드의 모양은 다음과 같습니다.

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유


고급 React 데이터 그리드 만들기

이제 FlexGrid를 이용해 동일한 데이터를 표시해 보겠습니다. 코드 양은 동일하지만 보기가 더 좋고 데이터를 더 유연하게 표시할 수 있습니다.

이제 페이지 코드는 다음과 같이 표시됩니다.

import "@grapecity/wijmo.styles/wijmo.css";
import React from "react";
import { CollectionView } from "@grapecity/wijmo";
import { FlexGrid, FlexGridColumn } from "@grapecity/wijmo.react.grid";
import { CellMaker, SparklineMarkers } from "@grapecity/wijmo.grid.cellmaker";
import { SortDescription } from "@grapecity/wijmo";
​
const data = [
{ year: 2016, jan: 20, feb: 108, mar: 45, apr: 10, may: 105, jun: 48 },
{ year: 2017, jan: 48, feb: 10, mar: 0, apr: 0, may: 78, jun: 74 },
{ year: 2018, jan: 12, feb: 102, mar: 10, apr: 0, may: 0, jun: 100 },
{ year: 2019, jan: 1, feb: 20, mar: 3, apr: 40, may: 5, jun: 60 },
];
​
export default function WijmoPage() {
const [view] = React.useState(() => {
  const view = new CollectionView(
    data.map((item) => ({
      ...item,
      info: [item.jan, item.feb, item.mar, item.apr, item.may, item.jun],
    }))
  );
  return view;
});
​
const [infoCellTemplate] = React.useState(() =>
  CellMaker.makeSparkline({
    markers: SparklineMarkers.High | SparklineMarkers.Low,
    maxPoints: 25,
    label: "Info",
  })
);
​
return (
  <FlexGrid itemsSource={view}>
    <FlexGridColumn header="Year" binding="year" width="*" />
    <FlexGridColumn header="January" binding="jan" width="*" />
    <FlexGridColumn header="February" binding="feb" width="*" />
    <FlexGridColumn header="March" binding="mar" width="*" />
    <FlexGridColumn header="April" binding="apr" width="*" />
    <FlexGridColumn header="May" binding="may" width="*" />
    <FlexGridColumn header="June" binding="jun" width="*" />
    <FlexGridColumn
      header="Info"
      binding="info"
      align="center"
      width={180}
      allowSorting={false}
      cellTemplate={infoCellTemplate}
    />
  </FlexGrid>
);
}


가장 두드러진 점은 Wijmo 데이터 그리드가 React에서 선언적으로 열을 정의한다는 것입니다. 스파크라인 셀의 경우, 여기서는 Wijmo의 CellMaker Sparkline 컨트롤을 사용하여 "Info" 열의 각 셀에 스파크라인을 삽입합니다. useState를 사용해 데이터를 캐시하고 비용이 많이 드는 계산 과정 없이도 다시 렌더링하는 시점 간에 데이터를 실시간으로 유지할 수 있습니다.

여기서 기본 결과는 실제 스프레드시트 애플리케이션과 유사하게 표시됩니다.

React 데이터 그리드와 데이터 표 간의 차이점과 React 데이터 그리드 및 데이터 표가 필요한 이유

데이터 그리드는 일반적으로 애플리케이션에서 가장 큰 컴포넌트이므로 지연 로드하는 것이 좋습니다. 단일 페이지에서 데이터 그리드만 사용하는 경우 이 특정 페이지를 지연 로드하여 복잡한 작업이 발생하지 않도록 하는 것으로 충분합니다.

import * as React from "react";
import { Switch, Route } from "react-router-dom";
​
const PageWithDatagrid = React.lazy(() => import("./pages/DatagridPage"));
​
export const Routes = () => (
<Switch>
  {/* ... */}
  <Route path="/datagrid" component={PageWithDatagrid} />
</Switch>
);


유일한 요구 사항은 지연 로드된 모듈에 적절한 기본 내보내기 기능이 있어야 한다는 것입니다.

export default function PageWithDatagrid() {
return /* ... */;
}


데이터 그리드 컴포넌트와 같은 고유한 종속 항목은 모두 사이드 번들에 포함되어야 합니다. 이 사이드 번들은 시작 성능에 상당한 영향을 미칩니다.


데이터 로드 모범 사례

위의 예에서 저는 하드 코딩된 데이터만 몇 개 로드했습니다. 실제 상황에서는 파일, 데이터베이스, API와 같은 외부 소스에서 동적 데이터를 가져오는 경우가 대부분일 것입니다.

일반적으로 데이터 로드는 거의 백엔드 주제로 간주되지만 논의해야 할 몇 가지 프론트엔드 고려 사항이 있습니다. 가장 중요한 것은 데이터를 무제한으로 제공하는 API가 있을 경우 문제가 될 수 있다는 점입니다. 한 가지 흔한 문제는 전체 데이터 집합 렌더링이 매우 느리거나 청크로만 발생하여 일부 데이터가 사용되지 않은 상태로 남는 것입니다.

위와 같은 문제를 피하기 위해 일부 API에서는 페이징을 허용합니다. 가장 단순한 형태는 페이지 번호를 API로 전달하면 API가 데이터 집합에서 오프셋을 계산하는 것입니다. 신뢰할 수 있는 페이지 매김과 유연성 극대화를 위해 페이지 매김 메커니즘에서는 마지막으로 내보낸 데이터 항목의 표식인 포인터를 사용해야 합니다.

페이지가 매겨진 API를 Wijmo 데이터 그리드에 포함하려면 CollectionView 인스턴스를 사용하세요. API가 OData를 지원하는 경우 이 작업에 ODataCollectionView를 사용하면 됩니다.

예를 들어 다음 뷰에서는 페이지당 6개의 항목을 제공합니다.

const view = new ODataCollectionView(url, 'Customers', {
  pageSize: 6,
  pageOnServer: true,
  sortOnServer: true,
});


일반적으로 CollectionView는 비동기식 데이터 로드에도 사용할 수 있습니다.

const [view, setView] = React.useState(() => new CollectionView());
​
React.useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
  .then(res => res.json())
  .then(posts => setView(view => {
    view.sourceCollection = data;
    return view;
  }));
}, []);
​
// render datagrid


위 코드는 완전하지 않으므로, 처리자를 사용해 비동기식 작업을 적절히 제거해야 합니다. 개선된 버전의 useEffect는 다음과 같습니다.

React.useEffect(() => { 
const controller = new AbortController();
const { signal } = controller;

fetch('https://jsonplaceholder.typicode.com/posts', { signal })
  .then(res => res.json())
  .then(/* ... */);

return () => controller.abort();
}, []);

API를 직접 호출하는 것 외에 CORS(Cross-Origin Resource Sharing)에 관심을 갖고 계실 수 있습니다. CORS는 브라우저의 보안 메커니즘으로, 현재 도메인이 아닌 다른 도메인에 대한 요청을 수행하는 데 영향을 미칩니다.

실행 전 요청을 비롯한 암시적 CORS 요청 및 반응 패턴 외에 매우 중요한 한 가지 측면은 쿠키 등을 사용한 자격 증명의 제공입니다. 기본적으로 자격 증명은 동일한 원본 요청으로만 전송됩니다.

다음 코드에서는 다른 서비스가 실행 전(OPTIONS) 요청에 올바르게 응답한 경우 자격 증명을 해당 서비스에도 제공합니다.

fetch('https://jsonplaceholder.typicode.com/posts', { credentials: 'include' })


지금까지는 컴포넌트 마운트 시 데이터 호출이 수행되었습니다. 이러한 방법이 이상적인 것은 아닙니다. 항상 데이터를 기다려야 할 뿐만 아니라 취소 및 기타 플로우를 구현하는 것이 더 어렵습니다.

사용자가 원하는 것은 쉽게 그리고 특정 컴포넌트의 라이프사이클과 별개로 액세스하고 변경할 수 있는 글로벌 데이터 상태입니다. Redux와 같은 상태 컨테이너 솔루션을 가장 많이 선택하고 있지만, 더 간단한 방법도 있습니다.

한 가지 방법을 제시하자면 Zustand(독일어로 "상태"를 뜻함) 사용이 있습니다. 전역적으로 정의된 상태 개체에 대한 조작으로 모든 데이터 관련 활동을 모델링할 수 있습니다. 이 개체의 변경 사항은 React 후크를 통해 보고됩니다.

// state.js
import create from 'zustand';
​
const [useStore] = create(set => ({
data: undefined,
load: () =>
  fetch('https://jsonplaceholder.typicode.com/posts')
    .then(res => res.json())
    .then(posts => set({ data: posts })),
}));
​
export { useStore };
​
// datagrid.js
import { useStore } from './state';
// ...
​
export default function MyDataGridPage() {
const data = useStore(state => state.data);
const load = useStore(state => state.load);
const view = new CollectionView(data);
​
React.useEffect(() => {
  if (!data) {
    load();
  }
}, [data]);
​
return (
  <FlexGrid itemsSource={view} />
);
}


다음 단계:

데이터 그리드는 모든 종류의 애플리케이션에서 데이터를 표시하고 구성할 뿐 아니라 편집까지 할 수 있는 유연한 도구로 큰 인기를 누리게 되었습니다. FlexGrid를 사용하면 Angular, React, Vue 데이터 그리드를 5분 내에 쉽고 빠르게 구성할 수 있습니다.

Wijmo의 React 데이터 그리드에 대한 자세한 내용은 아래 링크를 확인하세요.

  1. Wijmo React 문서

  2. Wijmo React 데모




지금 바로 Wijmo를 다운로드하여 직접 테스트해보세요!

wj.png

  • 페이스북으로 공유
  • 트위터로  공유
  • 링크 복사
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그1

인기글

더보기
  • 인기 게시물이 없습니다.
메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@mescius.com | 전화 : 1670-0583 | 경기도 과천시 과천대로 7길 33, 디테크타워 B동 1107호 메시어스(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 ⓒ 2024 MESCIUS inc. All rights reserved.