디바운싱(Debouncing) / 쓰로틀링(Throttling)

이다현·2024년 6월 27일

📌 문제점

날씨 프로그램을 제작 중 useEffect안에 axios로 비동기 데이터를 불러와 input[type=text]에 onChange 이벤트를 걸었으나, 'london'이라는 text를 모두 작성하기도 전에 페이지에 인식되는 문제가 발생했다.

-> london을 다 작성하기도 전에 lon이 먼저 나오는 상황

이 때 'Debouncing'이라는 방식을 알게 되었고 useEffect안에 적용시켜보았다.

✔️ 적용 전

useEffect(() => {
 // 빈값일 시 API 호출을 하지 않음
    if (!city) return;
  // API를 호출하여 날씨 데이터를 가져오는 함수
  const getWeatherData = () => {
    const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=키값&units=metric`;
    axios
      .get(url)
      .then((res) => {
        const data = res.data;
        setWeatherData([
          {
            city: data.name,
            country: data.sys.country,
            temp: data.main.temp,
            imgCode: data.weather[0].icon,
            loading: false,
          },
        ]);
      })
      .catch((error) => {
        console.error("Error fetching weather data: ", error);
      });
  };
    getWeatherData();
  }, [city]);

✔️ 적용 후

  useEffect(() => {
    // 빈값일 시 API 호출을 하지 않음
    if (!city) return;
    const debounceTimer = setTimeout(() => {
      // API를 호출하여 날씨 데이터를 가져오는 함수
      const getWeatherData = () => {
        const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=키값&units=metric`;
        axios
          .get(url)
          .then((res) => {
            const data = res.data;
            setWeatherData([
              ...weatherData,
              {
                city: data.name,
                country: data.sys.country,
                temp: data.main.temp,
                imgCode: data.weather[0].icon,
                loading: false,
              },
            ]);
          })
          .catch((error) => {
            console.error("Error fetching weather data: ", error);
          });
      };
      getWeatherData();
      return () => clearTimeout(debounceTimer);
    }, 1000);
  }, [city]);

Debounce와 setTimeout을 걸어주어, 이벤트 발생 후 1초 뒤의 마지막 결과값을 가져오도록 하니 결과가 london 데이터만 잘 나왔다.

📌 디바운싱(Debouncing)이란?

연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출하도록 하는 것

✔️ 디바운싱(Debouncing) 언제 사용할까?

  • 주로 이벤트 핸들러가 너무 자주 호출되는 것을 방지하고자 할 때
  • 연속적으로 발생한 이벤트를 하나로 처리하는 방식일 때
  • 키워드 검색 혹은 자동완성 기능에서 api 함수 호출 횟수를 최대한 줄이고 싶을때


    예를 들어, 검색을 통해 API를 가져오는 경우 '화이팅'를 검색창에 친다고 했을 때, 일반적으로 각 글자를 입력할 때마다 API를 요청하게 된다.

이 경우 서버에 너무 많은 HTTP 요청이 들어가게 되면서 서버 자원의 부담으로 이어지기 쉽고 쿼리 하나 하나가 다 돈이기 때문에 비용적인 문제와도 관련이 있는 상황이 된다.

이때 위 예시 코드처럼 setTimeout과 함께 타이머를 걸어주어 사용하면, 특정 시간동안 딱한번만 함수가 실행되도록 코드를 작성할 수 있다.

즉, 사용자가 타자를 치는동안은 함수를 호출을 무시하고 1초 동안 입력이 없으면 입력을 끝난 것으로 간주하고 함수를 실행하는 것이다.👍🏻

혹시나 반복적으로 코드가 계속 돌 수 있기 때문에 clearTimeout로 cleanup 해줘야함

return () => clearTimeout(debounceTimer);

디바운싱을 공부하던 중 비슷한 방식으로 쓰로틀링, Throttling을 알게 되었다.

📌 쓰로틀링(Throttling)

일정 시간 동안 특정 이벤트가 연속해서 발생하더라도, 주어진 시간 내에서 최대 한 번의 이벤트만 실행되도록 하는 기술

  • 예를 들어 setTimeout으로 1초의 시간을 걸어준다면 이벤트는 1초동안 동안 최대 한번만 발생하게 됨
  • 즉 마지막 함수가 호출된 후 일정시간이 지나기 전에 다시 호출되지 않도록함
    일정 시간동안 딱 한번만 이벤트를 발생시킴!!

📌 디바운싱과 쓰로틀링의 차이점

다른 블로그를 통해 공부하던 중 이해가 가장 잘 되는 그림을 발견해 가져오게 되었다.
(출처 : https://velog.io/@kskim625/%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81)

✔️ 쓰로틀링
👉 연이어 호출되는 함수들 중에서 첫 번째 함수만을 호출하여 주어진 시간동안 후속 이벤트를 무시하는 것

✔️ 디바운싱
👉 연이어 호출되는 함수들 중에서 이전 이벤트를 무시하고 마지막 함수만을 호출하는 것

보통 쓰로틀링은 스크롤에 많이 사용한다는데, 나중에 사용해 볼 기회가 있었음 좋겠다!!👍🏻

profile
프론트엔드 코딩공부 페이지입니다.

0개의 댓글