[TIL_Javascript_21.01.05] Debouncing & Throttling

Prologue

현재 진행중인 프로젝트 고도화 작업에서 끊임없이 실행되는 스크롤 이벤트 함수들을 좀 더 효율적으로 사용할 수 있는 방법을 찾다가 발견한 Javascript 개념이다. 스크롤 이벤트가 매 스크롤마다 실행된다면 웹/앱 성능적으로 큰 문제가 될 수 있다고 판단했다.

1. Debouncing

유저가 검색창에서 검색어를 치자마자 엔터나 클릭 이벤트 없이 결과가 바로 나오는 서비스들이 있다. 이러한 결과를 유도하기 위해서는 input 이벤트를 상시 대기하고 있어야한다. 이를 콘솔로 찍어본다면 더욱 확실하게 이해할 수 있다.

Javascript가 단일 스레드 언어이므로 이러한 메소드를 자주 호출하면 브라우저 성능에 큰 영향을 줄 수 있다. 디바운싱은 시간이 많이 걸리는 작업이 자주 발생하지 않도록 조절하며, 웹 페이지의 성능 저하를 막는 프로그래밍 방식이다. 즉, 함수 호출 속도를 제한한다.

특정 시간(인터벌) 내에 이벤트 발생이 없으면 로직이 실행된다.

document.querySelector(#input).addEventListener('input', function(e) {
	console.log('리소스 낭비중', e.target.value)
}

연결된 input 엘리먼트에 값을 입력할때마다 클릭 이벤트가 발생하고 예를 들면 아래의 사진과 같이 설명할 수 있다.

  • 디바운싱 적용 후
var timer;
document.querySelector('#input').addEventListener('input', function(e) {
  if (timer) {
    clearTimeout(timer);
  }
  timer = setTimeout(function() {
    console.log('여기에 ajax 요청', e.target.value);
  }, 200);
});

주로 사람들은 검색을 할 때는, 빠른 시간 내에 단어를 완성한다. 따라서, 유저가 0.5초동안 입력이 없을 때, 비로소 이벤트가 실행된다. 즉, 0.5초 내에 이벤트가 발생하지 않을 때, 마지막 이벤트 로직을 실행한다.

그렇다면 우리의 Angular의 ngModel은 디바운싱에 어떻게 대처하고있나?
Angular의 ngModel은 ngModelOption 지시자를 사용해서 debounce를 설정할 수 있다.

<div class="form-group">
   <label>아이디</label>
   <!-- ng-model-options 는 옵션객체로 계산되는 표현식이 올 수 있다. -->
   <input type="text" class="form-control" name="inputId" ng-model="member.id" 
       ng-model-options="{debounce : 1000}">
</div>

2.Throttling

유저가 서비스를 이용하는 과정에서 스크롤 이벤트를 사용하면 실시간으로 한 번의 스크롤 마다 이벤트가 발생한다. 스크롤 이벤트가 복잡한 작업의 로직이라면 성능적인 관점에서 좋지 않다. 이러한 문제를 해결하기 위해 쓰로틀링을 사용한다.

쓰로틀링은 매 밀리 초마다 또는 특정 시간 간격 후에 첫 번째 이벤트만 즉시 실행되는 함수를 호출하는 데 사용된다. 디바운싱과 함께 퍼포먼스 이슈를 해결하기 위한 방법 중 하나이다.

쓰로틀링은 이벤트리스너가 반응해도 최소한은 특정 시간동안 로직을 주기적으로 1회만 실행한다. 즉, 최초 이벤트가 발생하고 지정한 시간동안 발생하는 이벤트가 무시된다.

const throttle = () => {
  setTimeout(function() {
    scrollEvent();
  }, 200);
}

window.addEventListener('scroll',this.throttle, true);

좋은 웹페이지 즐겨찾기