2023.08.01 ~ 2023.08.12 (완성 후 지속적인 업데이트 및 배포 중)
포켓몬과 포켓몬 정보를 찾아볼 수 있는 도감 서비스입니다. 이 프로젝트는 대용량 렌더링의 최적화에 대해 노력했던 프로젝트입니다.
위 서비스는 3가지로 나누어 집니다.
Typescript, React, Recoil,TailwindCss
[성능 최적화를 위해 생각했던 방안]
[React-window를 선택한 이유]
[React-window 스크롤 분리 개선]
윈도우와 콘텐츠 스크롤 분리 현상
react-window
스크롤 분리 개선 후 윈도우 스크롤과 연동하기
react-window
의 스크롤은 사라져 윈도우 스크롤 하나만 생성 됩니다. 또한 자체 엘리먼트가 스크롤되지 않게 됩니다.react-window
에 숨겨진 콘텐츠를 보이게 할 수 없다는 것입니다. react-window
내부의 스크롤 동작에만 반응해 노드의 위치를 계산하여 적합한 콘텐츠를 보여주기 때문입니다. 라이브러리의 내부 동작을 살펴보면 CSS 속성 중 position: absolute
를 사용하여 스크롤 위치에 맞는 항목을 조정하는 것을 확인할 수 있었습니다.따라서 이제는 window
의 스크롤을 react-window
와 연동할 필요가 있었습니다.
[React-window 스크롤 연동 및 스크롤 오차값 계산]
export default function useReactWindowScroll() {
const innerRef = useRef<HTMLElement | null>(null);
const outerRef = useRef<HTMLElement | null>();
const ref = useRef<FixedSizeList | null>(null);
useEffect(() => {
//쓰로틀링 처리 해 스크롤 이벤트 처리량 최적화.
const handleWindowScroll = throttle(() => {
const { offsetTop = 0 } = outerRef.current || { offsetTop: 0 };
const scrollMin = 0;
let windowScrollY = window.scrollY;
//양쪽 스크롤 높이 차이값
let scrollOffset = windowScrollY - offsetTop;
let isScrollRender =
scrollOffset >= scrollMin && scrollOffset <= document.body.scrollHeight;
//스크롤 위로 올릴 시 쓰로틀링 때문에 생기는 오차값 보정
if (ref.current && windowScrollY === 0) {
ref.current.scrollTo(scrollOffset);
return;
}
if (ref.current && windowScrollY === document.body.scrollHeight) {
ref.current.scrollToItem(1000);
}
//타겟지점 + 스크롤 가능 범위 판별
if (ref.current && isScrollRender) {
//브라우저 스크롤이 움직이면 react-window의 List 엘리먼트 스크롤 내리기
ref.current.scrollTo(scrollOffset);
}
}, 10);
handleWindowScroll();
window.addEventListener("scroll", handleWindowScroll);
window.addEventListener("resize", handleWindowScroll);
return () => {
window.removeEventListener("scroll", handleWindowScroll);
window.removeEventListener("resize", handleWindowScroll);
};
}, []);
return { ref, outerRef, innerRef };
}
react-window
스크롤을 조작하기 위해 useRef
를 사용하여 react-window
DOM의 스크롤 위치를 탐색했습니다.scrollTo
함수를 활용하여 스크롤을 조정하고 scrollOffset
을 이용하여 양쪽 스크롤 높이 값의 오차를 보정했습니다react-window
콘텐츠를 조작했습니다.[성과]