1만 행 모두 렌더하면 DOM 폭발 → 60fps 깨짐. 화면에 보이는 30개만 렌더 + 위/아래 padding 으로 스크롤바 유지 = windowing. 1만 행도 60fps.
📖 핵심 개념
가상 list: 보이는 영역(viewport) + overscan 만 실제 DOM.
Total height = itemCount * itemHeight 로 가짜 padding.
스크롤 시 보이는 영역 계산 → 그 인덱스 범위만 render.
💻 코드 패턴
@tanstack/react-virtual
import{useVirtualizer}from'@tanstack/react-virtual';functionBigList({items}:{items: Row[]}){constparentRef=useRef<HTMLDivElement>(null);constv=useVirtualizer({count: items.length,getScrollElement:()=>parentRef.current,estimateSize:()=>60,// 평균 행 높이
overscan: 5,});return(<divref={parentRef}style={{height:'100vh',overflow:'auto'}}><divstyle={{height: v.getTotalSize(),position:'relative'}}>{v.getVirtualItems().map(vi=>(<divkey={items[vi.index].id}data-index={vi.index}ref={v.measureElement}// 가변 높이 측정
style={{position:'absolute',top: 0,left: 0,width:'100%',transform:`translateY(${vi.start}px)`,}}><Rowdata={items[vi.index]}/></div>))}</div></div>);}