본문 바로가기
SPA/Next

[Next] AG Grid 사용하기

by J4J 2022. 4. 3.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 AG Grid 사용하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

들어가기에 앞서 AG Grid에서 제공해주는 여러 기능들 중 기본적인 기능들만 다뤄보려고 합니다.

 

추가적인 상세 내용이 필요하신 분들은 공식 문서를 참고하시면 좋을 것 같습니다.

 

 

 

기본 설정

 

[ 1. 패키지 설치 ]

 

$ npm install ag-grid-react ag-grid-community

 

 

 

[ 2. 기본 코드 작성 ]

 

기본적인 구조를 가지는 코드를 base.tsx 파일을 생성하여 작성해보겠습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Base: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand' },
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}>
            </AgGridReact>
        </div>
    );
};

export default Base;

 

 

 

코드를 작성한 뒤 파일을 실행해보면 다음과 같이 가장 기본적인 grid 구조를 확인할 수 있습니다.

 

실행 결과

 

 

 

정렬 및 필터 설정

 

일반적으로 많이 사용되는 기능들 중 하나인 정렬 및 필터 설정을 해보려고 합니다.

 

AG Grid를 사용하여 구현할 경우 정렬 및 필터 기능을 설정하는 것은 정말 간단한 작업입니다.

 

위의 코드에서 다음과 같이 columnDefs를 변경해주기만 하면 됩니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const SortingFilter: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    // 정렬 및 필터 설정
    const [columnDefs] = React.useState([
        { field: 'brand', sortable: true, filter: true },
        { field: 'name', sortable: true, filter: true },
        { field: 'capacity', sortable: true, filter: true },
        { field: 'price', sortable: true, filter: true },
    ])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}>
            </AgGridReact>
        </div>
    );
};

export default SortingFilter;

 

 

 

실행해보면 설정하기 전과 다를 것이 없는 화면을 확인할 수 있습니다.

 

실행 화면

 

 

 

하지만 다음과 같이 필드를 클릭하면 클릭된 필드에 맞게 정렬이 되는 것을 확인할 수 있습니다.

 

정렬

 

 

 

또한 필드에 마우스를 가져가면 필드마다 햄버거 바를 확인할 수 있고 클릭할 경우 필터 할 수 있는 내용들을 작성할 수도 있게 됩니다.

 

필터

 

 

반응형

 

 

필드별 공통 설정 분리

 

위의 코드를 확인해보면 정렬과 필터를 설정하기 위해 필드마다 설정값들을 모두 작성해준 것을 확인할 수 있습니다.

 

이런 반복적인 작업을 하지 않기 위해 AG Grid에서는 필드별 공통 설정을 할 수 있도록 도와줍니다.

 

조금 더 깔끔하게 코드를 작성하기 위해 다음과 같이 수정해줄 수 있습니다.

 

 

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const DefaultColDef: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    // 기존 공통 설정 제거
    const [columnDefs] = React.useState([
        { field: 'brand' },
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    // 필드별 공통 설정
    const defaultColDef = React.useMemo(() => {
        return {
            sortable: true,
            filter: true,
        }
    }, [])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            {/* 그리드에 공통 설정 추가 */}
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}
                defaultColDef={defaultColDef}>
            </AgGridReact>
        </div>
    );
};

export default DefaultColDef;

 

 

 

Grid 너비 수정 설정

 

이번에는 화면에 그려진 Grid의 너비를 수정할 수 있도록 설정해보겠습니다.

 

4개의 필드중 brand 필드만 수정할 수 있도록 다음과 같이 코드를 작성해줄 수 있습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Resize: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand', resizable: true }, // brand 필드만 사이즈 변경 설정
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}>
            </AgGridReact>
        </div>
    );
};

export default Resize;

 

 

 

코드를 실행해보면 다음과 같이 brand 필드 옆에 세로 바가 하나 생긴 것을 확인할 수 있습니다.

 

너비 수정

 

 

 

마우스를 가져다 대면 양방향 화살표가 나오고 클릭하여 자유롭게 너비를 수정해줄 수 있습니다.

 

 

 

SelectBox 설정

 

다음 설정으론 selectBox를 추가하여 원하는 row를 선택하고 선택된 row들의 데이터를 확인해볼 수 있도록 해보겠습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const CheckBox: NextPage = () => {

    const agGridReactRef = React.useRef<AgGridReact>(null); // agGridReact useRef

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand', checkboxSelection: true }, // brand에 checkbox 추가
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    // 선택된 데이터 확인
    const handleSelected = () => {
        if(agGridReactRef.current) {
            const selectedNodes = agGridReactRef.current.api.getSelectedNodes();
            const selectedData = selectedNodes.map((node) => node.data);
            console.log(selectedData);
        }
    }

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            {/* 체크박스 다중 선택 설정 */}
            <AgGridReact
                ref={agGridReactRef}
                rowData={rowData}
                columnDefs={columnDefs}
                rowSelection="multiple">
            </AgGridReact>

            <button onClick={handleSelected}>Click !</button> {/* 버튼 클릭 시 선택된 데이터 확인 */}
        </div>
    );
};

export default CheckBox;

 

 

 

코드를 실행해보면 다음과 같이 brand 필드에 체크박스가 생성된 것을 확인할 수 있습니다.

 

체크박스 확인

 

 

 

또한 row를 선택하고 Click ! 버튼을 누르면 다음과 같이 console창에 선택한 데이터가 확인되는 것도 볼 수 있습니다.

 

선택된 데이터 확인

 

 

728x90

 

 

필드에 이미지 추가 (Renderer 설정)

 

위의 selectBox와 유사한 느낌으로 이번엔 이미지를 추가해보도록 하겠습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Image: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    // 필드에 보여질 화면
    const renderer = (params: any) => {
        return (
            <span>
                <img src="/images/lion.jpg" height="30px" />
                {params.value}
            </span>
        );
    }

    const [columnDefs] = React.useState([
        { field: 'brand', cellRenderer: renderer }, // brand에 renderer 설정
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}>
            </AgGridReact>
        </div>
    );
};

export default Image;

 

 

 

코드를 실행해보면 다음과 같은 결과를 확인할 수 있습니다.

 

필드에 이미지 추가

 

 

 

renderer설정은 이미지 뿐만 아니라 개인적으로 커스텀하여 다양한 모습의 필드를 보여줄 수 있다고 생각하기 때문에 여러 방면으로 활용될 수 있을 것이라고 생각합니다.

 

 

 

필드 고정 설정 (pin 설정)

 

이번에는 특정 필드들의 위치를 고정시키는 설정을 해보겠습니다.

 

brand만 왼쪽에 고정시켜 다른 필드들은 스크롤이 되더라도 위치가 유지되도록 해보겠습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Pin: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand', pinned: 'left' }, // brand만 왼쪽에 고정
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}>
            </AgGridReact>
        </div>
    );
};

export default Pin;

 

 

 

코드를 작성한 뒤 실행해보면 다음과 같은 결과를 확인할 수 있습니다.

 

필드 고정 - 1

 

 

 

그리고 우측으로 스크롤을 해보면 다음과 같이 brand는 왼쪽 위치에 고정되어 있는 것을 확인할 수 있습니다.

 

필드 고정 - 2

 

 

 

필드 그룹화

 

상황에 따로 사용될 수 있는 필드별 그룹화를 설정해보겠습니다.

 

brand를 기준으로 그룹화를 하여 화면에 표출시켜보겠습니다.

 

한 가지 알아야 될 점은 그룹화 같은 경우는 추가 패키지 설치를 진행해줘야 합니다.

 

추가 설치되는 패키지는 테스트단계에서는 자유롭게 사용할 수 있지만 운영 환경에서 사용될 때는 비용을 지불해야 하는 것으로 보입니다.

 

자세한 사항은 공식 문서를 참고해주시길 바랍니다.

 

 

 

 

[ 1. 패키지 설치 ]

 

$ npm install ag-grid-enterprise

 

 

 

[ 2. 그룹화 설정 ]

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import 'ag-grid-enterprise'; // enterprise import
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Group: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand', rowGroup: true, hide: true }, // brand를 기준으로 그룹화
        { field: 'name', /* rowGroup: true, hide: true */ }, // group 기준 필드를 늘리고 싶은 경우 주석 해제
        { field: 'capacity' },
        { field: 'price' },
    ])

    // 그룹화된 컬럼 설정
    const autoGroupColumnDef = React.useMemo(() => {
        return {
            resizable: true,
        }
    }, [])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            {/* Grid에 그룹 컬럼 설정 추가 */}
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}
                autoGroupColumnDef={autoGroupColumnDef}>
            </AgGridReact>
        </div>
    );
};

export default Group;

 

 

 

코드를 실행해보면 다음과 같이 그룹화가 이루어진 화면을 확인할 수 있습니다.

 

필드 그룹화

 

 

 

애니메이션 설정

 

위에 설정된 그룹화 내용을 확인하기 위해 펼쳐보면 다음과 같습니다.

 

애니메이션 설정 전

 

 

 

딱딱한 느낌으로 실행이 이루어지기 때문에 애니메이션 설정을 통해 화면 사용자 경험을 높여보도록 하겠습니다.

 

import * as React from 'react';
import { NextPage } from 'next';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import 'ag-grid-enterprise';
import { AgGridReact } from 'ag-grid-react';

interface IrowData {
    brand: string;
    name: string;
    capacity: number;
    price: number;
}

const Animated: NextPage = () => {

    const [rowData] = React.useState<IrowData[]>([
        { brand: '칠성', name: '사이다', capacity: 500, price: 2000 },
        { brand: '칠성', name: '사이다', capacity: 1000, price: 3000 },
        { brand: '칠성', name: '제로사이다', capacity: 360, price: 1000 },
        { brand: '펩시', name: '콜라', capacity: 500, price: 1500 },
        { brand: '펩시', name: '제로콜라', capacity: 500, price: 1500 },
        { brand: '코카콜라', name: '콜라', capacity: 500, price: 1800 },
        { brand: '코카콜라', name: '제로콜라', capacity: 500, price: 2000 },
        { brand: '해태', name: '갈아만든배', capacity: 360, price: 1500 },
    ])

    const [columnDefs] = React.useState([
        { field: 'brand', rowGroup: true, hide: true },
        { field: 'name' },
        { field: 'capacity' },
        { field: 'price' },
    ])

    const autoGroupColumnDef = React.useMemo(() => {
        return {
            resizable: true,
        }
    }, [])

    return (
        <div className="ag-theme-alpine" style={{ width: 600, height: 400, margin: '0 auto' }}>
            {/* 애니메이션 설정 추가 */}
            <AgGridReact
                rowData={rowData}
                columnDefs={columnDefs}
                autoGroupColumnDef={autoGroupColumnDef}
                animateRows={true}>
            </AgGridReact>
        </div>
    );
};

export default Animated;

 

 

 

위와 같이 단순하게 animateRows값에 true를 넣어 애니메이션 설정을 해봤습니다.

 

결과는 다음과 같이 실행되는 것을 확인할 수 있습니다.

 

애니메이션 설정 후

 

 

 

 

 

 

 

이상으로 AG Grid 사용하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글