최근에 React Query 강의를 수강하고 있는데, React Query로 무한스크롤(Infinite Scroll)을 편리하기 구현할 수 있다고 한다. 마침 팀프로젝트에서 무한 스크롤을 구현하고 싶었는데 다른 기능을 우선적으로 구현하느라 미뤄두었던 게 기억나서 무한스크롤을 연습해야겠다고 생각했다.
React Query에서 구현하기 전에, 일반적인 방법인 Intersection Observer API로 구현하는 방법을 먼저 알면 좋을 것 같다. 실제로도 많이 활용되는 방법이기도 하고, 직접 사용해보면서 다른 방법과의 차이를 체감하기 좋은 기회라고 생각한다.
window.addEventListener('scroll', function() {
return console.log('scroll!');
});
쓰로틀을 보기 전에 디바운스를 간단하게 알고 넘어가보자. 디바운스는 연속해서 이벤트가 발생하면 일정 시간 이후 한 번만 이벤트를 호출하는 기법이다.
예를 들어 3초의 시간 간격을 주어 3초 안에 이벤트가 계속해서 발생하면 이벤트 핸들러 즉 콜백 함수를 실행하지 않고 있다가, 3초가 지나도 이벤트가 발생하지 않으면 이벤트가 완료되었다고 판단하여 마지막에 실행된 이벤트를 발생시켜 이벤트 핸들러를 한 번 호출하는 것이다.
디바운스는 어떤 경우에 사용할 수 있을까? 바로 input 이벤트가 발생하는 입력창이다. 예를 들어 사용자가 입력창에 사용자 정보를 입력하면 input 이벤트는 입력될 때마다 발생한다. 만약 해당 입력값으로 Ajax 요청을 보내는 로직이 있다면, 작성이 미처 완료되지 않은 입력을 가지고도 요청을 보내게 되어 불필요한 요청이 발생한다.
따라서 디바운스는 대기 시간을 걸어, 대기 시간 이후로 입력이 발생하지 않으면 입력이 완료되었다고 보고 이벤트 핸들러를 한 번 호출함으로써 이벤트 호출을 최적화한다.
💡 이벤트가 발생한 지 3초가 지났을 때 실행하는 것(디바운스)과, 3초마다 실행하는 것(쓰로틀)은 다른 개념이다. 헷갈리지 않도록 주의하자!
디바운스와 쓰로틀에 대해 알아본 이후, 쓰로틀이라는 기법이 있는데도 불구하고 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 | MDN
디바운스(Debounce)와 스로틀(Throttle ) 그리고 차이점
모던 자바스크립트 Deep Dive - 41장. 디바운스 / 스로틀