SNS 등에서 많이 사용하는 infinity scroll 등에서 스크롤이 끝에 도달 했는지를 확인하기 위해, 스크롤 이벤트를 사용해야 한다.
하지만 이 스크롤 이벤트는 아주 살짝만 움직여도 Listener가 동작하기 때문에,
클라이언트는 이 이벤트를 짧은 시간에 많이 반복하게 되어, 성능적으로 문제가 생길 수 있다.
특히 저사양의 PC나 모바일 등에서 말이다.
이 성능이 왜 중요한지 직접 테스트를 진행해보았다.
약 7,600px 높이 정도의 개발중인 페이지에서 키보드 아랫 방향키를 눌러 동일한 속도로 스크롤 하였을 때,
이벤트가 발생되면 콘솔에 "event call"이 찍히도록 해보았다.
$(window).scroll(function() { var self = $(this); console.log('event call') if (self.scrollTop() == $(document).height() - $(window).height()) { // scroll action } })
약 7초 정도 되는 시간에 무려 302번의 스크롤 이벤트가 실행되는 것을 볼 수 있다.
물론 이 수치는 클라이언트의 성능에 따라 다를 수 있다.
이 문제를 해결하려면
timeout
을 이용하여 이벤트 사이의 처리를 지연시켜야 하는데,코드를 직접 짜보는 것도 방법이지만, 외부 라이브러리를 이용하여 작업시 더 빠르게 개발을 할 수 있다.
이 Underscore.js에는 개발에 편리한 함수들이 구현되어있다.
그 중 이번에 알아볼 것들은
throttle
과 debounce
이다.throttle
은 지정한 시간마다 최대 1번만 실행될 수 있도록 도와준다.debounce
는 리스너가 실행된 후 다음 실행까지의 딜레이를 설정할 수 있도록 도와준다.$(window).scroll( var self = $(this); _.throttle(function() { console.log('event call') if (self.scrollTop() == $(document).height() - $(window).height()) { // scroll action } }, 100) );
스크롤 이벤트가 100ms중 한 번만 실행되도록 변경되었다.
하지만 이 100ms가 실제 서비스에 크게 영향을 주지는 않아 UX 상으로도 나쁘지 않은 모습을 보인다.
논외로
debounce
라는 함수도 존재하는데,$(window).scroll( var self = $(this); _.debounce(function() { console.log('event call') if (self.scrollTop() == $(document).height() - $(window).height()) { // scroll action } }, 100) );
debounce
를 사용하면 event call이 2번 나오게 된다.이 이유는
debounce
가 이벤트가 끝난 후의 시점부터 딜레이를 계산하기 때문이다.즉 스크롤이 시작되었을 때 실행 후 끝났을 때에 타이머 동작을 위해 실행되게 된다는 뜻이다.