회사 프로젝트 진행 중에 supabase의 데이터들을 테이블 형식 그대로 화면에 띄워야 했다. 입사 전에는 노가다(...)로 만드는 것만 해 봤기 때문에 grid로 일단 만들까요? 라고 질문했다가 '이거 한번 보고 마음을 바꿔 봐요......'라는 메시지와 함께 이런 링크를 받았다.
React Data Grid
이렇게나 깔끔하게 나타낼 수 있는 라이브러리가 있었다! react-grid는 들어 봤지만 AG Grid는 처음 들어 보는 라이브러리였기 때문에 하나하나 검색해야 했는데, 공식 문서 외에는 정보가 별로 없어 내가 공부했던 부분들만 따로 정리해 보려 한다.
# npm
npm install --save ag-grid-community ag-grid-react
# yarn
yarn add ag-grid-community ag-grid-react
공식 문서에서 community도 함께 설치해야 한다고 설명하고 있다. 한꺼번에 설치해 두자.
아래 코드는 데이터를 담고 있는 rowData
와 필드명을 가지고 있는 columnDefs
를 작성해 둔 코드다. 두 가지만 설정해 줘도 충분히 그럴싸한 테이블이 나오는 걸 확인할 수 있다. rowData
의 속성과 columnDefs
의 field 값은 일치해야 한다.
import React, { useState } from "react";
import { AgGridReact } from "ag-grid-react";
import { ColDef } from "ag-grid-community";
import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-alpine.css";
const App = () => {
const [rowData] = useState<any[]>([
{ artist: "Nirvana", country: "US", debut: 1987 },
{ artist: "Arctic Monkeys", country: "UK", debut: 2005 },
{ artist: "R.E.M.", country: "US", debut: 1980 },
{ artist: "AC/DC", country: "Australia", debut: 1975 },
{ artist: "Blur", country: "UK", debut: 1990 },
{ artist: "Tahiti80", country: "France", debut: 1993 }
]);
const [columnDefs] = useState<ColDef[]>([
{ field: "artist" },
{ field: "country" },
{ field: "debut" }
]);
return (
<div className="ag-theme-alpine" style={{ height: 350, width: 600 }}>
<AgGridReact rowData={rowData} columnDefs={columnDefs} />
</div>
);
};
export default App;
많은 속성들 중에서 내가 사용했던 속성만 예시로 적용해 보았다.
gridOptions
전반적인 테이블의 속성을 지정한다.
- pagination: 어렵게 코드로 구현할 필요 없이 한 페이지에 보여 줄 데이터 개수만 지정하면 깔끔하게 나타낼 수 있다.
defaultColDef
열의 속성을 지정한다.
- resizable
: 유연하게 열의 너비를 사용자가 늘였다 줄였다 할 수 있는 속성이다.
- sortable
: 정렬 기능을 제공한다. 필드 이름을 누르면 오름차순/내림차순으로 정렬할 수 있다.
- filter
: 조건을 붙여 정렬한다. 이 역시 필드 이름으로 hover 해 보았을 때 오른쪽에 뜨는 아이콘으로 정렬 가능하다.
domLayout: autoHeight
를 사용해 높이를 자동으로 조절되게 설정할 수 있다.
enableCellTextSelection: 스크롤 해 텍스트를 복사할 수 있다.
onSelectionChanged: 사용해 본 적은 없으나 선택한 정보를 가져올 수 있는 속성이라고 한다.
const gridOptions: GridOptions = {
pagination: true,
paginationPageSize: 3,
suppressHorizontalScroll: true
};
const defaultColDef: ColDef = useMemo(() => {
return {
resizable: true,
sortable: true,
filter: true
};
}, []);
return (
<div className="ag-theme-alpine" style={{ width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
gridOptions={gridOptions}
enableCellTextSelection={true}
domLayout="autoHeight"
/>
</div>
);
onGridReady
에 원하는 데이터를 fetch 해 와 렌더링시키는 것이 하이라이트!
rowData
와 columnDefs
를 상태관리 하기 위해 useState로 먼저 선언해 주고, api에서 데이터를 가지고 와 각각 넣어 주면 쉽게 테이블을 만들 수 있다.
데이터는 JSONPlaceholder에서 가지고 왔다.
const [rowData, setRowData] = useState<any[]>([]);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([]);
const onGridReady = async () => {
try {
const response = await fetch(
"https://jsonplaceholder.typicode.com/todos"
);
const data = await response.json();
setRowData(data);
setColumnDefs(
Object.keys(data[0]).map((field) => ({
headerName: field,
field: field
}))
);
} catch (error) {
console.log(error);
}
};
return (
<div className="ag-theme-alpine" style={{ width: 800 }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
gridOptions={gridOptions}
enableCellTextSelection={true}
onGridReady={onGridReady}
domLayout="autoHeight"
/>
</div>
);