본문으로 건너뛰기

자바스크립에서 이벤트 제어하기, 디바운싱과 쓰로틀링

프로젝트를 하다보면 모든 API 요청을 마구잡이로 보내서 과해지는 경우가 있습니다. 사용자에 입력에 대한 요청을 조절하여 수행할 수 있도록 어떻게 해야할까요? 왜 버튼은 여러번 클릭해도 한 번만 입력되는 건지, 검색 결과의 목록 표시는 어떻게 이뤄지는 건지. 프론트엔드 영역에서의 최적화, Debouncing과 Throttiling은 무엇이고 어떨 때 사용해야 하는 것인지 개념을 알아봤습니다.

Debouncing (디바운싱)

Debouncing은 사용자가 어떠한 이벤트를 몇 번이나 발생시키든 이벤트를 실행하지 않고 일정한 시간이 지난 뒤에 실행하도록 하는 방법입니다. 예를 들어 사용자가 '자바스크립트'를 검색하려고 합니다. 여기서 발생하는 이벤트는 '텍스트를 입력'하는 것이고, 입력한 텍스트에 대한 결과를 요청(query)하여 검색창 하단에 보여줄 것입니다. 하지만 입력 패턴을 보자면 'ㅈ > 자 > 자ㅂ > ... > 자바스크립트'의 순서로 API 요청을 하게 될겁니다. 이러한 과정은 모두 비용이 소모되므로 문제가 됩니다. 따라서 디바운싱은 위의 예시와 같이 연이어 발생하는 이벤트를 단일 이벤트로 만들어야 하는 기능(입력 이벤트의 검색 결과 표시, 자동 저장 기능 등)에 주로 사용됩니다.

let timer;

const debounce = (func, delay = 200) => {
return (...args) => {
if (timer) {
clearTimeout(timer);
timer = null;
}

timer = setTimeout(() => {
func(...args);
}, delay);
};
};

Throttling (쓰로틀링)

Debouncing이 특정한 시간 이후에 이벤트를 실행하는 방법이라면 Throttling은 사용자가 이벤트는 몇 번이나 발생시키든 일정한 시간을 간격으로 한번만 실행하는 방법입니다. 예를 들어 사용자가 다음 페이지로 넘어가려고 페이지네이션 버튼을 클릭했다고 가정해봅니다. 하필 이 때 네트워크 환경이 좋지 않아 화면은 계속 로딩 중이고, 사용자는 다음 페이지를 확인하려고 계속 버튼을 클릭합니다. 이 때 뭔가 복작한 작업이 실행되도록 설정했다면 클릭할 때마다 실행이 매우 빈번해지므로 엄청난 렉이 걸릴 것입니다. 이럴 때 Thottling 방법을 이용하여 일정 시간에 한 번씩만 실행되도록 제한을 두는 것입니다.

Debouncing과 다른 점이라면 반환하는 함수 안에서 timer에 대한 처리 과정입니다. Debouncing은 일정한 시간마다 실행하도록 한다면 Throttling은 최초에 요청을 수행하는 동안 다른 요청은 모두 무시한다는 차이가 있습니다.


let timer;

const throttle = (func, delay = 200) => {
return ((...args) => {
if (!timer) {
func(...args);

timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
}, delay);
}
}) as Fn;
}

알아보고나니

Debouncing과 Throttling을 가볍게 알아봤는데 여태 서비스들을 이용했을 때를 되돌아보니 정말 흔하게 사용되는 방법이었습니다. Debouncing은 주로 검색 API, Throttling은 스크롤 이벤트나 페이지네이션 등에도 사용될 수 있는 것 같아요. 이외에도 다른 어떠한 이벤트가 엄청나게 많은 요청을 요구할 수 있게 된다면 Throttling을 이용해 해당 요청에 대한 부담을 줄일 수 있을 것 같습니다. 더 나아가서 Throttling을 적용하고 끝내는 것이 아니라 이 때의 상황을 고려하여 화면을 설계할 수 있다면 사용자 경험에도 긍정적인 지표를 보여주지 않을까 생각합니다.

참고자료