본문으로 바로가기

 

[이벤트 핸들러를 효율적으로 처리해야 하는 이유]

input 태그 같은 곳에서 값을 입력할 때마다 이벤트 핸들러에 비즈니스 로직 혹은 API가 포함된 로직이 호출하게 되면 비용적인 문제도 발생하고, 유료 API 같은 경우 호출할 때마다 비용이 발생하게 됩니다. 간단한 예제를 통해 이벤트 핸들러가 보통 어떻게 호출되는지 확인해 보겠습니다.

export default function App() {
  const onChange = e => {
    console.log(e.target.value);
  }

  return <input type="text" onChange={e => onChange(e)} />;
}

 

'안녕하세요'를 입력하면 'ㅇ', '아', '안', '안ㄴ', '안녀', '안녕' ... 입력할 때마다 불필요하게 이벤트가 실행되는 것을 확인할 수 있습니다.

 
이렇게 연속해서 호출되는 핸들러는 과도하게 호출되어 성능에 문제가 올 수 있습니다. 따라서 Debounce, Throttle을 통해 핸들러를 다룰 필요가 있습니다. 이번 글에서는 Debounce와 Throttle에 대해 알아보겠습니다.

 


[Debounce]

Debounce는 특정 이벤트가 발생할 때 작동하는 비즈니스 로직이 과도하게 작동하는 것을 방지하기 위해 발생하는 방식입니다. 즉, 연이어 호출되는 함수들 중 가장 마지막(처음) 함수만 호출하도록 하는 것입니다. 아무리 많은 이벤트를 발생시키려해도 딱 한 번만 마지막(처음) 이벤트를 발생시킵니다.
 
Debounce는 그리 어렵지 않게 간단하게 구현이 가능합니다. 간단한 예제를 통해 확인해 보도록 하겠습니다.

import { useState, useEffect } from "react";

const useDebounce = <T>(value: T, delay: number) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

export default useDebounce;

 
'안녕하세요'를 입력하면 불필요하게 이벤트가 실행되지 않고 마지막에 한 번만 이벤트가 호출되는 것을 확인할 수 있습니다.

 
Debounce와 Throttle을 사용하면 클라이언트와 서버에서 불필요한 함수와 API를 호출하지 않아 리소스와 비용면에서 절약이 가능합니다. 이러한 이점들로 인하여 사용자에게 좀 더 부드러운 서비스를 제공할 수 있습니다. Debounce는 실무에서 주로 API를 요청하는 로직들 자동완성, 버튼 중복 클릭 방지 등에 사용되고 Throttle에서는 무한 스크롤을 구현할 때 자주 사용됩니다.
 


[Throttle]

Throttle이란 이벤트 발생 즉시 실행되고 지정한 시간동안 이벤트를 발생하지 못하도록 막는 것입니다. 즉, 함수가 주어진 시간동안에 한 번 이상 호출되는 것을 막아주는 것을 말합니다.
 
Throttle도 Debounce와 마찬가지로 lodash에서 제공하는 Throttle을 통해 간단하게 구현이 가능합니다. 간단한 예제를 통해 확인해 보도록 하겠습니다.

export default function App() {
  const throttle = _.throttle((e) => {
    console.log(e.target.value);
  }, 2000);
  return <input type="text" onChange={(e) => throttle(e)} />;
}

 
'안녕하세요'를 입력하면 지정한 시간(2초) 동안 이벤트가 호출되지 않고 입력하고 2초가 지나서 그 이후에 이벤트가 실행되는 것을 확인할 수 있습니다.

 
 
References
자바스크립트 딥다이브
https://ko.reactjs.org/docs/faq-functions.html