프론트엔드 개발을 하다보면 대용량 데이터를 리스트로 보여주거나 많은 양의 데이터를 테이블 등 보여줘야하는 로직이 생긴다.
이럴 때에는 렌더링 이슈가 일어나기 쉽고 성능 이슈가 필수적으로 일어난다고 생각하는데,
이럴 때 사용하는 것이 가상화 이다.
일단, 가상화란 무엇이고 어떤 원리일까?
가상화 (Virtualization)
리스트 가상화란, 화면에 보이는 데이터만 렌더링하고 보이지 않는 요소는 DOM에서 제거하여 렌더링 성능을 극대화 하는 기법이다.
주로 많이 쓰이는 라이브러리는
- react-window
- react-virtualized
- RecycleListView
나는 react-virtualized를 사용했다.
특히 무한스크롤 기법을 사용하면 DOM에 무한한 요소들이 쌓이기때문에 성능 저하를 유발하기 쉬우니 유의하자.

구글링하다가 발견한 가상화 기법의 상황이다. 간결하게 정리가 잘 되어있다. 우리가 생각하는 뷰포트에 있는 것만 렌더하고 나머지는 렌더를 안하다가 스크롤 동작이 실행될 때 렌더링이 된다.
import generateArray from "./generateArray.ts";
import { useRef } from "react";
import { useVirtualizer } from "@tanstack/react-virtual";
const VirtualLargeList = () => {
const dummyArr = generateArray();
const parentRef = useRef(null);
const rowVirtualizer = useVirtualizer({
count: dummyArr.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 36,
overscan: 3,
});
return (
<div className="stack">
<p>Windowing 적용</p>
<div className="stack" ref={parentRef}>
<div
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
width: "100%",
position: "relative",
}}
>
{rowVirtualizer.getVirtualItems().map((virtualRow) => (
<div
key={virtualRow.index}
className={"item"}
style={{
position: "absolute",
width: "100%",
height: "36px",
transform: `translateY(${virtualRow.start}px)`,
}}
>
{dummyArr[virtualRow.index].content}
</div>
))}
</div>
</div>
</div>
);
};
export default VirtualLargeList;
적용은 이런식으로 하면 된다. 간단하게 어떻게 동작을 하는 지 설명해보자면,
tanstack에서 제공하는 useVirtualizer라는 hook은 부모 컴포넌트의 ref (참조)와 자식요소의 대략적인 크기를 입력을받아서
해당 ref를 통해 총 요소의 높이, 스크롤 위치 등의 정보를 계산하고
이를 바탕으로 해당 컴포넌트의 시작위치 보여져야 하는 컴포넌트 인덱스 등이 담긴 row를 리턴한다.
가상화 자식 요소들의 엘리먼트 만 translate로 이동을 시키고, 나머지 요소들은 DOM에서 제거하는 형태로 스크롤이 가능한 가상 리스트를 구현할 수 있다.
이렇게 가상화 기법을 이용하면, 성능이 얼마나 줄어드냐면 보통 브라우저가 화면에 그려내는 페인팅 시간이 1/10 수준으로 줄어든다
'FE 기술' 카테고리의 다른 글
| scratch 프로젝트와 Rush 모노레포: 개발 환경 최적화 전략 (0) | 2025.02.27 |
|---|---|
| [항해 플러스 1주차] 프레임워크 없이 SPA 만들기 - SPA , 라우터, 이벤트 위임 (0) | 2024.12.29 |