프로젝트를 진행하면서 알게 된 무한스크롤을 되짚어보겠습니다.
정보를 한번에 가져와서 보여주기엔 정보량이 너무 많아서 API fetch로 받는 결과가 느릴 때, 스크롤을 통해서 아주 작은 일부분만 가져와서 추가로 보여주는 기술을 말합니다.
즉, Scroll End 지점까지 가면 다시 추가정보를 fetch를 계속해나가는 방식
페이지네이션과 비슷하기 때문에 자주 비교가 됩니다.
무한스크롤을 하는 방법은 크게 2가지가 있습니다.
scroll event
는 우리가 익히 사용했던 DOM scroll event
를 이용하는 것이기 때문에 익숙해서 상대적으로 구현은 쉽지만, 이 scroll event
에 throttle
혹은 rAF
로 최적화를 해줘야된다는 점이 있습니다.IntersectionObserver
는 익숙하지 않으면 익히는데 시간이 걸리기 때문에 상대적으로 어렵고, 페이지 마지막에 가시성 감지를 위한 target 요소를 만들어야되는 단점이 있습니다. Scroll Event에서 쓰이는 documentElement.scrollTop
과 documentElement.offsetHeight
는 reflow를 일으켜서 성능상 좋지 않다.
Scroll Event를 이용한 useInfiniteScroll Custom Hook 만들기
- Scroll Event를 최적화 하기전에, 커스텀훅으로 useInfiniteScroll
을 만들어 줘야 합니다.
설계 방식은 [isFetching, setIsFetching] = useInfiniteScroll(fetchCallback)
과 같은 방식으로 만들어서 custom Hook을 사용하는 곳에서 setIsFetching
을 통해서도 접근할 수 있게 하였습니다.
import { useState, useEffect } from "react";
export default function useInfiniteScroll(fetchCallback) {
const [isFetching, setIsFetching] = useState(false);
const handleScroll = () => {
if (window.innerHeight + document.documentElement.scrollTop >= document.documentElement.offsetHeight) {
setIsFetching(true);
}
}
useEffect(() => {
window.addEventListener('scroll', handleScrollThrottle);
return () => {
window.removeEventListener('scroll', handleScrollThrottle);
};
}, []);
useEffect(() => {
if (!isFetching) {
return;
}
fetchCallback();
}, [isFetching]);
return [isFetching, setIsFetching];
}
그리고 위와 같이 커스텀훅을 만들 경우 컴포넌트에서 아래와 같이 사용할 수 있습니다.
const [isFetching, setIsFetching] = useInfiniteScroll(updateFunctionOnScroll);
async function updateFunctionOnScroll() {
try {
const result = await fetchFunction();
setState(result);
} catch(error) {
setErrorState(error.message);
} finally {
setIsFetching(false);
}
}
useEffect(() => {
updateFunctionOnScroll();
}, []);
Infinite Scroll
장점
단점
Pagenation
장점
단점