MOMOO 프로젝트에서 무한히 많은 게시물을 보여주기 위해 무한 스크롤을 사용했습니다. 콘텐츠가 몇 천 개, 몇 만 개 이상으로 무한히 추가될 수 있는 무한 스크롤 UI 특성상 스크롤을 할수록 성능 저하가 일어날 수 있습니다. 따라서 무한 스크롤 성능 최적화를 위해 가상 리스트 기술을 적용했습니다.
Chrome DevTools Perfomence를 사용하여 성능을 측정했습니다.
성능 테스트는 CPU나 네트워크 자원 등의 제한하지 않은 맥북 에어 환경에서 진행했습니다.
가상 리스트 적용 후 약 3.6배의 성능 향상을 확인할 수 있었습니다.
0부터 약 500번째까지 콘텐츠를 추가하며 성능을 측정했습니다.
1169 ~ 1245번째 콘텐츠까지 5페이지를 추가하며 성능을 측정했습니다.
getFeeds ~ GPU 작업 완료, fetch 완료 ~ GPU 작업 완료 / getFeeds ~ fetch 완료
콘텐츠가 추가될 때마다 렌더링에 소요되는 시간이 증가하고 있음을 확인할 수 있습니다.
데이터를 불러오는 속도에는 유의미한 차이는 없으며,
렌더링 속도에서 큰 개선이 있었습니다.
가상 리스트 적용 후, 콘텐츠 추가 성능이 약 3.6배 향상되었습니다. (데이터 요청 시부터 렌더링 완료 시까지 / 1169 ~ 1245 콘텐츠 기준)
Virtuoso 라이브러리를 사용하여 기존 무한 스크롤 코드에 가상 리스트를 적용했습니다.
<Virtuoso data={feedsData} itemContent={itemContent} />
리스트 요소에 스크롤이 생겼습니다.
이는 윈도우 스크롤로 게시물을 탐색하려는 의도와 다릅니다.
따라서 useWindowScroll 속성을 추가했습니다.
<Virtuoso useWindowScroll data={feedsData} itemContent={itemContent} />
<Virtuoso
useWindowScroll
data={feedsData}
itemContent={itemContent}
components={{
List,
Item
}}
/>
접근성을 위해 List와 Item 태그를 각가 Ul, Li로 변경하려 했으나, 타입 에러가 발생했습니다.
const List = forwardRef<HTMLUListElement, HTMLProps<HTMLUListElement>>((props, ref) => (
<ul ref={ref} {...props} />
));
const Item = forwardRef<HTMLLIElement, HTMLProps<HTMLLIElement>>((props, ref) => (
<li ref={ref} {...props} />
));
'ForwardRefExoticComponent<Omit<HTMLProps<HTMLUListElement>, "ref"> & RefAttributes<HTMLUListElement>>' 형식은 'ComponentType<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style" | "children"> & { ...; } & RefAttributes<...> & { ...; }> | undefined' 형식에 할당할 수 없습니다.
차선책으로 ARIA role을 사용했습니다.
const List = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>((props, ref) => (
<div role="list" ref={ref} {...props} />
));
const Item = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>((props, ref) => (
<div role="listitem" ref={ref} {...props} />
));
ul, li 태그를 사용하기 위해 조사한 라이브러리입니다.
VariableSizeList를 사용하는 경우에도 itemSize를 개발자가 직접 계산해야 합니다.
MOMOO 프로젝트 게시물의 경우, 게시물을 렌더링한 후 게시물의 높이를 알 수 있습니다.
이는 게시물이 많아질수록 저장해야 하는 값이 무한히 늘어날 수 있기에, 좋은 로직은 아니라고 생각합니다.