[WEB] 느림의 미학 - Debounce, Throttle

느려터진 웹사이트는 왜 느릴까

프론트엔드 시점에서 웹사이트를 느리게 만드는 상황은 돌이켜봤을 때 이 정도가 생각난다.

  • 네트워크 지연 - 아무리 비동기 처리를 한다고 해도 로딩이 길면 어쩔 수 없다.
  • 불필요한 리렌더링 - <tr> 하나 추가할 때마다 수천 줄이 담긴 테이블 전체가 리렌더링 된다거나..?
  • 무거운 이벤트 핸들러 - scroll, resize, keyup을 할 때마다 네트워크가 호출된다면..

이 외에도 수많은 상황이 존재하겠지만, 이번 글에서는 마지막으로 언급한 무거운 이벤트 핸들러를 처리하기 위한 방법에 대해 다루려고 한다.

가장 확실한 방법 : 이벤트 핸들러 가볍게 만들기

당연하게도 쓸데없이 무거운 이벤트 핸들러를 가지고 있는 상황이라면
불필요한 로직을 핸들러 밖으로 옮기고 다음 단계를 논하는 게 맞을 것이다.

제목에 있는 Debounce, Throttle는 어쩔 수 없이 무거운 이벤트 핸들러를 처리하기 위함이라는 것부터 생각하자.

어쩔 수 없이 무거운 이벤트 핸들러 예시

아마 다들 슬랙, 페이스북, 아이메시지 등의 메신저를 써봤다면
'상대방이 입력 중'인 상태를 한 번씩은 본 경험이 있을 것이다.

이렇게 상대방을 쫄깃하게 만드는 기능을 구현하기 위해서는
키보드를 누를 때마다 불가피하게 네트워크를 통해 아직 입력 중이라는 정보를 전달해야 한다.

$input.addEventListener('keyup', e => {
  // 아직 입력 중임을 알리기 위한 네트워크 요청
});

만약 "개발자 살려" 라는 메시지를 보낸다면,
띄어쓰기 포함 13번의 네트워크 요청이 가게 된다.
(ㄱㅐㅂㅏㄹㅈㅏ ㅅㅏㄹㄹㅕ)

이 상황이 어쩔 수 없이 무거운 이벤트 핸들러의 대표적인 예시이다.

지금은 키보드 이벤트를 예시로 들었지만,
scroll/resize/mousedown 등 다양한 케이스에 대입해서 생각해볼 수 있다.

Debounce, Throttle

Debounce와 Throttle은 이러한 상황에서 타협을 제시하는 기법인데,
매 이벤트마다 호출하지 말고 적당히 천천히 실행하자는 것이 주요 컨셉이다.

둘의 공통점은 매번 동작을 실행하지 않는다는 점이고,
차이점다 끝나고(끝났다고 판단됐을 때) 실행하느냐 (debounce), 중간에 주기적으로 실행하느냐 (throttle) 이다.

아무튼 Debounce와 Throttle을 의인화하자면 다음과 같다.

(Debounce) 다 끝났으면 이제 처리해도 될까? 아, 안끝났구나.. 마저 해!

마지막 이벤트 이후로 (예를 들어) 500ms가 지나도 다음 이벤트가 발생하지 않으면 동작을 실행하는 식이다.

이 경우, 500ms 간격 안에서 이벤트가 계속 들어오면 단 한번도 동작이 실행되지 않는다.

(Throttle) 지금까지 된 건 일단 가져가고, 이따가 또 가지러 올게

이벤트가 계속 들어오더라도 매번 실행하지 않고 (예를 들어) 500ms 간격으로 동작을 실행한다.

이 경우, 500ms 간격 안에서 이벤트가 계속 들어오더라도 주기적으로 동작은 실행된다.

마무리

여기는 TIL이기도 하고 참고자료에 코드와 함께 설명은 잘 되어 있으니,
앞으로도 개념의 필요성과 이해하기 쉬운 요약 정도로 종종 찾아오도록 하겠습니다!
(꾸준히 오래 블로그하려면 페이스 조절이 중요하니까..ㅎ)

참고자료

https://www.zerocho.com/category/JavaScript/post/59a8e9cb15ac0000182794fa
https://pks2974.medium.com/throttle-와-debounce-개념-정리하기-2335a9c426ff
https://webclub.tistory.com/607

좋은 웹페이지 즐겨찾기