Throttling과 Debouncing에 대해서 아시나요 / 네?

Grace·2021년 8월 27일
3
post-thumbnail

면접을 통해 많이 배운다는걸 느꼈던 n회차 면접..
내가 모르는 개념들을 정말 많이도 물어봐주셨다.
감사한것은 그저 질문에서 끝나는게 아니라 본인이 아시는 정도,
이해한 정도에 대해서도 설명해주시곤 하셨다.
내가 js에서 어떤부분이 부족하고, 더 채워야 하는지 알게된 시간.
그래서 더 잘 정리해두어야겠다는 생각에 정리해보는 새로운 두가지의 개념!


이벤트 오버클럭(overclock-과도한 이벤트 발생)은
리소스 사용량을 증가시키기 때문에 성능문제를 야기하고, 사용자 경험을 떨어뜨린다.
예를 들어 스크롤 이벤트의 경우, 스크롤을 빨리 내리게 되면
3초 간격 내에 몇 천번 이상의 이벤트가 발생하게 되기 때문에
성능에 문제가 생기게 된다.

과도한 이벤트나 함수들의 빈도수를 줄여서 성능을 향상시키는 프로그래밍 기법 중,
자주 언급되는 두가지를 알아보자.

Throttling(쓰로틀링)

마지막 함수가 호출된 후 일정시간이 지나기 전에 다시 호출되지 않게 하는 것
= 여러번 실행되는 이벤트를 일정시간 동안 한번만 실행되게 하는 것

위 이미지를 보면 점선으로 된 박스 안에 이벤트가 발생한 순서대로 묶여있고
8번의 이벤트 중에 실제 실행된 것은 1️⃣, 4️⃣, 7️⃣, 8️⃣ 뿐이다.
점선으로 표시된 박스는 정해둔 시간의 간격을 표시하고,
그 정해둔 시간의 가장 마지막에 호출된 이벤트를 발생시키는 기법이 쓰로틀링이다.
실행 횟수에 제한을 걸어두는 것이 특징이다.

코드로 예를 들어보자

이은지를 검색창에 친다고 가정했을 때,
엔터를 치지 않고도 자동완성 기능을 보여주려면
항상 input 이벤트에 대기하고 있어야 한다.

로그가 콘솔에 찍힐때마다 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 요청을 날리게 된다.

이런 특성 탓에 스크롤 이벤트 발생 시 다른 작업을 설정시킬 때에
자주 사용되곤 하는 기법이다.

Debouncing(디바운싱)

약간 통통 튀는 이미지로 생각하기, 정해놓은 간격 없이 여러번 실행되는 것

계속 호출되는 함수들 중 제일 마지막 함수만 호출되게 하는 것
= 가장 최신으로 실행된 이벤트를 실행되게 하는 것

쓰로틀링과 달리 위 이미지에서는 1️⃣,7️⃣,8️⃣ 이벤트만이 실행된 것을
볼 수 있는데, 정해둔 delay time 보다 짧은 시간 내에 이벤트가 발생된 경우에는 실행되지 않고 delay time을 지나면 실행이 되는 것이다.

코드로 예를 들어보자

위 쓰로틀링 예제에서 생기는 문제들을 해결하기 위해,
이름을 다 입력했을 때에만 요청을 하기 위해서는 아래와 같은 코드가 필요하다.

var timer;
document.querySelector('#input').addEventListener('input', function(e) {
  if(timer) {
    clearTimeout(timer); // 타자 입력으로 이전 타이머 취소 
  }
  timer = setTimeout(function() { // 새로운 타이머 설정
    console.log('여기에 ajax 요청', e.target.value);
  }, 200);
});

이렇게 하게 되면 실제로 콘솔에는

중간에 머뭇거리지만 않는다면, 모든 입력이 끝난 후에 200ms동안
아무 이벤트가 일어나지 않으면 콘솔에 찍히게 된다.

이런 특성탓에 주로 ajax로 처리되는 입력에 따른 자동완성/연관검색어
노출시킬 때 사용하곤 한다.


이렇게 직접 코드를 작성할 수도 있지만
lodashunderscore와 같은 라이브러리에서도
내장함수로 구현되어 있기 때문에, 이를 이용하면
간편하게 함수 호출만으로도 동일한 기능을 수행할 수 있다.

📌 참고하였습니다 :)

profile
쉽게 사는건 재미가 없더군요, 새로 시작합니다🤓

0개의 댓글