리스트가 길어질수록 모든 항목을 한 번에 렌더링하면 성능 문제가 발생한다.
특히 1,000개 이상의 데이터를 렌더링할 때 브라우저가 느려지고 사용자 경험이 저하된다.
이를 해결하는 기술이 Virtual Scroll(가상 스크롤)이다.
🔎 가상 스크롤(Virtual Scroll)이란?
가상 스크롤(Virtual Scroll)은 긴 리스트나 테이블에서 화면에 보이는 항목만 렌더링하고 나머지 항목은 렌더링하지 않는 기법이다.
- 사용자가 스크롤할 때마다 보여줄 항목만 동적으로 추가한다.
- 렌더링 비용과 메모리 사용량을 크게 줄일 수 있다.
항목 수가 많아도 초기 렌더링 속도를 빠르게 유지하고 스크롤 성능을 높이는 것이다.
💡 예: 카카오톡, 인스타그램, 유튜브 피드 → 수천~수만 개 항목이 있지만 느려지지 않는다.
🧩 예제 코드
import { FixedSizeList as List } from 'react-window';
import { useState } from 'react';
const ITEM_COUNT = 1000;
const generateItems = () => {
return Array.from({ length: ITEM_COUNT }, (_, i) => `항목 ${i + 1}`);
};
const items = generateItems();
const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => {
console.log('렌더링된 항목:', index);
return <div style={{ ...style, padding: 8, borderBottom: '1px solid #ddd' }}>{items[index]}</div>;
};
const ListCompare = () => {
const [showNormalList, setShowNormalList] = useState(true);
return (
<div style={{ padding: 20 }}>
<h2>Virtual Scroll 실험</h2>
<button onClick={() => setShowNormalList(!showNormalList)}>
{showNormalList ? 'Virtual Scroll 보기' : '일반 리스트 보기'}
</button>
<div style={{ marginTop: 20, height: 400, overflow: 'auto', border: '1px solid #ccc' }}>
{showNormalList ? (
<div>
{items.map((_, index) => (
<Row
key={index}
index={index}
style={{ padding: 8, borderBottom: '1px solid #ddd' }}
/>
))}
</div>
) : (
<List height={400} itemCount={ITEM_COUNT} itemSize={35} width={'100%'}>
{Row}
</List>
)}
</div>
</div>
);
};
export default ListCompare;
총 1,000개의 항목 데이터를 생성하여 일반 리스트는 1,000개 항목을 모두 렌더링하고, Virtual 리스트는 react-window 라이브러리의 FixedSizeList를 사용하여 보이는 항목만 렌더링하도록 하였다.
🧩 실험 결과
▶️ 일반 리스트
- 1,000개의 항목이 모두 렌더링된다.
- 브라우저의 메모리 사용량이 크게 증가한다.
- 스크롤 성능이 느려진다.
- 콘솔에 렌더링된 항목: 0 ~ 999가 한 번에 모두 출력된다.
▶️ Virtual 리스트
- 보이는 영역에 해당하는 항목만 렌더링된다.
- 스크롤할 때 새로운 항목만 추가 렌더링된다.
- 브라우저 메모리 사용량이 일정하게 유지된다.
- 콘솔에 스크롤 위치에 따라 일부 index만 출력된다.
React Developer Tools 익스텐션을 켜고 확인해 보면 스크롤할 때마다 렌더링되는 것을 확인할 수 있다.
📝 Virtual Scroll의 원리
- 실제 DOM에는 화면에 보이는 항목만 추가된다.
- 보이지 않는 항목은 렌더링하지 않고 스크롤 위치에 따라 동적으로 교체된다.
- 렌더링 비용을 크게 줄여 긴 리스트에서도 빠른 반응성을 유지한다.
📝 정리
항목 | 일반 리스트 | Virtual 리스트 |
렌더링 항목 수 | 전체 항목 (1,000개) | 화면에 보이는 항목만 |
초기 렌더링 속도 | 느림 | 빠름 |
메모리 사용량 | 높음 | 낮음 |
스크롤 성능 | 느림 | 빠름 |
반응형
'Library & Runtime > React' 카테고리의 다른 글
[React] Control Props 패턴 : Controlled vs Uncontrolled (0) | 2025.05.07 |
---|---|
[React] Compound Component 패턴 + Context 이해하기 (0) | 2025.05.06 |
[React] 계산/렌더링 최적화: useMemo + React.memo 실험 (0) | 2025.05.04 |
[React] 무거운 연산 최적화 : 일반 계산 vs useMemo (0) | 2025.05.03 |