-
Notifications
You must be signed in to change notification settings - Fork 5
쓰로틀링과_디바운싱
- 쓰로틀링: 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것. 주로 ajax검색에 자주 쓰인다.
- 디바운싱: 연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출하도록 하는 것. 스크롤 기능에 자주 사용한다.
최근의 서비스에서 검색어를 치자마자 엔터 없이도 결과가 바로 나오는 것을 확인할 수 있다.
만약 '부스트캠프'를 검색창에 친다고 해보자. 엔터 없이도 결과를 즉시 보여주려면 항상 input 이벤트에 대기하고 있어야 한다.
<input id="input" />
document.querySelector('#input').addEventListener('input', function(e) {
console.log('여기에 ajax 요청', e.target.value);
});
(ajax대신에 콘솔로 대체)
로그가 콘솔에 찍힐 때마다 ajax 요청이 실행된다고 생각하면 된다. 문제는 한 글자 칠 때마다 ajax 요청이 실행된다는 것.
('ㅈ', '제', '젤', '제로', '제롳', '제로초' 모두 요청이 실행되는데 'ㅈ', '젤', '제롳'는 제대로 된 검색 결과가 나오지 않을 것 같은 검색어)
이와 같은 낭비는 유료 API를 사용했을 때 큰 문제가 된다. 만약 구글지도 API같은 것을 사용할 때 위와 같이 쿼리를 10번 날리면 어마어마한 손해이다. (쿼리 하나가 다 비용과 연결되므로!) 따라서 디바운싱은 비용적인 문제와도 관련이 있다. 우리는 마지막 '제로초'를 다 쳤을 때 ajax 요청을 보내고 싶다.
먼저 어떻게 구현할지 생각해보자. 보통 사람들은 타자를 연달아친다. 중간에 잠시 생각하느라 몇 초 쉴 수는 있겠지만 대부분 한번에 검색어를 입력한다.
따라서 입력이 다 끝난 후에 요청을 보내면 된다.
즉, 타자를 칠 때(input 이벤트 발생)마다 타이머를 설정해서, 200ms동안 입력이 없으면 입력이 끝난 것으로 간주한다.
200ms 이전에 타자 입력이 발생하면 이전 타이머는 취소하고 새로운 타이머를 다시 설정하는 것.
var timer;
document.querySelector('#input').addEventListener('input', function(e) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function() {
console.log('여기에 ajax 요청', e.target.value);
}, 200);
});
이제 더는 여러 번 호출되지 않는다. 이게 바로 디바운싱. (한글 특성상 마지막에 두 번 호출되는 경우도 있다)
쓰로틀링은 보통 성능 문제 때문에 많이 사용한다.
특성 자체가 실행 횟수에 제한을 거는 것이기도 하다.
스크롤을 올리거나 내릴 때 scroll 이벤트가 매우 많이 발생한다. scroll 이벤트가 발생할 때 뭔가 복잡한 작업을 하도록 설정했다면
매우 빈번하게 실행되기 때문에 엄청난 부하가 걸릴 것. 그럴 때 쓰로틀링을 걸어주면 된다.
몇 초에 한 번, 또는 몇 밀리초에 한 번씩만 실행되게 제한을 두는 것.
(+) 디바운싱으로 구현했던 ajax 검색을 쓰로틀링으로 대체할 수도 있다. 200ms로 타이머를 설정하고, 해당 시간 이후에 ajax 요청을 날리게 하면 된다.
var timer;
document.querySelector('#input').addEventListener('input', function (e) {
if (!timer) {
timer = setTimeout(function() {
timer = null;
console.log('여기에 ajax 요청', e.target.value);
}, 200);
}
});
이제 최소 200ms마다 요청을 보낸다. 물론 ajax 검색은 디바운싱으로 처리하는 것을 더 추천한다.
하지만 중간 중간 검색 결과도 보여주고 싶다면 쓰로틀링도 괜찮은 옵션일 것.
물론 매우 빠르게 구현한 것이기 때문에 위의 코드로는 예외 사항들을 처리하지 못 할 수도 있으니 주의하자.
(그럴땐 underscore의 _.debounce
와 _.throttle
을 추천함)