React 무한 스크롤 (라이브러리 없이)

기멜·2021년 12월 12일
3

React

목록 보기
15/24

프로젝트를 진행하면서 알게 된 무한스크롤을 되짚어보겠습니다.

무한스크롤이란?

정보를 한번에 가져와서 보여주기엔 정보량이 너무 많아서 API fetch로 받는 결과가 느릴 때, 스크롤을 통해서 아주 작은 일부분만 가져와서 추가로 보여주는 기술을 말합니다.
즉, Scroll End 지점까지 가면 다시 추가정보를 fetch를 계속해나가는 방식
페이지네이션과 비슷하기 때문에 자주 비교가 됩니다.

무한스크롤 적용하는 두 가지의 방법

무한스크롤을 하는 방법은 크게 2가지가 있습니다.

  • scroll event
  • IntersectionObserver
    scroll event는 우리가 익히 사용했던 DOM scroll event를 이용하는 것이기 때문에 익숙해서 상대적으로 구현은 쉽지만, 이 scroll eventthrottle 혹은 rAF로 최적화를 해줘야된다는 점이 있습니다.
    IntersectionObserver는 익숙하지 않으면 익히는데 시간이 걸리기 때문에 상대적으로 어렵고, 페이지 마지막에 가시성 감지를 위한 target 요소를 만들어야되는 단점이 있습니다.

Scroll Event에서 쓰이는 documentElement.scrollTopdocumentElement.offsetHeight는 reflow를 일으켜서 성능상 좋지 않다.

Scroll Event

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];
}
  • window.innerHeight는 지금 화면으로 보이는 윈도우의 높이
  • document.documentElement.scrollTop은 현재 화면이 어느 화면의 어느 좌표를 보고있는지를 알려주는 top 좌표 (얼마만큼 스크롤했느냐로 생각하면 된다)
  • document.documentElement.offsetHeight는 스크롤을 포함한 전체 페이지 길이이다.

그리고 위와 같이 커스텀훅을 만들 경우 컴포넌트에서 아래와 같이 사용할 수 있습니다.

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 VS Pagenation

Infinite Scroll

장점

  • 사용자 참여 및 콘텐츠 탐색이 쉽다.
  • 클릭하는 것보다 더 나은 사용자 경험을 제공한다.
  • 모바일에 적합하다

단점

  • 스크롤을 해서 가져오는 정보가 많아질 수록 페이지 성능이 느려진다.
  • 정보 탐색이 힘들다. (특정 항목, 첫 위치로 돌아오기가 힘듦)
  • 스크롤 막대로 정확한 정보량을 알 수 없다. (끝에 도달하면 새로 갱신되기 때문에 언제 끝날지 모름)
  • 푸터를 찾기 힘들다.

Pagenation

장점

  • 사용자 의도에 맞게 페이지를 넘길 수 있다.
  • 사용자가 페이지에 통제감을 느낄 수 있다.
  • 특정 항목의 위치를 파악 및 찾기가 쉽다.

단점

  • ‘클릭’ 혹은 ‘다음페이지’를 클릭해야되는 번거로움이 있다.
  • 한페이지에서 매우 제한된 내용을 본다.
profile
프론트엔드 개발자를 꿈꾸는 도화지 위를 달리는 여자

0개의 댓글