React-Virtualized ํบ์๋ณด๊ธฐ! ๐
๋ฆฌ์กํธ๋ก ๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ๋ฌด์ํ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ํ ์ด๋ธ, ๋ฆฌ์คํธ, ๋๋ ๊ทธ๋ฆฌ๋ ํํ๋ก ๋ ๋๋งํด์ผ ํ ๋๊ฐ ์์ด์. ํ์ง๋ง ํ๋ฉด์ ๋ณด์ด์ง ์๋ ๋ฐ์ดํฐ๊น์ง ์ ๋ถ ๋ ๋๋งํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ๋๋ ค์ง๊ณ , ์ฌ์ฉ์ ๊ฒฝํ์ด ์ ํ๋ ์ ์์ฃ . ์ฌ๊ธฐ์ ๋ฑ์ฅํ๋ ํด๊ฒฐ์ฌ๊ฐ ๋ฐ๋ก React-Virtualized์ ๋๋ค!
React-Virtualized๋? ๐
React-Virtualized๋ ๊ธด ๋ฆฌ์คํธ๋ ํ ์ด๋ธ์ ํจ์จ์ ์ผ๋ก ๋ ๋๋งํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ณด์ด๋ ์์ญ(viewport)์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ง ๋ ๋๋งํ๊ณ , ์คํฌ๋กค์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์์ดํ ์ ์์ฑํ๊ฑฐ๋ ์ ๊ฑฐํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
๐ ๊ฐ์ํ(Virtualization): ํ์ํ ๋ฐ์ดํฐ๋ง ‘๋ณด์ด๋ ๋งํผ’ ๊ทธ๋ ค์ค์ผ๋ก์จ DOM์ ๊ฐ๋ณ๊ฒ ์ ์งํ๋ ๊ธฐ์ ์ ๋๋ค.
์ React-Virtualized๋ฅผ ์จ์ผ ํ ๊น?
1. ์ฑ๋ฅ ์ต์ ํ
๋ธ๋ผ์ฐ์ ๋ ์์ฒ ๊ฐ์ DOM ์์๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ๊ธฐ ์ด๋ ค์์. React-Virtualized๋ ํ์ํ DOM๋ง ์์ฑํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๊ณ , ๋ ๋๋ง ์๋๋ฅผ ๋์ ๋๋ค.
2. ๋ค์ํ ๊ธฐ๋ฅ ์ ๊ณต
๋ฆฌ์คํธ, ๊ทธ๋ฆฌ๋, ํ ์ด๋ธ ๊ฐ์ UI ์์๋ฅผ ์ต์ ํ๋ ๋ฐฉ์์ผ๋ก ๋ ๋๋งํ ์ ์๋ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
3. ๊ฐํธํ ์ฌ์ฉ๋ฒ
์ฝ๊ฒ ์ค์นํ๊ณ ํ์ํ ์ปดํฌ๋ํธ๋ฅผ ์ ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ด์.
์ฃผ์ ์ปดํฌ๋ํธ
React-Virtualized๋ ์ฌ๋ฌ ์ปดํฌ๋ํธ๋ฅผ ์ ๊ณตํ์ง๋ง, ํต์ฌ ์ปดํฌ๋ํธ๋ ์๋์ ๊ฐ์ต๋๋ค.
1. List
์คํฌ๋กค ๊ฐ๋ฅํ ๊ธด ๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํ ๋ ์ฌ์ฉํฉ๋๋ค.
2. Grid
ํ(row)๊ณผ ์ด(column)๋ก ๊ตฌ์ฑ๋ ๋ฐ์ดํฐ(์: ๋๊ท๋ชจ ํ ์ด๋ธ)๋ฅผ ๋ ๋๋งํ ๋ ์ ์ฉํฉ๋๋ค.
3. AutoSizer
ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ์ปดํฌ๋ํธ ํฌ๊ธฐ๋ฅผ ๋์ ์ผ๋ก ์กฐ์ ํฉ๋๋ค.
4. InfiniteLoader
๋ฌดํ ์คํฌ๋กค ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ์ฌ์ฉํฉ๋๋ค.
์ค์นํ๊ธฐ
๋จผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ๊ฒ ์ฃ ?
npm install react-virtualized
# ๋๋
yarn add react-virtualized
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
๋ฆฌ์คํธ(List) ์ปดํฌ๋ํธ
๊ธด ๋ฆฌ์คํธ๋ฅผ ๋ ๋๋งํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ ์์ ์ ๋๋ค.
import React from "react";
import { List } from "react-virtualized";
const rowCount = 1000; // 1,000๊ฐ์ ๋ฆฌ์คํธ ์์ดํ
const rowHeight = 50; // ๊ฐ ์์ดํ
์ ๋์ด
const rowRenderer = ({ key, index, style }) => (
<div key={key} style={style}>
Row #{index}
</div>
);
function App() {
return (
<List
width={300} // ๋ฆฌ์คํธ ๋๋น
height={300} // ๋ฆฌ์คํธ ๋์ด
rowHeight={rowHeight} // ๊ฐ ์์ดํ
์ ๋์ด
rowCount={rowCount} // ์ด ์์ดํ
๊ฐ์
rowRenderer={rowRenderer} // ๊ฐ ์์ดํ
๋ ๋๋ง ๋ฐฉ์
/>
);
}
export default App;
๊ทธ๋ฆฌ๋(Grid) ์ปดํฌ๋ํธ
ํ ์ด๋ธ ํํ์ ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋งํ ๋ ์ฌ์ฉํฉ๋๋ค.
import React from "react";
import { Grid } from "react-virtualized";
const cellRenderer = ({ columnIndex, key, rowIndex, style }) => (
<div key={key} style={style}>
Cell {rowIndex}, {columnIndex}
</div>
);
function App() {
return (
<Grid
cellRenderer={cellRenderer} // ์
๋ ๋๋ง ๋ฐฉ์
columnCount={10} // ์ด์ ๊ฐ์
columnWidth={100} // ๊ฐ ์ด์ ๋๋น
height={300} // ๊ทธ๋ฆฌ๋ ๋์ด
rowCount={10} // ํ์ ๊ฐ์
rowHeight={50} // ๊ฐ ํ์ ๋์ด
width={800} // ๊ทธ๋ฆฌ๋ ๋๋น
/>
);
}
export default App;
AutoSizer์ ํจ๊ป ์ฌ์ฉํ๊ธฐ
ํ๋ฉด ํฌ๊ธฐ์ ๋ง๊ฒ ๋ฆฌ์คํธ ๋๋ ๊ทธ๋ฆฌ๋์ ํฌ๊ธฐ๋ฅผ ์๋์ผ๋ก ์กฐ์ ํ๋ ค๋ฉด AutoSizer๋ฅผ ์ฌ์ฉํฉ๋๋ค.
import React from "react";
import { List, AutoSizer } from "react-virtualized";
const rowRenderer = ({ key, index, style }) => (
<div key={key} style={style}>
Row #{index}
</div>
);
function App() {
return (
<AutoSizer>
{({ width, height }) => (
<List
width={width}
height={height}
rowHeight={50}
rowCount={1000}
rowRenderer={rowRenderer}
/>
)}
</AutoSizer>
);
}
export default App;
InfiniteLoader๋ก ๋ฌดํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ
๋ฌดํ ์คํฌ๋กค์ ๊ตฌํํ๊ณ ์ถ๋ค๋ฉด InfiniteLoader๋ฅผ ํ์ฉํ์ธ์.
import React, { useState } from "react";
import { List, InfiniteLoader } from "react-virtualized";
const rowCount = 1000;
const loadMoreRows = ({ startIndex, stopIndex }) =>
new Promise((resolve) => {
console.log(`Loading rows ${startIndex} to ${stopIndex}`);
setTimeout(resolve, 1000); // API ํธ์ถ ์๋ฎฌ๋ ์ด์
});
const rowRenderer = ({ key, index, style }) => (
<div key={key} style={style}>
Row #{index}
</div>
);
function App() {
const [loadedRowsMap, setLoadedRowsMap] = useState({});
const isRowLoaded = ({ index }) => !!loadedRowsMap[index];
return (
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreRows}
rowCount={rowCount}
>
{({ onRowsRendered, registerChild }) => (
<List
width={300}
height={300}
rowHeight={50}
rowCount={rowCount}
onRowsRendered={onRowsRendered}
ref={registerChild}
rowRenderer={rowRenderer}
/>
)}
</InfiniteLoader>
);
}
export default App;
React-Virtualized์ ์ฅ์
- ํผํฌ๋จผ์ค: ์์ฒ ~ ์๋ฐฑ๋ง ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋๋ ๋ ๋๋ง์ด ๋น ๋ฆ ๋๋ค.
- ์ ์ฐ์ฑ: ๋ฆฌ์คํธ, ํ ์ด๋ธ, ๊ทธ๋ฆฌ๋ ๋ฑ ๋ค์ํ UI๋ฅผ ์ง์ํฉ๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ: ๊ฐ์ํ๋ก ๋ถํ์ํ DOM ์์ฑ ๋ฐฉ์ง.
์ฃผ์์ฌํญ
- ์คํ์ผ ์ง์ : ๊ฐ ํญ๋ชฉ์ style ์์ฑ์ ํตํด ์์น์ ํฌ๊ธฐ๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค.
- ๋ ๋๋ง ๋น์ฉ: rowRenderer์ ๊ฐ์ ๋ ๋๋ง ํจ์๋ ๊ฐ๋ฒผ์ด ์ฐ์ฐ๋ง ์ํํด์ผ ํฉ๋๋ค.
- ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋น๊ต: react-window๋ React-Virtualized์ ๊ฐ๋ฒผ์ด ๋์์ผ๋ก ๋ ๋์ ์ฑ๋ฅ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
React-Virtualized๋ฅผ ํ์ฉํ๋ฉด ๋ฐ์ดํฐ ์์ด ๋ง์๋ ์ฑ๋ฅ ์ข์ ๋ฆฌ์คํธ๋ ํ ์ด๋ธ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ด์. ์ฒ์์ ์ฝ๊ฐ ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง, ํ ๋ฒ ์ตํ๋ฉด ํ๋ก์ ํธ์์ ๊ฐ๋ ฅํ ๋๊ตฌ๋ก ํ์ฉํ ์ ์์ต๋๋ค!
๐ท์ ์ค์ ๊ฐ๋ฐ์๊ฐ ๋์ด๋ด ์๋น! ๐ท