전체 개발 회의에서 리뷰 기능의 페이지네이션을 무한스크롤로 구현해보자는 의견이 나왔다.
아래를 보면 기존에는 오프셋 방식으로 페이지네이션을 했다.
백엔드 측에서 새로운 스타일의 페이지네이션을 제안했고, 무한 스크롤을 이용해서 페이지네이션을 구현하기로 결정했다.
스크롤을 이용한 페이지네이션의 이유에는 사용자에게 더욱 편리한 경험을 전달하기 위함이다.
오프셋 방식은 휴대폰이나 컴퓨터로 웹 페이지에 접속했을 때, 원하는 숫자 버튼을 찾아서 클릭해야하는 번거로움을 준다.
오프셋 방식의 장점은 원하는 데이터가 있는 공간으로 빠르게 이동할 수 있다는 것 같다. 하지만 리뷰를 확인하는데 오프셋 방식이 주는 이점은 없다고 생각했고, 추후에 필터링 기능을 추가하여 충분히 보완할 수 있다고 생각한다.
서칭을 통해 intersection Observer API 라는 걸 알게 됐다.
감시하고자 하는 요소가 다른 요소(viewport)에 들어가거나 나갈 때 또는 요청한 부분만큼 두 요소의 교차부분이 변경될 때 마다 실행될 콜백 함수를 등록할 수 있게 합니다.
이해한 바, 간단하게 3가지 순서로 나뉜다.
...
const observeReviewList = useRef(null);
...
observeReviewList 라는 target 을 Ref 로 생성했다.
그 후, 감지하고 싶은 tag 에 Ref 를 부여했다.
return (
<>
<div className="tabs">
...
</div>
<div ref={observeReviewList} />
</>
);
callback 을 위한 fetch 함수를 만들었다.
const fetch = useCallback(async () => {
try {
...
).then(res => {
...
});
if (hasNextPage) {
page.current += 1;
}
} catch (err) {
console.error(err);
}
}, []);
useEffect(() => {
...
const io = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
fetch();
}
});
io.observe(observeReviewList.current);
}, [fetch, hasNextPage]);
IntersectionObserver
를 생성하고 observe
를 사용해서 감지할 부분을 매개변수로 대입했다.
아래 코드가 생성부 및 감지할 대상 선정.
const io = new IntersectionObserver
...
io.observe(observeReviewList.current);
생성 후 감지했을 때 실행할 fetch()
함수를 넣었다.
entries => {}
안에 isIntersecting
라는 옵션이 있다.
해당 옵션은 entries[0]
를 감지했을 때 true
또는 false
를 반환한다.
true
일 때 fetch()
를 실행하도록 구성했다.
키보드로 스크롤을 내리고 있다.
오른쪽에 스크롤을 보면 <div ref={observeReviewList} />
, 즉 맨 밑을 감지하고 추가 데이터를 가져오는 callback 함수인 fetch 를 실행하는 것을 확인할 수 있다.
IntersectionObserver
에 관한 자료
isIntersecting
에 관한 자료
구현에 참고했던 블로그
오프셋과 스크롤 페이지네이션에 관한 자료
구글링 짱이다. 그리고 공식 문서를 꼭 참고하자. 처음에 공식 문서를 봤을 때 이해가 안됐다. 그래서 블로그를 봤다. 실제 개발자가 어떻게 구현했는지 블로그를 통해 간접 경험하고 공식 문서를 다시 읽어봤다. 이해가 훨씬 쉽게 됐다.
공식 문서 -> 블로그 -> 공식 문서
이 방식이 적절한 방식인지 알 수 없지만, 앞으로 개발 공부를 하며 나에게 맞는 방법을 찾아보자.