데이터 그리드 (Mui-X)
X2BEE BO(BackOffice) 템플릿은 목록 조회 및 데이터 관리(입력/수정/삭제)를 효율적으로 처리하기 위해 MUI-X 데이터 그리드를 활용합니다. 이 템플릿은 BO 프로그램 전반에 걸쳐 폭넓게 사용되며, MUI를 확장하여 추가 기능을 제공함으로써 개발 편의성을 크게 향상시킵니다.
X2beeDataGrid
데이터 그리드 파일 구조
파일 위치는
/src/lib/x2bee-data-grid/*입니다.
파일명
설명
x2bee-data-grid.tsx
화면에 그려지는 그리드 컴포넌트입니다.
x2bee-data-grid-utils.ts
그리드 컴포넌트에서 사용되는 함수들로, 다회 사용되거나 분리가능하고 상대적으로 긴 코드들을 컴포넌트에서 분리해 둔 유틸 파일입니다.
x2bee-data-grid-constants.ts
그리드에서 사용되는 상수들을 관리하는 파일입니다.
x2bee-data-grid-types.ts
그리드에서 사용되는 타입들을 관리하는 파일입니다.
x2bee-grid-date-picker.tsx
그리드에서 사용되는 date picker 관련 파일입니다.
use-x2bee-data-grid.ts
그리드에 관련된 hook이 선언된 파일입니다.
x2bee-data-grid-context.tsx
그리드를 감싼 컴포넌트로 dataRef를 주입해줍니다.
데이터 그리드 컴포넌트 제공 옵션
MUI 그리드 옵션에서 MUI 제공 옵션에 대해 자세하게 확인할 수 있습니다.
X2beeDataGrid 컴포넌트에서 추가적으로 제공하는 옵션은 다음과 같습니다.
옵션
설명
dataRef
MUI에서 제공되는 API(apiRef) 외에 추가적으로 제공되는 함수들을 포함한 ref 객체입니다. 소스 페이지의 X2beeDataGridDataRefType에서 제공되는 기능들을 확인할 수 있습니다. 대표적으로 그리드에서 관리되는 CUD의 row state별로 row 리스트를 가져올 수 있으며, 버튼의 행 관리 기능도 함수로 제공됩니다.
hideDeleteRow
Row 삭제 시 그리드에서 노출 여부를 설정합니다. 기본값은 false입니다.
enableRowState
Row의 상태(CUD)를 표시할지 여부를 설정합니다. 기본값은 false입니다.
fetchSave
Row의 저장 버튼에 대한 콜백 함수입니다. 선언 시 저장 버튼이 노출됩니다.
paginationProps
페이지네이션을 구현하기 위해, 필요하지 않은 경우 MUI 데이터 그리드의 기본 속성 rows를 간단히 사용할 수 있습니다. 기본값으로 최소한 빈 배열을 제공하는 것이 필수적입니다. paginationProps가 없으면 rows는 필수로 지정되어야 합니다. 이 접근 방식은 MUI의 페이지네이션 구현에 의존하지 않고 X2beeDataGrid 내에서 모든 상태를 내부적으로 관리합니다. 입력 타입은 X2beeSimplePagination이며, paginationProps, 기존의 rows, pagination, pageSizeOptions와 동시에 사용할 수 없습니다. paginationProps 내의 pageSizeOptions는 옵션으로 지정할 수 있으며, 제공되지 않을 경우 기본값은 [100, 500, 1000, 5000, 10000]입니다.
enableNoColumn
이 옵션은 기본 열 "No"의 가시성을 설정할 수 있게 해줍니다. 기본값은 true입니다.
컴포넌트 사용 가이드
X2beeDataGrid 컴포넌트는 DataGridPremium 컴포넌트를 감싸, 내부적으로 MUI에서 제공하지 않는 추가, 수정, 삭제 상태를 관리하는 역할을 합니다.
그리드는 자체적으로 공간을 가지지 않으므로, 반드시 상위 태그 및 컴포넌트에서 공간을 확보해야 정상적으로 렌더링됩니다. 참고: https://mui.com/x/react-data-grid/layout/
필수로 입력해야 하는 옵션값은
columns와rows또는paginationProps입니다.paginationProps와rows는 반드시 둘 중 하나만 입력해야 합니다.
예시:
<Box sx={{ height: '500px' }}>
<X2beeDataGrid
dataRef={dataRef}
apiRef={apiRef}
columns={columns}
checkboxSelection
onCellDoubleClick={onCellDoubleClickHandler}
slotProps={{
columnsManagement: { getTogglableColumns: () => columns.map((el) => el.field) },
baseCheckbox: { disabled: baseCheckboxDisable }
}}
slots={{
toolbar: () => CustomButtons({
changeCheckBoxSelectable: (value) => setBaseCheckboxDisable(!value)
})
}}
// pagination용 추가가 필요한 props
paginationProps={{ fetch: async (paginationModel) => fetch(paginationModel.page, paginationModel.pageSize) }}
/>
</Box>그리드 API
1. 커스텀 그리드 API(dataRef)
MUI에서 제공되는 그리드 API는 MUI apiRef 정보에서 자세하게 확인할 수 있습니다.
X2beeDataGrid 컴포넌트 내부의 상태값등에 접근하며, 커스텀 기능들을 호출가능하게 해주는 API 객체입니다.
기능
설명
useDataRef()
이 훅은 dataRef에 대한 객체를 제공합니다. 예: const dataRef = useDataRef(); <X2beeDataGrid dataRef={dataRef} ... />
dataRef.current.all()
오브젝트는 update, create, delete라는 세 가지 프로퍼티를 포함하여 반환됩니다. 각 프로퍼티는 수정된 행, 추가된 행, 삭제된 행을 배열 형태로 제공합니다.
dataRef.current.grid()
다음은 반환되는 함수 목록 입니다. selectClear, selectDelete, allClear, addRow, setUpdateRows export type X2beeDataGridDataRefGridFnType = { selectClear: () => void // 선택 행 변경취소 selectDelete: () => void // 선택 행 삭제 allClear: () => void // 전체 행 변경취소 addRow: () => void // 행 추가 save: () => void // fetchSave 호출 validation: ValidationFunction // update 및 create 행 valid asyncValidation: AsyncValidationFunction // update 및 create 행 valid를 비동기로 시행 setUpdateRows: (ids: GridRowId[]) => void // updateRowId를 직접 추가 }
dataRef.current.fetch()
수동으로 grid에 fetch를 진행할때 사용됩니다. paginationProps을 사용하여 fetch를 구현한경우 반드시 해당 기능으로 fetch를 진행해야 합니다.
dataRef.current.create() / dataRef.current.update() / dataRef.current.delete()
dataRef.current.all()에서 제공되는 값들을 별도로 제공하는 함수입니다.
dataRef.current.validation()
그리드의 모든 editRow에대해 validation을 진행합니다.
2. API 객체 활용 가이드
MUI에서는 그리드를 제어할 수 있는 API 객체를 제공합니다. X2beeDataGrid에서도 그리드의 등록, 수정, 삭제 관련 기능 및 데이터를 API 객체를 통해 활용할 수 있습니다.
예시:
const dataRef = useDataRef();
const apiRef = useGridApiRef();
return (
<>
<Box>
<Markdown children={content} />
</Box>
<Stack direction="column">
<Box sx={{ border: 1 }}>데이터 출력</Box>
<Box sx={{ border: 1 }}>{JSON.stringify(showData)}</Box>
</Stack>
<Stack direction="row" borderBottom={1}>
<Button onClick={() => setShowData(dataRef.current.create())}> 추가 데이터 가져오기 </Button>
<Button onClick={() => setShowData(dataRef.current.update())}> 수정 데이터 가져오기 </Button>
<Button onClick={() => setShowData(dataRef.current.delete())}> 삭제 데이터 가져오기 </Button>
<Button onClick={() => setShowData(dataRef.current.all())}> 모든 데이터 가져오기 </Button>
</Stack>
<Box height="500px">
<X2beeDataGrid
columns={columns}
rows={gridSampleRows}
dataRef={dataRef}
apiRef={apiRef}
enableRowState
// pagination을 위한 추가 props
fetchSave={(allGridData, validation) => {
const errorMessage = validation();
if (errorMessage) alert(errorMessage);
}}
/>
</Box>
</>
);X2beeDataColDef
1. 그리드 컬럼 제공 옵션
MUI에서 제공하는 옵션은 MUI 컬럼 옵션 에서 확인 할 수 있습니다.
X2beeGridColDef 에서 제공하는 추가옵션은 다음과 같습니다.
옵션명
타입
설명
visible
boolean
열이 초기에 노출될지 여부를 설정 가능합니다. initialState의 column hide를 단순화 한 옵션입니다.
defaultValue
any
열 추가시 기본으로 지정되는 값입니다.
validBlank
boolean
셀 수정시, 빈값을 허용할지 여부를 설정 가능합니다.
validation
X2beeGridValidation[]
셀 수정시, 값 검증을 위해 사용됩니다. valid와 message를 prop으로 가지며, valid의 리턴값이 false일 경우, 셀에서 message가 오류로 출력됩니다. 제공되는 params는 다음과 같습니다. { id, value, field, row, otherProps, apiRef }
dateEditor
Object
셀 수정시, DatePicker 사용할 옵션을 설정합니다. type을 통해 노출할 달력 형식을 지정할 수 있으며 결과 값을 dateFormat을 통해 지정할 수 있습니다. 제공되는 params는 다음과 같습니다. { type: 'date' | 'dateTime', dateFormat: string, minDate: string, maxDate: string }
dynamicEditable
코드 참조X2beeGridColDef의 dynamicEditable참조.
다른 셀의 값에 의해 해당 셀의 editable여부가 동적으로 변경되는 옵션입니다. 사용시 editable은 따로 선언해주지 않으셔도 됩니다. 제공되는 params는 다음과 같습니다. { otherProps: GridValidRowModel, apiRef: MutableRefObject, dataRef: MutableRefObject<X2beeDataGridDataRefType> } 리턴으로 돌려줘야하는 값은 다음과 같습니다. { editable: boolean, value?: string }
2. 확장된 컬럼 타입 정의 및 유효성 검증 가이드
MUI 에서 제공하는 GridColDef 타입을 상속 받아 옵션을 추가한 컬럼 타입입니다. 기존의 MUI의 기능 및 X2beeDataGrid에서 추가적으로 제공하는 기능들을 정의 가능합니다.
예시:
const cols: X2beeGridColDef[] = [
{
headerName: '상품번호',
field: 'goodsNo',
editable: true,
width: 150,
validBlank: '상품번호를 입력해 주세요',
validation: [
{
valid: (params) => {
if (params.otherProps.goodsType === '묶음상품') {
const typeInt = parseInt(params.value as string, 10) ?? 1000
return typeInt >= 1000
}
return true
},
message: '묶음상품인경우 상품번호가 1000보다 커야합니다'
},
{
valid: (params) => {
if (params.otherProps.goodsType === '일반상품') {
const typeInt = parseInt(params.value as string, 10) ?? 1000
return typeInt < 1000
}
return true
},
message: '일반상품인경우 상품번호가 1000보다 작아야합니다'
}
]
},
{
headerName: '상품명',
field: 'goodsNm',
type: 'string',
editable: true,
width: 150,
validBlank: true,
validation: [
{
valid: (params) => {
const allRow = params.apiRef.current.getRowModels()
const allRowIds = params.apiRef.current.getAllRowIds()
return allRowIds.every(
(id) => params.id === id || allRow.get(id)?.[params.field] !== params.value
)
},
message: '중복된 상품명은 사용할수 없습니다.'
}
]
},
{
headerName: '상품타입',
field: 'goodsType',
type: 'singleSelect',
valueOptions: [...GoodsTypeArr],
defaultValue: GoodsTypeArr[0],
editable: true,
width: 150
},
{
headerName: '가격',
field: 'price',
type: 'number',
editable: true,
width: 150,
validation: [
{
valid: (params) => (params.value as number) > 0,
message: '가격은 0보다 커야합니다'
}
]
},
{
headerName: '등록일',
field: 'regDate',
editable: true,
width: 150,
defaultValue: dayjs().format(),
dateEditor: {
type: 'date',
dateFormat: 'YYYYMMDD',
minDate: dayjs().format(),
maxDate: '2050-12-31'
}
}
]Common-toolbar
2. 툴바 확장 및 커스터마이징 가이드
이 가이드는 MUI에서 제공하는 GridToolbarContainer를 감싸 기능을 추가한 컴포넌트를 상세히 설명합니다.
그리드에 필요한 기본 기능인 열 추가, 삭제, 초기화 외에도 커스텀 버튼 및 엑셀 다운로드 버튼을 추가할 수 있는 방법을 안내합니다.
예시:
<X2BeeDataGrid
...
slots={{
toolbar: () => (
<Toolbar.Container
leftSlot={
<>
<Toolbar.Button type="add" title="기획전 등록" onClick={() => console.log('등록 팝업')} />
<Toolbar.Button type="remove" />
<Toolbar.Button type="resetAll" />
<Toolbar.Button type="save" />
<Toolbar.Button type="custom" title="일괄 변경" onClick={() => console.log('일괄 변경')} />
</>
}
rightSlot={
<>
<Toolbar.Button type="excel" />
<Toolbar.Button type="custom" title="복사" onClick={() => console.log('복사')} />
</>
}
/>
)
}}
/>