Virtualized List

jade·7일 전

가상 리스트, 가상 스크롤, 목록 가상화 등 다양한 이름으로 불리는 최적화 방식에 대해서 알아보자.

이 방식은 동적인 목록을 렌더링할때, 특히 대량의 리스트를 랜더링할 때, 전체 목록을 렌더링하지 않고 화면에 “보이는” 컨텐츠 들만 랜더링하는 방식이다.

목록의 요소들을 가상화하기 위해서는 윈도우를 고정시키고 목록 주변에서 윈도우를 움직여야 한다.


// 리스트 아이템 하나의 높이
const ItemHeightSize = 50;

// 
function RecylerView({items}: Props) {

	// 목록의 시작인덱스, 끝 인덱스를 상태로 관리하며
	// 사용자가 스크롤할때마다 보여줄 목록의 인덱스를 업데이트 한다.
	// 여기서 보여줄 목록의 갯수는 20개
    const [visiableStartIndex, setVisiableStartIndex] = useState(0);
    const [visiableEndIndex, setVisiableEndIndex] = useState(20);

	
    const containerRef = useRef<HTMLDivElement>(null);


	// 스크롤 할때마다 start, end index update
    const handleScroll = () => {
        if(containerRef.current) {
        const scrollTop:number = containerRef.current.scrollTop;
        const newStartIndex = Math.floor(scrollTop/ ItemHeightSize);
        const visibleItemCount = Math.ceil(window.innerHeight/ ItemHeightSize);
        const newEndIndex = newStartIndex + visibleItemCount;
        setVisiableStartIndex(newStartIndex);
        setVisiableEndIndex(newEndIndex);
        }
    }

	
	// 이벤트 핸들러, 최초 1회 등록
    useEffect(() => {
        if(containerRef.current){
            containerRef.current.addEventListener("scroll", handleScroll)

        return () => {
            if(containerRef.current){
                 containerRef.current.removeEventListener("scroll", () => {})
            }
        }
        }
    }, [])


    return(

        // container : 스크롤을 위한 큰 돔 엘리먼트
        <div style={{ overflowY:"scroll", height:"100vh"}} ref={containerRef}>
		// 이녀석이 Window : relative 속성을 가지는 작은 컨테이너 돔 엘리먼트
            <ul style={{ height: ItemHeightSize * items.length, position:"relative" , width:500}}>
                {items.slice(visiableStartIndex, visiableEndIndex).map((item: number, index: number) => (
					// 컨테이너 내부에 위치하고
					// absolute 포지션 속성을 가지고
					// top | left | width |. height 속성을 가지는 자식 요소들
                    <li key={index} style={{height: `${ItemHeightSize}px`, position: "absolute", top: (visiableStartIndex+index)*ItemHeightSize}}>{item}</li>
                ))}
            </ul>
        </div>
    )
}

https://patterns-dev-kr.github.io/performance-patterns/list-virtualization/

profile
keep on pushing

0개의 댓글