디바운스, 쓰로틀, 그리고 Intersection Observer API

Daisy🌼·2022년 12월 19일
0

학습 계기

  • 최근에 React Query 강의를 수강하고 있는데, React Query로 무한스크롤(Infinite Scroll)을 편리하기 구현할 수 있다고 한다. 마침 팀프로젝트에서 무한 스크롤을 구현하고 싶었는데 다른 기능을 우선적으로 구현하느라 미뤄두었던 게 기억나서 무한스크롤을 연습해야겠다고 생각했다.

  • React Query에서 구현하기 전에, 일반적인 방법인 Intersection Observer API로 구현하는 방법을 먼저 알면 좋을 것 같다. 실제로도 많이 활용되는 방법이기도 하고, 직접 사용해보면서 다른 방법과의 차이를 체감하기 좋은 기회라고 생각한다.

스크롤 이벤트의 문제

  • 자바스크립트에는 기본적으로 사용자의 스크롤 동작에 따라 어떠한 일을 수행하고 싶을 때 사용하는 scroll 이벤트가 있다. 하지만 이 스크롤 이벤트는 아주 빠른 속도로 실행된다. 마우스 스크롤을 살짝만 내려도 스크롤 이벤트에 대한 콜백 함수는 수십 번 실행되는 걸 확인해볼 수 있다.
window.addEventListener('scroll', function() {
   return console.log('scroll!');
});

  • 따라서 스크롤 이벤트에 대한 콜백함수가 과도하게 호출되면 메인 스레드에 부담을 주게 되고, 결국 성능 저하의 문제가 발생할 수 있다. (스크롤 뿐만 아니라 resize, input, onmousemove와 같은 이벤트도 과도하게 콜백을 호출할 수 있는 이벤트다.)

이벤트 제어하기

  • 그렇다면 이러한 스크롤 이벤트를 제어해서 최적화를 하는 방법은 없을까? 이벤트 핸들러(콜백 함수)를 제어하는 기법으로는 디바운스와 쓰로틀이 있는데, 스크롤 이벤트에서는 주로 쓰로틀 기법을 사용해 이벤트 핸들러를 제어한다.

✨ 디바운스

  • 쓰로틀을 보기 전에 디바운스를 간단하게 알고 넘어가보자. 디바운스는 연속해서 이벤트가 발생하면 일정 시간 이후 한 번만 이벤트를 호출하는 기법이다.

  • 예를 들어 3초의 시간 간격을 주어 3초 안에 이벤트가 계속해서 발생하면 이벤트 핸들러 즉 콜백 함수를 실행하지 않고 있다가, 3초가 지나도 이벤트가 발생하지 않으면 이벤트가 완료되었다고 판단하여 마지막에 실행된 이벤트를 발생시켜 이벤트 핸들러를 한 번 호출하는 것이다.

  • 디바운스는 어떤 경우에 사용할 수 있을까? 바로 input 이벤트가 발생하는 입력창이다. 예를 들어 사용자가 입력창에 사용자 정보를 입력하면 input 이벤트는 입력될 때마다 발생한다. 만약 해당 입력값으로 Ajax 요청을 보내는 로직이 있다면, 작성이 미처 완료되지 않은 입력을 가지고도 요청을 보내게 되어 불필요한 요청이 발생한다.

  • 따라서 디바운스는 대기 시간을 걸어, 대기 시간 이후로 입력이 발생하지 않으면 입력이 완료되었다고 보고 이벤트 핸들러를 한 번 호출함으로써 이벤트 호출을 최적화한다.

✨ 쓰로틀

  • 디바운스는 대기 시간이라면 쓰로틀은 주기, 간격이라고 할 수 있다. 즉 몇 초에 한 번, 몇 밀리 초에 한 번 이벤트 핸들러를 호출하는 것이다.

💡 이벤트가 발생한 지 3초가 지났을 때 실행하는 것(디바운스)과, 3초마다 실행하는 것(쓰로틀)은 다른 개념이다. 헷갈리지 않도록 주의하자!

  • 쓰로틀은 주로 스크롤 이벤트를 처리할 때 유용하게 사용된다. 예를 들어 무한 스크롤을 구현하기 위해서는 스크롤의 끝에 닿았을 때(페이지의 바닥에 닿았을 때) 데이터를 요청해야 한다. 만약 스크롤 이벤트가 발생할 때마다 요청을 하게 되면 과도한 요청이 처리될 것이다. 따라서 일정 시간 간격을 두어 데이터를 요청한다면 그나마(?) 요청을 줄일 수 있어 성능 면에서는 유리할 것 같다.

Intersection Observer API를 쓰는 이유?

  • 디바운스와 쓰로틀에 대해 알아본 이후, 쓰로틀이라는 기법이 있는데도 불구하고 Intersection Observer API를 쓰는 이유가 궁금해졌다. 그러던 중 성능을 직접 비교한 글을 찾을 수 있었다. (Scroll listener vs Intersection Observers: a performance comparison)

  • 위의 자료에서는 쓰로틀을 이용한 스크롤 이벤트와 Intersection Observer API를 사용했을 때의 성능을 비교하고 있다. 결과적으로 Intersection Observer API를 이용하는 것이 메인 스레드에 부담을 덜 준다는 것을 알 수 있다.

  • Intersection Observer API는 브라우저가 제공하는 Web API로, 뷰포트와 요소를 감지하는 역할을 메인 스레드가 아닌 브라우저가 담당하기 때문에 메인 스레드의 부담이 적은 이유가 아닐까 생각한다.

결론

  • 디바운스와 쓰로틀은 인풋, 스크롤 이벤트 뿐만 아니라 연속적으로 빈번하게 발생하는 이벤트를 효과적으로 제어할 때 사용할 수 있는 프로그래밍 기법이다. 개념을 알고 있으면 현업에서 비슷한 문제가 생겼을 때 이런 방법을 떠올릴 수 있을 것 같다.

  • Intersection Observer API는 쓰로틀을 사용한 스크롤 이벤트 처리보다 성능상 좋은 Web API이다. 특히 무한 스크롤을 구현할 때 자주 사용된다.


참고자료

Intersection Observer API - Web API | MDN

디바운스(Debounce)와 스로틀(Throttle ) 그리고 차이점

모던 자바스크립트 Deep Dive - 41장. 디바운스 / 스로틀

profile
커피와 재즈를 좋아하는 코린이 | 좋은 글 좋은 코드를 쓰고 싶습니다

0개의 댓글