본문 바로가기

기록/TIL

2023.08.22 - lodash로 편하게 Throttle 사용하기

무한스크롤을 구현했다. 

그러나 스크롤을 내릴때 호출이 너무 많이 되는걸 발견했다..

 

스크롤 전

 

스크롤 후

데이터를 한번 더 불러오는데 몇번이 호출되는지. 이를 막는 방법이 필요했고, 쓰로틀링과 디바운싱이 떠올랐다.

디바운싱은 이벤트를 모두 모아 마지막 이벤트에서 특정 시간이 지난 후 하나의 이벤트를 발생시키고, 쓰로틀링은 주기마다 이벤트를 모아 한번만 발생시킨다. 여기서는 쓰로틀링이 좋겠다고 판단했다.

 

직접 구현해보는 방법도 있겠으나, 내가 아는 방법은 setTimeOut의 방식으로 작동하기에 callstack의 상황에 따라 원하는대로 작동하지 않을 수 있다고 들었다. 그래서 lodash를 사용하기로 했다.

 

나는 yarn과 typescript를 사용중이므로 아래와 같이 작성하여 설치했다.

 

install

yarn add @types/lodash

 

그 후 lodash를 import하고

import { throttle } from 'lodash';

 

 

기존 코드를 throttle 내부에 넣어준다.

 

기존 코드

const ref = useIntersect(async (entry, observer) => {
    observer.unobserve(entry.target);
    if (isNextPage && !isFetching) {
      // 이전 offset에 size를 더하여 다음 페이지 데이터를 가져오도록 설정
      setOffset((prevOffset) => prevOffset! + size);
      refetch();
    }
  });

  useEffect(() => {
    if (data) {
      setIsNextPage(data.isNextPage);
      // 새로운 데이터를 현재 데이터 뒤에 추가
      setList((prevList) => [...prevList, ...data.list]);
    }
  }, [data]);

 

 

throttle이 적용된 코드

 const throttledLoadMore = throttle(() => {
    if (isNextPage && !isFetching) {
      // 이전 offset에 size를 더하여 다음 페이지 데이터를 가져오도록 설정
      setOffset((prevOffset) => prevOffset! + size);
      refetch();
    }
  }, 1000); // 1초에 한 번만 호출되도록 설정

  const ref = useIntersect(async (entry, observer) => {
    observer.unobserve(entry.target);
    throttledLoadMore();
  });

  useEffect(() => {
    if (data) {
      setIsNextPage(data.isNextPage);
      // 새로운 데이터를 현재 데이터 뒤에 추가
      setAnimeList((prevList) => [...prevList, ...data.list]);
    }
  }, [data]);

 

 

결과

아직 많다고 생각이 들지만.. 기존과 비교하면 정말 적다. 근데 왜 호출이 두번이지..? 이건 나중에 확인해야겠다.

 

 

23. 08. 23 > lodash의 throttle을 사용할 때 time을 주게 되면 setTimeOut의 방식으로 작동한다는 소문을 들었다. 조금 더 찾아보고 수정이 필요하다면 수정해야겠다.