This project was bootstrapped with Create React App.
์ด ํ๋ก์ ํธ๋ CRA(Create React App)์ผ๋ก ๋ง๋ค์ด์ก์ต๋๋ค.
ํ๋ก์ ํธ๋ฅผ ๊ฐ๋ฐํ๊ฒฝ์ผ๋ก ๋ก์ปฌ์์ ํธ์คํ ํ๋ ค๋ฉด ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด์ฃผ์ธ์.
ํ๋ก์ ํธ๋ฅผ build ํ๋ ค๋ฉด ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด์ฃผ์ธ์.
build๋ ํ๋ก์ ํธ๋ฅผ ๋ก์ปฌ์์ ํธ์คํ
ํ๋ ค๋ฉด ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํด์ฃผ์ธ์.
Production build๋ฅผ ํธ์คํ
ํ๋ ค๋ฉด ๋จผ์ npm install -g serve ๋ฅผ ํตํด serve ํจํค์ง๋ฅผ ์ค์นํด์ฃผ์ธ์.
ํ๋ก์ ํธ์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
root
| .env
| .gitignore
| output.txt
| package-lock.json
| package.json
| README.md
| tree.txt
+---build
| |
| \ ...
+---node_modules
| |
| \ ...
+---public
| favicon.ico
| index.html
| logo192.png
| logo512.png
| manifest.json
| robots.txt
|
\---src
| App.css
| App.jsx
| App.test.js
| custom.css
| index.css
| index.js
| logo.svg
| reportWebVitals.js
| setupTests.js
|
+---api
| mediData.js
|
\---component
ChartContainer.jsx
DetailCellRenderer.jsx
PatientTable.jsxํ๋ก์ ํธ๋ฅผ ์คํํ๊ธฐ ์ํด์๋ API ์๋ฒ์ ์ฃผ์๋ฅผ .env ํ์ผ์ ์์ฑํด์ผ ํฉ๋๋ค.
์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ ๋์ผํ ์์น์ .env ํ์ผ์ ์์ฑํ๊ณ ๋ด๋ถ์ ๋ค์๊ณผ ๊ฐ์ด ํ๊ฒฝ๋ณ์๋ฅผ ์์ฑํ์ธ์.
# CRA requires REACT_APP_ prefix
REACT_APP_API_BASE_ADDR=[API_ADRESS_HERE]CRA๋ก ์์ฑ๋ ํ๋ก์ ํธ์๋
dotenvํจํค์ง๊ฐ ์ด๋ฏธ ์ค์น๋์ด ์์ต๋๋ค. ๋ค๋ง,.envํ์ผ ๋ด๋ถ์REACT_APP_์ ๋ฏธ์ฌ๊ฐ ๋ถ์ ํ๊ฒฝ๋ณ์ ๋ง์ ์ ์์ ์ผ๋ก ๋ถ๋ฌ ์ฌ ์ ์์ผ๋process.env์์ ์ํ๋ ํ๊ฒฝ๋ณ์๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ ๊ฒฝ์ฐ ์ด ๊ท์น์ ์ง์ผ์ผ ํฉ๋๋ค.
ํ๋ก์ ํธ ์งํ์ ์์ ์ด๋ค ํ๋ก ํธ์๋ ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํ์ฌ ๊ตฌํ์ ํ ์ง ๊ณ ๋ฏผํ์ต๋๋ค. ๊ธฐ์กด์ PHP ํ์คํ ํ๋ก์ ํธ์์ ํ๋ก ํธ์๋๋ฅผ ๋ง๋ค ๋ ์์ฃผ ์ฐ๋ jQuery, ๊ฐ์ฅ ์ต๊ทผ์ ์๋กญ๊ฒ ๊ณต๋ถํ๋ Svelte, ๊ทธ๋ฆฌ๊ณ ํ์ฌ์์ ์ผํ๋ฉฐ ์จ๋ณด์๋ React, ๋ชจ๋ ๋๋ฆ์ ์ฅ๋จ์ ์ ๊ฐ์ง๊ณ ์์ง๋ง ํ๋ก์ ํธ์ ๊ฐ์ฅ ์ ํฉํ๋ค๊ณ ํ๋จ๋๋ ๊ฒ์ ๊ณจ๋ผ์ผ ํ์ต๋๋ค.
jQuery๋ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก DOM์ ๋ค๋ฃจ๋ ๊ฒ์ ํ์ฌ๋ ํจํด์ผ๋ก ๋จ์ถ์์ผ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋๋ค. ๋๋ฌธ์ ์๋ฌด๋ฐ ํ๋ ์์ํฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด ๊ตฌํ์ ํ๋ ๊ฒ๋ณด๋ค ์ฝ๋์ ์์ ๋ค์ ์ค์ฌ์ฃผ๋ ์ฅ์ ์ด ์์ต๋๋ค. ๋ค๋ง, ๋ชจ๋ํ์ ์ด๋ ค์๊ณผ ์ ๋ง์ DOM์ด๋ฒคํธ๋ฅผ ๊ด๋ฆฌํ๊ธฐ์ ์ด๋ ต๊ธฐ ๋๋ฌธ์ jQuery์ ์ฌ์ฉ์ ํฌ๊ธฐํ์ต๋๋ค.
Svelte๋ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฅ์์ผ์ ๋งค์ฐ ๋จ์ํ ๋ฌธ๋ฒ์ผ๋ก ๋ชจ๋ ํ๋ก ํธ์๋ ํ๋ ์์ํฌ๋ค์ด ์ ๊ณตํ๋ ๋ค์ํ ๊ธฐ๋ฅ๋ค์ ์ง์ํฉ๋๋ค. Context API, Redux์ ๊ฐ์ ๊ธฐ์ ์ด ์์ด๋ ์ปดํฌ๋ํธ์ State๋ฅผ ๊ด๋ฆฌํ ์ ์๋ ๊ธฐ๋ฅ๋ค์ด ๋ด์ฅ๋์ด ์์ผ๋ฉฐ ๋ฌด์๋ณด๋ค๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ๊ฐ ์ ๋์ ์ผ๋ก ์ ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ ์๋๋ฅผ ๋์ผ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฒ ํ๋ก์ ํธ์์๋ ์ฐจํธ, ํํฐ๋ง๊ณผ ์ ๋ ฌ์ด ๊ฐ๋ฅํ ํ ์ด๋ธ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํด์ผ ํ๊ธฐ ๋๋ฌธ์ Svelte๋ก ๋ง๋ค์ด์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ ํ์ฌ ์์ ์์๋ ๋ถ์ ์ ํ์ต๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก React์์ ์คํ์ผ๋ง์ ์ํ Bootstrap 5.X์ ๋ํผ react-bootstrap๊ณผ ๋ฐ์ดํฐ ํ ์ด๋ธ, ์ฐจํธ ๋ฑ์ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ชจ๋ ์ฐพ์ ์ ์์๊ณ ํ๋ก์ ํธ์ ๊ฐ์ฅ ํฐ ๋ผ๋๋ React๊ฐ ๋์์ต๋๋ค. ์ด๋ฒ ํ๋ก์ ํธ์ CRA์์ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ ๊ฒ ์ด์ธ์ ์ฌ์ฉ๋ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"dependencies": {
"ag-grid-community": "^27.1.0", // ag-grid community license
"ag-grid-enterprise": "^27.1.0", // ag-grid enterprise license(trial)
"ag-grid-react": "^27.1.0", // react ๋ฐ์ดํฐ ํ
์ด๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
"apexcharts": "^3.33.2", // ๋ค์ํ ์ฐจํธ๋ฅผ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ react ๋ฒ์
"axios": "^0.26.1", // rest api ํธ์ถ์ ์ํ http ํด๋ผ์ด์ธํธ
"bootstrap": "^5.1.3", // bootstrap์ react ๋ํผ
}์ด ํ๋ก์ ํธ๋ ๋ค์์ 5ํญ๋ชฉ์ ๊ตฌํํ๋ ๊ณผ์ ๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค. ๊ฐ ํญ๋ชฉ์ ๊ตฌํํ๋ฉด์ ์ ํ๋ ์๊ฐ ๋ด์ ์ต๋ํ ๋ง์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ์ต๋๋ค. ๋ํ ์ค์ ๋์๋ณด๋ ํํ์ ์น์ฑ๋ค์ด ๊ฐ์ง๋ UI์ ๋น์ทํ ํํ๋ก ํ๋ฉด์ ๊ตฌ์ฑํ๊ณ ํ ํ๋ฉด์ ๋ด๊ธด ๋ง์ ์ ๋ณด๋ฅผ ํธ์ํ๊ฒ ๋ณผ ์ ์๋ ํํ๋ก ๊ตฌ์ฑํ์ต๋๋ค.
๋ณธ๊ฒฉ์ ์ผ๋ก ๊ตฌํ์ ์์ํ๊ธฐ ์ ์ ๊ฐ์ฅ ํต์ฌ์ด ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ AG Grid ์ ApexCharts ์ ๊ณต์ ๋ฌธ์๋ฅผ ์ดํด ๋ณด์์ต๋๋ค. ApexCharts ๋ ์ด์ ์ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ์ ์ผ๋ก ์ฌ์ฉํ ์ ์ด ์๊ธฐ ๋๋ฌธ์ React ํ๊ฒฝ์์ ์ฌ์ฉํ ๋ ์ด๋ค Component์ Prop์ ์ ๊ณตํ๋์ง๋ฅผ ์ฐพ์๋ดค์ต๋๋ค.
AG Grid ์ ๊ฒฝ์ฐ ๊ณต์ ๋ฌธ์์์ Enterprise ๋ผ์ด์ผ์ค์๋ง ์ ์ฉ ๊ฐ๋ฅํ ๊ธฐ๋ฅ์ ๋ชฉ๋ก์ด ๋ณ๋ ํ๊ธฐ๋์ด ์๋๋ฐ ๊ณต์ ๋ฌธ์์ ๋์์๋ ์ฝ๋ ์ค๋ํซ์ ๊ทธ๋๋ก ์ฌ์ฉํด๋ ๋์ํ์ง ์๋ ๋ถ๋ถ์ด ์์ด ๋จ์ ํ
์คํธ ๋ชจ๋์ ๋ง๋ค์ด ์ค์ ์ฌ์ฉ ๊ฐ๋ฅํ Prop๊ณผ Option์ ์ฐพ๋๋ฐ ์๋นํ ์๊ฐ์ ์๋นํ์ต๋๋ค.
ํ๋ฉด ๋ด๋ถ์ ๊ฐ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ธฐ ์ , react-bootstrap ์ ํ์ฉํ์ฌ ๊ฐ๋จํ ๋ค๋น๊ฒ์ด์
๋ฐ์ ๋ณธ๋ฌธ ์์ญ์ ๋ง๋ค๊ณ ๋์ ํด์๋์์๋ ์ ๋ณด๋ฅผ ์ง์คํด์ ๋ณผ ์ ์๋๋ก Container ์ปดํฌ๋ํธ๋ก ๋ณธ๋ฌธ ์์ญ์ ์ขํ ๊ทธ ์์ ํ
์ด๋ธ๊ณผ ์ฐจํธ ์ปดํฌ๋ํธ๋ฅผ ๋ฃ๊ธฐ๋ก ํ์ต๋๋ค. ํ
์ด๋ธ ์ปดํฌ๋ํธ ์ ์ชฝ์ ์ฐจํธ ์ปดํฌ๋ํธ๊ฐ ์์นํด์ผ ํ๊ณ ์ฐจํธ ์ปดํฌ๋ํธ๋ 5๊ฐ์ ์ฐจํธ๋ก ๊ตฌ์ฑ๋ ์ปจํ
์ด๋์ ์ ์ ํ ๋ฐฐ์นํด์ผ ํ๋ฉฐ ํ๋จ์ ํ
์ด๋ธ ์ปดํฌ๋ํธ์์ ํ์ํ ์ปจํธ๋กค ์์๋ค์ ๊ณ ๋ คํ์ฌ ์์ญ์ Row , Col ์ปดํฌ๋ํธ๋ก ๊ตฌ๋ถํ์ต๋๋ค.
Swagger UI๋ก API์ ๋ช
์ธ๊ฐ ์ ๊ณต๋์๊ธฐ ๋๋ฌธ์ ๊ฐ Endpoint ์ ํ๋ผ๋ฏธํฐ, ๋ฐํ ๋ชจ๋ธ์ ํ์ธํ๊ณ Axios ์์ฒญ์ ๋ณด๋ด๋ ์ ํธ๋ฆฌํฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์์ต๋๋ค.
์ฒซ๋ฒ ์งธ๋ก ๊ตฌํํด์ผ ๋๋ ์ปดํฌ๋ํธ๋ API์์ ์ ๊ณต๋๋ ํ์๋ค์ ๋ฆฌ์คํธ ๋ฐ์ดํฐ๋ฅผ ํ
์ด๋ธ ํํ๋ก ๋ณด์ฌ์ฃผ๋ ๋ฐ์ดํฐ ํ
์ด๋ธ ์ปดํฌ๋ํธ ์
๋๋ค. ๋จ์ํ ํ
์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ๋ถํฐ ์์ํ์ต๋๋ค. API๋ฅผ ์์ฒญํ๋ ์ ํธ๋ฆฌํฐ๋ ์ด๋ฏธ ๋ง๋ค์ด ๋์๊ธฐ ๋๋ฌธ์ AG Grid ์ ์๋ฒ์ฌ์ด๋ ํ๋ก์ธ์ฑ ์ต์
์ ์ฃผ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ํ๋ฉด ๋ฉ๋๋ค. ํ
์ด๋ธ์ ํ๊ธฐ๋์ด์ผ ํ ์ ๋ณด๋ ํ์ id, ์ฑ๋ณ, ์๋
์์ผ, ๋์ด, ์ธ์ข
, ๋ฏผ์กฑ, ์ฌ๋ง ์ฌ๋ถ ์ด 7๊ฐ์ ์ปฌ๋ผ์ผ๋ก AG Grid ์ columnDefs ์ต์
์ ์ถ๋ ฅํ ๋ฐ์ดํฐ ํ๋๋ฅผ ๋งคํํ๊ณ ํ๊ธ๋ก ํค๋๊ฐ ์ถ๋ ฅ๋ ์ ์๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค. ๋ํ ์ฑ๋ณ, ์๋
์์ผ, ์ฌ๋ง ์ฌ๋ถ ์ปฌ๋ผ์ ๊ฒฝ์ฐ API ์์ฒญ์ผ๋ก ํ๋ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณตํด์ ์ถ๋ ฅํฉ๋๋ค. ๊ทธ ๋ฐ์ ์ด ํ ๋ฌธ์ ์์ ๊ตฌํํด์ผ ๋๋ pagination , sorting , filtering ๊ธฐ๋ฅ์ ์ํด ๊ด๋ จ ์ต์
์ ์ฐพ์ ๋ถ์ฌํ์ต๋๋ค.
ํ
์ด๋ธ์ SSRM(Server-side Row Model) ์ต์
์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ ์ธก์์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์์ ์ถ๊ฐ๋ก ํ์ํ ์ต์
๋ค์ด ๋ง์ด ์์์ต๋๋ค. ๊ทธ ์ค์์๋ rowModelType: "serverSide" ์ต์
์ Enterprise License ์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ pagination: true ์ต์
๊ณผ ํจ๊ป ์ฌ์ฉํ ๊ฒฝ์ฐ ํ์ด์ง์ด ์ ๋๋ก ๋์ํ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์ด๋ ํจํค์ง ๋ฒ์ ^25.0.1 ์ดํ ๋ณ๊ฒฝ๋ ๊ฒ์ผ๋ก serverSideStoreType: "partial" ์ต์
์ผ๋ก store ๋ฐฉ์์ ๋ณ๊ฒฝํ์ง ์๊ณ ๊ธฐ๋ณธ ๊ฐ์ธ full ๋ก ์ฐ๋๋ ๊ฒฝ์ฐ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผํ์ฌ ํ์ฌ ํ์ด์ง๋ฅผ ์๋ ค์ฃผ๋ endRow ๊ฐ ๋์ํ์ง ์์ผ๋ฏ๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค.
// ag-grid options
const gridOptions = useMemo(
() => ({
masterDetail: true,
pagination: true,
rowModelType: "serverSide", // only available on Enterprise License(include trial)
serverSideStoreType: "partial", // !important! required for SSRM pagination, sorting, filtering
domLayout: "autoHeight",
detailRowHeight: 400,
)
}),
[setFilterModel]
)๊ณต์ Github์ ๊ด๋ จ ์ด์๊ฐ ์๋ด๋์ด ์์ต๋๋ค. => GitHub Issue
ํ์ด์ง๊ณผ ์ ๋ ฌ์ ์ํด์ AG Grid ์ columnDefs ์์ ์ ๋ ฌ์ด ๊ฐ๋ฅํ๊ฒ ํ ์ปฌ๋ผ์ ์ง์ ํ๊ณ , SSRM ๋ฐ์ดํฐ๋ฅผ ์ค๋นํ๋ useEffect() ๋ด์์ params ๋ก ์ ๋ฌ๋๋ prop์ endRow , sortModel ๊ฐ์ ์ฝ์ด ํ์ฌ ํ์ด์ง, ์ ์ฒด ๋ ์ฝ๋์ ์, ๊ทธ๋ฆฌ๊ณ ํ
์ด๋ธ์์ ์ด๋ค ์ปฌ๋ผ์ ์ ๋ ฌ์ ํ๋ ค๊ณ ํ๋์ง๋ฅผ ์์๋ด๊ณ ์ด๋ฅผ API๋ฅผ ํธ์ถํ ๋ ํ์ํ parameter๋ก ๋งคํํฉ๋๋ค.
[ ์ ๋ ฌ์ด ๊ฐ๋ฅํ ์ปฌ๋ผ(API ๋ช ์ธ๋ฅผ ๋ฐ๋ผ) ]
- ํ์ id (personID)
- ์ฑ๋ณ (gender)
- ์๋ ์์ผ (birthDatetime)
- ์ธ์ข (race)
- ๋ฏผ์กฑ (ethnicity)
- ์ฌ๋ง ์ฌ๋ถ (isDeath)
// pagination
const page = endRow / pageSize
// sorting
const sortOptions = {
orderColumn: null,
orderDesc: false,
}
if (sortModel.length) {
const { colId, sort } = sortModel[0]
const columnInfo = {
personID: "person_id",
gender: "gender",
birthDatetime: "birth",
race: "race",
ethnicity: "ethnicity",
isDeath: "death",
}
sortOptions.orderColumn = columnInfo[colId]
sortOptions.orderDesc = sort === "desc"
}์ถ๊ฐ ๊ธฐ๋ฅ์ผ๋ก ํ ํ์ด์ง ๋น ๋ณด์ฌ์ง๋ Row์ ์๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ ์ปจํธ๋กค์ด ํ์ํ์ต๋๋ค. ์ปจํธ๋กค์ ํํ๋ react-ootstrap์ Select ๋ฅผ ์ฌ์ฉํ๊ณ ํด๋น ์ปจํธ๋กค์ ๊ฐ์ ์ฝ์ด ๋ก์ปฌ state์ ์ ์ฅํ ๋ค, AG Grid ์ API๋ฅผ ํธ์ถํด ๋ ๋๋งํ ํ์ด์ง ์ฌ์ด์ฆ๋ฅผ ๋ณ๊ฒฝํ๋๋ก ํ์ต๋๋ค.
์ด๋ฒ ๊ตฌํ์์๋ ๋ค์์ ์ปฌ๋ผ์์ ํํฐ๋ง์ด ๊ฐ๋ฅํ๋๋ก ํ ์ด๋ธ์ ์์ ํด์ผ ํฉ๋๋ค.
- ์ฑ๋ณ(gender)
- ๋์ด(age)
- ์ธ์ข (race)
- ๋ฏผ์กฑ(ethnicity)
- ์ฌ๋ง ์ฌ๋ถ(death)
์ด๋ฅผ ์ํด์ AG Grid ์์ ์ ๊ณตํ๋ ํํฐ ์ปดํฌ๋ํธ๋ฅผ ํ์ฑํ ํ๊ธฐ ์ํด columnDefs ์ต์
์ filter: [filterClass] ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ๋์ด ์ปฌ๋ผ์ ์ ์ธํ ๋๋จธ์ง ์ปฌ๋ผ์ ๋ชจ๋ ์ฒดํฌ๋ฐ์ค๋ก ๋ฏธ๋ฆฌ ์ง์ ๋ ํญ๋ชฉ์ ์ ํ ๊ฐ๋ฅํ agSetColumnFilter ์ ์ฌ์ฉํ๊ณ ํํฐ๋ง ์ต์
์ ๋ค์ด๊ฐ ํญ๋ชฉ์ ๊ฐ๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํ๋ API์ ์์ฒญํ์ฌ ๋์ ์ผ๋ก ๋ฐ์ ์ ์๋๋ก ๊ตฌ์ฑํ์ต๋๋ค. ๋์ด๋ ํ์์ ๋ฆฌ์คํธ๋ฅผ ํ๋ํ ์ ์๋ API์์ minAge , maxAge ๋ฅผ ์ ๊ณตํ๋ฏ๋ก ์ซ์ ๋ฒ์๋ฅผ ํํฐ๋ง ํ ์ ์๋ agNumberColumnFilter ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๊ฐ ์ปฌ๋ผ์ ์ ์๋ ํํฐ๋ฅผ ์ค์ ๋ฐ์ดํฐ์ ๋ฐ์ฌํ๊ธฐ ์ํด์ SSRM ๋ฐ์ดํฐ๋ฅผ ์ค๋นํ๋ useEffect() ๋ด์์ params ๋ก ์ ๋ฌ๋๋ prop์ filterModel ์ ์ฝ์ด ์ฌ์ฉ์๊ฐ ์ด๋ค ์ปฌ๋ผ์์ ์ด๋ค ๊ฐ์ ๊ธฐ์ค์ผ๋ก ํํฐ๋ง์ ํ๊ณ ์ ํ๋ ์ง๋ฅผ ์์๋ด๊ณ API๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ์์ ํํฐ ๊ฐ๊ณผ ํํฐ๋งํ ์ปฌ๋ผ์ ID๋ฅผ ๋งคํํด ์ค๋๋ค.
// call api
getPatientList({
page,
length: pageSize,
orderColumn: sortOptions.orderColumn,
orderDesc: sortOptions.orderDesc,
gender: filterOptions.gender,
race: filterOptions.race,
ethnicity: filterOptions.ethnicity,
ageMin: filterOptions.ageMin,
ageMax: filterOptions.ageMax,
death: filterOptions.death,
})
.then((data) => {
params.success({
rowData: data.patient.list,
rowCount: data.patient.totalLength,
})
})
.catch((err) => {
console.log(err)
params.fail()
})์ด ๊ณผ์ ์์ API์ parameter ๊ฐ ์ฌ์ ์ ์ ํด์ ธ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ๋ฌธ์ ๊ฐ ์์๋๋ฐ, AG Grid ์ ํํฐ ๊ธฐ๋ฅ์ ํ ์ปฌ๋ผ์์ ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ ๋์์ And ๋ Or ์ฐ์ฐ์ผ๋ก ๋ณตํฉ ์กฐ๊ฑด ๊ฒ์์ด ๊ฐ๋ฅํ์ง๋ง API ์๋ํฌ์ธํธ์์ ์ง์๋์ง ์๊ธฐ ๋๋ฌธ์ ํ ๋ฒ์ ๋ ๊ฐ ์ด์์ ํํฐ๋ฅผ agSetColumnFilter ์์ ์ ํํ๊ฑฐ๋ minAge , maxAge ๊ฐ์ ์ถ์ถํ ์ ์๋ ์กฐ๊ฑด์ด ์๋ ํญ๋ชฉ์ agNumberColumnFilter ์์ ์ ํํ ๋ ํด๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํด ์ค ์ ์์์ต๋๋ค. ํด๋ผ์ด์ธํธ ์ธก์์ ์ฌ๋ฌ๋ฒ API๋ฅผ ํธ์ถํ์ฌ ๋ฐ์ดํฐ๋ฅผ Merge ํ๋ ๋ฐฉ๋ฒ๋ ์์์ง๋ง ๊ทธ๋ ๊ฒ ๋๋ฉด SSRM ์ฌ์ฉ์ ๋ชฉ์ ์ด ๋ฌด์ํด ์ง๊ธฐ ๋๋ฌธ์ ์ ์ ํ ๋ฉ์์ง๋ฅผ ์ฌ์ฉ์์๊ฒ ์ถ๋ ฅํ๊ณ ํด๋น ์ปฌ๋ผ์ filter ๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ผ๋ก ํ์ต๋๋ค.
๊ณผ์ ์กฐ๊ฑด์๋ ์์์ผ๋ ์ฌ๋ฌ ํํฐ๋ฅผ ๋์์ ์ ์ฉํ ์ ์๋ ํ
์ด๋ธ์ด๊ธฐ ๋๋ฌธ์ ํ์ฐ์ ์ผ๋ก ์ ๋ ฌ๊ณผ ํํฐ๋ง ๋ชจ๋๋ฅผ ํ๋ฒ์ ์ด๊ธฐํํ์ฌ ์ด๊ธฐ ์ํ์ ๋ฐ์ดํฐ๋ฅผ ๋ณผ ์ ์๋๋ก ๋ฆฌ์
์ปจํธ๋กค์ ์ถ๊ฐํ์ต๋๋ค. ์ปดํฌ๋ํธ์ ํํ๋ react-bootstrap ์ Button ์ ์ฌ์ฉํ์๊ณ ํ
์ด๋ธ ์๋จ ํด๋ฐ์ค ์ฐ์ธก์ ๋ฐฐ์นํ์ฌ ๋ฒํผ์ ํด๋ฆญํ๋ฉด AG Grid ์ API์์ ๊ฐ ์ปฌ๋ผ์ ์ง์ ๋ ํํฐ์ Instance๋ฅผ ํ๋ํ๊ณ Filter Model ์ null ๋ก ์ด๊ธฐํํ ๋ค, ์ ๋ ฌ, ํํฐ๊ฐ ๋ฌ์ ๊ฒฝ์ฐ ์ ๋ฌ๋๋ ์ด๋ฒคํธ๋ฅผ ์๋์ผ๋ก ํธ์ถํ์ฌ ์ ์ฒด ํ์ด์ง์ ๋ ๋๋ง ์์ด ํ
์ด๋ธ ๋ด์ ๋ฐ์ดํฐ๋ง ๋ค์ ๋ถ๋ฌ์ฌ ์ ์๋๋ก ํ์ต๋๋ค.
์ด๋ฒ ๋ฌธ์ ๋ ์ด๋ฏธ ๋ง๋ค์ด์ง full-function ๋ฐ์ดํฐ ํ
์ด๋ธ์ ๊ฐ row ์ child-row ๋ฅผ ์ ์๋ค ํ๋ค ํ ์ ์๋๋ก ๋ง๋ค๊ณ ๊ทธ ์์ ๋ ๊ฐ์ง API๋ก ๋ถํฐ ํ๋ํ ํ์์ ์์ธ ์ ๋ณด๋ฅผ ํ์ํ๋๊ฒ ๋ชฉ์ ์ด์์ต๋๋ค. AG Grid ์์ Master Detail ์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์ ๊ณต๋๋ ์์ธ๋ด์ฉ ์ต์
์ด ์์์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก 1๊ฐ์ ๋ฐ์ดํฐ ์์ค๋ก ๋จ์ผ ํ
์ด๋ธ๋ง ์ถ๋ ฅ ํ ์ ์์๊ธฐ ๋๋ฌธ์ ํ์์ ๋ฐฉ๋ฌธ ํ์์ ์ง๋จ ์์ธ์ ๋ณด ํ
์ด๋ธ์ ๋์์ ์ถ๋ ฅํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅ ํ์ต๋๋ค. ๋๋ฌธ์ ๊ณต์๋ฌธ์๋ฅผ ์ข๋ ์์ธํ ํ๊ณ ๋ค์ด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ป์ ์ ์์์ต๋๋ค.
AG Grid ์์ child-row ๋ฅผ ๊ทธ๋ฆฌ๋ ค๋ฉด detailCellRendererParams ๋ฅผ ํตํด child-row ์ ๋ค์ด๊ฐ ํ
์ด๋ธ์ ์ต์
๊ณผ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ๋ค๋ง ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ์ ์ธ ํ
์ด๋ธ ํ๋ ๋ฐ์ ์ถ๋ ฅํ ์ ์์ผ๋ฏ๋ก detailCellRenderer prop์ ํตํด์ ์ปค์คํ
cellRenderer ์ปดํฌ๋ํธ๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ผ๋ฐ์ ์ธ React Component ์ฒ๋ผ ๊ธฐ๋ณธ์ ์ธ ํ
์ด๋ธ ์ธ์ ์ํ๋ ํ์์ผ๋ก child-row ๋ด์ ์์๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ๋ง๋ค์ด์ง customCellRenderer ์๋ ๋ถ๋ชจ row์ data ์ rowNode , ๋ด๋ถ์์ AG Grid ์ API์ ์ ๊ทผํ๊ธฐ ์ํ API ๊ฐ์ฒด๊ฐ prop์ผ๋ก ์ ๋ฌ ๋ฉ๋๋ค. ๋๋ฌธ์ ๋ถ๋ชจ row๋ก๋ถํฐ rowIndex๋ ๋ฐ์ดํฐ ์์ personID ํ๋ ๊ฐ์ ์ฐธ์กฐํ์ฌ ์์ธ ์ ๋ณด API ํธ์ถ์ ํ์ํ parameter๋ฅผ ํ๋ํ ์ ์์ต๋๋ค.
const onGridReady = useCallback(
(params) => {
const gridInfo = {
id: node.id,
api: params.api,
columnApi: params.columnApi,
}
setGridApi(params.api)
api.addDetailGridInfo(rowId, gridInfo)
},
[node, rowId, api]
)๋ค๋ง AG Grid ์ API ์ฐธ์กฐ ๊ฐ์ฒด๋ ์ฌ๊ธฐ์ ๊ธฐ์ ๋ณต์ ๋์ด ์ ๋ฌ๋๊ธฐ ๋๋ฌธ์ prop์ผ๋ก ์ ๋ฌ๋๋ ๊ฒ์ ์ฐ์ง ์๊ณ ํ
์ด๋ธ์ด Mounted ์ํ์ผ ๋ ํธ์ถ๋๋ onGridReady() ์ฝ๋ฐฑ ๋ด์์ ํ๋ํ API ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ๋ ํ๋ํ ๊ฐ์ฒด๋ฅผ gridAPI ๋ก ์ ์ฅํด๋๊ณ API๋ฅผ ํธ์ถํด ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ useEffect() ์ deps์ ์ถ๊ฐํด ํ
์ด๋ธ์ด Mounted ๋ฌ์ ๋๋ง ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋๋ก ํฉ๋๋ค.
customCellRenderer ๋ด์์ ๊ทธ๋ ค์ง๋ ํ
์ด๋ธ์๋ ์ ๊ณต๋ API์ ๋ณ๋๋ก ํํฐ๋ง, ์ ๋ ฌ์ ์ํ parameter๋ฅผ ๋ฐ์ง ์๊ณ ํ ๋ฒ์ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ ๋ถ๋ฌ์ค๊ธฐ ๋๋ฌธ์ SSRM์ด ์ ์ฉ๋์ง ์์์ต๋๋ค. ๋ค๋ง ์ข์ ์์ญ์ ๊ทธ๋ ค์ง๋ ํ
์ด๋ธ์์ ๊ณ ๋ คํ์ฌ ํ ๋ฒ์ 5๊ฐ์ row๋ฅผ ํ์ํ๋๋ก ํ๊ณ ์ด๋ฏธ ๋ถ๋ฌ์จ ๋ฐ์ดํฐ๋ฅผ pageSize๋ก ๋๋์ด ๋ณด์ฌ์ค ์ ์๋๋ก ํ์ต๋๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ํ์์ ์ง๋จ ์์ธ์ ๋ณด ํ
์ด๋ธ ์์ชฝ์ react-bootstrap ์ Card ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํด ํด๋น ํ์๊ฐ ์ง๊ธ๊น์ง ๋ฐฉ๋ฌธํ ํ์๋ฅผ ํ์ํ๋๋ก ํ์ต๋๋ค.
onRowClicked: (e) => {
const { id: clickedRowIndex } = e.node
e.api.forEachNode((row) => {
if (row.id !== clickedRowIndex) {
row.setExpanded(false)
}
})
e.api.getDisplayedRowAtIndex(Number(clickedRowIndex)).setExpanded(!e.node.expanded)
},์ถ๊ฐ์ ์ผ๋ก ์์ฝ๋์ธ ํํ๋ก ํผ์ณ์ก๋ค๊ฐ ์ ํ๋ ๊ตฌ์กฐ์ child-row ์ ๋์ด ๋๋ฌธ์ ํ์ด์ง์ ์คํฌ๋กค ๊ธธ์ด๊ฐ ์ง๋์น๊ฒ ๊ธธ์ด์ง๋ ์ ์ ์ธ์งํด ํ
์ด๋ธ์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ด์ด๋๊ณ ๋น๊ตํ ์ผ์ด ์๋ค๋ ๊ฒ์ ์ ์ ๋กํ์ฌ ํ ๋ฒ์ ํ ๊ฐ์ ์์ธ์ ๋ณด child-row ๋ง ์ด๋ ค์๋๋ก ํ์ผ๋ฉฐ ์ด๋ ค์๋ child-row ๋ด์ ๋น ์์ญ์ ํด๋ฆญํ๊ฑฐ๋ ๋ถ๋ชจ row๋ฅผ ํด๋ฆญํ ๊ฒฝ์ฐ ๋ค์ ๋ซํ๋๋ก ํ ๊ธ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ต๋๋ค. ์ด ๊ณผ์ ์์ child-row ๋ํ ๋ถ๋ชจ ํ
์ด๋ธ์ row๋ก ์ฝ์
๋๊ธฐ ๋๋ฌธ์ rowIndex ๊ฐ ํ๋์ฉ ๋ฐ๋ ค ์ด๋ฏธ ๋ค๋ฅธ ํ
์ด๋ธ์ด ์ด๋ ค ์๋ ์ํฉ์์ ๋ ๋ค๋ฅธ ํ
์ด๋ธ์ ํผ์น๋ ค๊ณ ํ ๋ ๋ฐ๋ฆฐ rowIndex ์ ํด๋นํ๋ row๊ฐ ํผ์ณ์ง๋ ํ์์ onRowClicked() ์ฝ๋ฐฑ์์ ํด๋ฆญ๋ row์ ๊ณ ์ id ์ ๋น๊ตํด ์์ ํ์ต๋๋ค. ๋ํ ์๋๋ผ๋ฉด gridApi ๋ฅผ ํตํด ํ ๋ฒ์ ๋ชจ๋ row๋ฅผ ์ ์ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ deprecated ๋์๊ธฐ ๋๋ฌธ์ forEachNode() ๋ก ํ์ฌ ํ์ด์ง์ row๋ฅผ ์ํํ์ฌ ๋ด๋ถ prop์์ ํผ์ณ์ง ์ํ๋ฅผ ์ฝ๊ณ ๋ซ์์ค ์ ์๊ฒ ํ์ต๋๋ค.
์ด๋ฒ์๋ API์์ ์ ๊ณตํ๋ ํต๊ณ(์ง๊ณ) ์ ๋ณด๋ฅผ ๋ฐ์ ํ์ด ํํ์ ์ฐจํธ๋ก ์ถ๋ ฅํด์ผ ํฉ๋๋ค. ์ถ๋ ฅํด์ผ ํ๋ ํญ๋ชฉ์ ๋ค์์ 5๊ฐ์ง ์ ๋๋ค.
- ์ฑ๋ณ ํ์ ์
- ์ธ์ข ๋ณ ํ์ ์
- ๋ฏผ์กฑ๋ณ ํ์ ์
- (์ฑ๋ณ + ์ธ์ข )๋ณ ํ์ ์
- (์ฑ๋ณ + ๋ฏผ์กฑ)๋ณ ํ์ ์
API์์ ๋ฐํ๋๋ ๋ฆฌ์คํธ ๋ฐ์ดํฐ๊ฐ ๊ฐ ํญ๋ชฉ๋ณ๋ก ์ง๊ณ๋ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฐ ์กฐ๊ฑด๋ณ๋ก ๊ทธ๋ฃนํ๋ ๋ฐ์ดํฐ์ด๊ธฐ ๋๋ฌธ์ ๋ฆฌ์คํธ ๋ด์ ๊ฐ์ฒด๋ฅผ ์ด์ด ๊ทธ๋ํ์์ ํ์ํ ๋ฐ์ดํฐ์ ํํ๋ก ๊ฐ๊ณตํด ์ค ํ์๊ฐ ์์์ต๋๋ค. ApexCharts ์ Chart ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด ํ์ด ํํ์ ์ฐจํธ๋ฅผ ๊ทธ๋ฆฌ๋ ค๋ฉด ๋ ๊ฐ์ง array ๋ฐ์ดํฐ๊ฐ ํ์ํ๋ฐ, ํ ๊ฐ์ง๋ labels ๋ก ๊ฐ ํ์ด๋ณ legend(๋ฒ๋ก)์ ํด๋นํ๋ ํ
์คํธ ์ด๋ฉฐ ๋ค๋ฅธ ํ๋๋ series ๋ก ์ค์ ์ซ์ ๋ฐ์ดํฐ๊ฐ ์ ๊ณต๋์ด์ผ ํฉ๋๋ค. ์ด ๋ labels ์ series ์ ๊ฐ ํญ๋ชฉ์ 1๋1๋ก ์์๊ฐ ๋งค์นญ๋์ด์ผ ํฉ๋๋ค.
์ฐ์ labels์ ์ ๊ณตํ ๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ์ป๊ธฐ ์ํด์ ์ ๊ณต๋ API ์ค 3๊ฐ์ง๋ฅผ ํธ์ถํด์ ๋ก์ปฌ state ์ ์ ์ฅํ๊ณ ์ฒซ 3๊ฐ์ง ์ฐจํธ์ ๊ฐ๊ฐ ์ ๊ณตํ๊ณ ๋ค์ชฝ์ ๋ณตํฉ ์กฐ๊ฑด์ ๊ฐ์ง ์ฐจํธ์๋ ์ง์ string array๋ก labels ๋ฅผ ์ ๋ฌํ์ต๋๋ค. series ์ ์ ๊ณต๋ ๋ฐ์ดํฐ๋ API๋ฅผ ํธ์ถํ๋ useEffect() ๋ด์ ๋ฆฌ์คํธ ๋ฐ์ดํฐ๋ฅผ reduce() ๋ฅผ ํตํด ํ์ํ ์กฐ๊ฑด๋ณ๋ก ์ง๊ณํ๋๋ก ๊ตฌํํ์ต๋๋ค. ์ด ๋, ๋๋ฒ ์งธ-๋ค๋ฒ ์งธ, ์ธ๋ฒ ์งธ, ๋ค์ฏ๋ฒ ์งธ ๊ทธ๋ํ๋ ๊ฐ๊ฐ ์ฑ๋ณ๋ง ์ถ๊ฐ ์กฐ๊ฑด์ผ๋ก ํํฐ๋งํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ํ ๋ฒ์ API ํธ์ถ์์ ๊ฐ๊ฐ ๋ ์ฐจํธ์ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ๋ง๋ค์ด ๋ฐํํ๋๋ก ํ์ต๋๋ค.
return data ? (
<div className="pie-chart">
<Chart
options={chartOptions.options}
series={chartOptions.series}
type="pie"
width="100%"
/>
</div>
) : (
<div>No data.</div>
)์ด๋ ๊ฒ ๋ง๋ค์ด์ง 5๊ฐ์ Chart ์ปดํฌ๋ํธ๋ฅผ react-bootstrap ์ Row , Col, Card ๋ก ๋ง๋ค์ด์ง ChartContainer ์ปดํฌ๋ํธ์ ์ ์ ํ ๋ฐฐ์นํ์ฌ ํ
์ด๋ธ ์ปดํฌ๋ํธ ์์ชฝ์ ์ถ๋ ฅ๋๋๋ก ํ์ต๋๋ค. ๋ํ ์ ์์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ง ๋ชปํ ๊ฒฝ์ฐ์๋ ์ ์ ํ ๋ฉ์์ง๋ฅผ ๋์ ํ์ฌ ๋ณด์ฌ์ค๋๋ค.
๋ง์ง๋ง ๋ฌธ์ ์ธ ํ ์ด๋ธ ํํฐ๋ง์ ๊ทธ๋ํ ๋ ๋๋ง์ ๋ฐ์ํ๋ ๊ฒ์ ์๊ฐ์์ ๋ฌธ์ ์ ์ ๊ณต๋๋ API์์ ๋ฐํํ๋ ์ง๊ณ ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ๊ฒ ๊ฐ๊ณตํด์ ํ์ ๋ฆฌ์คํธ API๋ฅผ ํธ์ถํ์ง ์๊ณ ๋ ๊ตฌํํ ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํด ๊ตฌํํ์ง ๋ชปํ์ต๋๋ค. ํด๋น ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด์ ์๊ฐํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
App.jsx์AG Gridํ ์ด๋ธ์์ ํํฐ๋ง์ ํ ๋ ๋ฐํ๋๋filterModel์ ์ ์ฅํ state๋ฅผ ์ ์ธํ๋ค.- ํ
์ด๋ธ ์ปดํฌ๋ํธ์
filterModel์ ์ธ ์ ์๋setFilterModel๋ฉ์๋๋ฅผ prop์ผ๋ก ์ ๋ฌํ๊ณ ํ ์ด๋ธ์์ ํํฐ๋ง์ ํ ๋๋ง๋ค ์คํ๋๋onFilterChanged()์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด๋ถ์์setFilterModel(gridApi.getFilterModel())์ ๊ฐ์ดfilterModel์ ์ ์ฅํ๋ค. - ์ฐจํธ ์ปดํฌ๋ํธ์๋
filterModel์ prop์ผ๋ก ์ ๋ฌํด ์์กด์ฑ์ ๋ง๋ค๊ณ ์ฐจํธ ๋ฐ์ดํฐ ํ๋์ ์ํด API๋ฅผ ํธ์ถํ๋useEffect()์filterModel์ deps๋ก ์ถ๊ฐํด ์ค์ ํํฐ๋ง์ด ์ผ์ด๋ ๋๋ง๋ค ๋ค์ API๋ฅผ ํธ์ถํด ๋ ๋๋งํ๊ฒ ํ๊ณfilterModel๋ก ๋ถํฐ ์ด๋ค ์ปฌ๋ผ์ ์ด๋ค ๊ฐ์ ํํฐ๊ฐ ์ค์ ๋์ด์๋์ง๋ฅผ ์ป์ด๋ธ๋ค. - ํํฐ๊ฐ์ ๋ฐ๋ผ stats ๋ฆฌ์คํธ ๋ฐ์ดํฐ๋ฅผ ํํฐ๋งํ๊ณ ์ฌ ๊ฐ๊ณตํด์ ๊ฐ ์ฐจํธ์ ๋ฐ์ํ๋ค.
// filterModel
{
age: {
filter: 10
filterTo: 30
filterType: "number"
type: "inRange"
}
ethnicity: {
filterType: "set"
values: ['hispanic']
}
gender: {
filterType: "set"
values: ['M']
}
race: {
filterType: "set"
values: ['white']
}
}๋ค๋ง ์ด ๋ฐฉ๋ฒ์ API๋ฅผ ํธ์ถํ๋ useEffect() ์ ์ง๋์น๊ฒ ๋ง์ ์ฑ
์์ ๋ถ์ฌํ๊ณ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ๋๋ฌด ๋ง์ ์ฐ์ฐ์ ํ์๋ก ํ๊ณ stats ๋ฐ์ดํฐ๋ฅผ ๋๊ฒจ์ฃผ๋ API์ ๊ฐ ํญ๋ชฉ์ ๋ํ ์ง๊ณ๊ฐ ์ฃผ์ด์ง๋ ํธ์ด ๋ ๋์ ๊ตฌํ์ด ๊ฐ๋ฅํ์ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค. ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ํ์ ๋ฆฌ์คํธ API๋ฅผ ํธ์ถํด์ ์ง์ ํํฐ๋ง๋ ๋ฐ์ดํฐ์
์ ์ฒด๋ฅผ ์ง๊ณํด์ ์ฐจํธ์ ๋ฐ์ํ๋ ๊ฒ์ธ๋ฐ ์ด ๋ํ ๋นํจ์จ ์ ์
๋๋ค.
React๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ๊ฐ์ด ๊ธธ์ง ์๊ธฐ ๋๋ฌธ์ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ ํ๋๋ฐ ์ด๋ ค์์ด ์์์ต๋๋ค. jQuery์์ ๋์ ์ฌ์ฉํ๋ Datatables.js์ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ธฐ๋ํ AG Grid ๋ ํจ์ฌ ๋ง์ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์์๋ ์ ํํ์ง ์์ ๋ฌธ์ํ์ ํ์ฉ์ด ์ฝ์ง ์์์ต๋๋ค. ๋ํ ์ต๋ํ ๋ง์ด, ์ฃผ์ด์ง ๊ณผ์ ์์ ์๊ตฌํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ์ ์ด์ ์ ๋ง์ท๊ธฐ ๋๋ฌธ์ ๋ฆฌ๋ ๋๋ง ๋ฐฉ์ง์ ๊ฐ์ ์ฑ๋ฅ ์ต์ ํ๋ API ํธ์ถ, ๋ฐ์ดํฐ ํ์ฉ ๋ถ๋ถ์์ ๋ฆฌํฉํ ๋ง์ด ๊ฐ๋ฅํ ์ฝ๋๊ฐ ๋จ๊ฒ ๋์๊ณ ์์ ๋จ์๋ก ์ปดํฌ๋ํธ๋ฅผ ๋๋ ํ๋ฉด์ ์ข ๋ ์น๋ฐํ๊ฒ ๊ตฌ์ฑํ์ง ๋ชปํ ์ ์ด ์์ฌ์์ผ๋ก ๋จ์ต๋๋ค.