반응형
리액트 애플리케이션에서 성능 저하를 가장 체감하기 쉬운 순간은 수천, 수만 개의 데이터를 리스트로 렌더링할 때입니다. 브라우저가 수만 개의 DOM 노드를 한꺼번에 생성하고 관리하는 것은 메모리와 CPU에 엄청난 부담을 주기 때문입니다.
이 문제를 해결하는 시니어 개발자의 무기, 윈도잉(Windowing) 혹은 가상 리스트(Virtual List) 기법에 대해 알아보겠습니다.
1. 왜 대량의 리스트는 느릴까?
우리가 10,000개의 아이템이 담긴 배열을 단순하게 .map()으로 렌더링하면 다음과 같은 문제가 발생합니다.
- 초기 로딩 지연: 10,000개의 DOM 요소를 만드는 데 시간이 오래 걸립니다.
- 메모리 점유: 브라우저가 만 개의 노드를 메모리에 들고 있어야 하므로 램 사용량이 급증합니다.
- 스크롤 성능 저하: 스크롤 시 브라우저는 모든 노드의 위치를 계산해야 하므로 프레임 드랍(버벅임)이 발생합니다.
2. Windowing(가상화)의 핵심 원리
윈도잉 기법의 핵심은 간단합니다. **"사용자의 눈에 보이는 부분(Viewport)만 렌더링하자"**는 것입니다.
- 컨테이너 설정: 전체 리스트의 높이를 미리 계산하여 스크롤바를 만듭니다. (실제 데이터는 없지만 스크롤은 가능하게 함)
- 동적 렌더링: 사용자가 스크롤을 움직일 때마다 현재 화면 범위에 해당하는 아이템만 계산하여 DOM에 붙입니다.
- 노드 재사용: 화면 밖으로 나간 아이템은 즉시 제거하여 DOM 노드 개수를 수십 개 수준으로 일정하게 유지합니다.
3. 대표적인 라이브러리 비교
직접 구현할 수도 있지만, 안정성과 기능을 위해 검증된 라이브러리를 사용하는 것이 일반적입니다.
| 라이브러리 | 특징 | 추천 상황 |
| react-window | 매우 가볍고 빠름. 핵심 기능에 집중함. | 아이템의 높이가 고정(Fixed)되어 있을 때 |
| react-virtuoso | 사용하기 매우 쉬움. 동적 높이 지원이 강력함. | 댓글창처럼 아이템마다 높이가 다를 때 (Variable) |
| react-virtualized | 기능이 가장 많지만 무겁고 오래됨. | 복잡한 그리드나 다중 열 리스트가 필요할 때 |
4. 핵심 구현 개념: Overscan
가상 리스트를 사용할 때 가장 중요한 설정 중 하나가 Overscan입니다.
사용자가 빠르게 스크롤할 때, 딱 화면에 보이는 것만 렌더링하면 다음 아이템이 그려지기 전까지 빈 화면이 보일 수 있습니다. 이를 방지하기 위해 화면 위아래로 보이지 않는 아이템을 몇 개 더 미리 그려두는 것을 Overscan이라고 합니다.
💡 시니어의 팁: Overscan 값이 너무 크면 가상화의 의미가 퇴색되고, 너무 작으면 스크롤 시 깜빡임이 생깁니다. 보통 화면 크기의 1/2 정도나 아이템 5~10개 정도로 설정하는 것이 적당합니다.
5. 실전 적용 예시 (react-window)
JavaScript
import { FixedSizeList as List } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>아이템 {index} 행입니다.</div>
);
const Example = () => (
<List
height={500} // 리스트를 보여줄 창의 높이
itemCount={10000} // 전체 아이템 개수
itemSize={50} // 각 아이템의 높이
width={'100%'} // 리스트 너비
>
{Row}
</List>
);
이 방식을 사용하면 아이템이 1억 개라도 브라우저는 단 수십 개의 <div>만 렌더링하므로 성능은 $O(1)$에 가깝게 유지됩니다.
반응형
'개발 > React' 카테고리의 다른 글
| [고급반] Step 2-2. 로직 재사용의 기술: Render Props와 HOC (0) | 2025.12.23 |
|---|---|
| [고급반] Step 2-1. 확장성 있는 디자인 패턴: Compound Components (0) | 2025.12.23 |
| [고급반] Step 1-2. Memoization 전략: memo, useMemo, useCallback의 명과 암 (0) | 2025.12.23 |
| [고급반] Step 1-1. 재조정(Reconciliation)과 가상 DOM의 내부 원리 (0) | 2025.12.23 |
| [중급반] Step 3-3. 비동기 통신 및 에러 처리 고급 기법 (0) | 2025.12.15 |