개발을 하다보면 자주 안쓰다보니 혹은 너무 당연하게 생각하다 가끔 헷갈리거나 쌩둥맞게 낯설게 다가오는 것들이 있다. debounce
와 throttle
도 얼마 전에 뭐가 뭐였지 하고 다시 찾아봤던 것 중 하나다.
다시 보지 않기 위해 기록한다던 누군가(베토벤이었나?)의 말을 빌려 다신 헷갈리지 않기 위해 정리를 해본다.
일단 둘다 실행을 제어하기 위해, 좀 더 정확히는 빈번한 실행을 방지하기 위한 목적으로 사용한다.
Debounce
마지막 호출 이후 특정 시간이 지나야 호출 되도독 제한한다. 다른 말로는 이벤트를 그룹화 한다고도 한다. 즉 연속으로 발생하는 이벤트를 하나의 그룹으로 그룹화해서 한 번만 호출이 발생하도록 제한 것이다.
debounce
를 활용하기 좋은 예제는 자동 완성이다. 사용자가 타이핑을 계속하는데 매번 api를 호출해서 결과를 받아서 그리면 그 사이에 다른 타이핑이 발생하고 결국 보여주기도 전에 새로운 결과가 필요한 상황이 발생하는 비효율이 발생할 수 있다. 따라서 타이핑이 더이상 발생하지 않아 타이핑이 완료됐다는 판단이 들면 요청을 발생시키는 것이다.
debounce
에서는 두 가지 선택이 있다. 그룹화 된 호출들의 처음에 호출할지 대기 시간이 지난 후에 호출 할지이다. 즉 이벤트1이 발생하자마자 이벤트1을 실행하고 대기시간이 지난 후의 이벤트2가 발생했을 때 다시 이벤트2를 즉시 실행하거나, 이벤트1이 발생하고 대기시간이 지난 후에 이벤트1을 실행하고 대기시간이 지나고 이벤트2가 발생하면 다시 대기시간이 지난 후에 이벤트2를 실행한다. 차이라고 한다면 즉시 실행을 하게 되면 호출이 빈번하지 않은 경우 debounce
가 적용되지 않은 것과 동일한 시점에 이벤트가 발생 한다는 것이다.
Throttle
일정 주기마다 한 번씩만 호출 되도록 제한한다. debounce
와 차이점은 특정 시간 안에 최소 한 번의 실행을 보장한 다는 것이다. 다르게 표현하자면 이벤트가 발생한 후 특정 시간 동안 발생하는 이벤트들을 무시하고 정해진 시간이 지난 후에 다시 이벤트를 발생 시키는 것이다.
throttle
의 예로는 무한 스크롤을 수 있다. 다음 내용을 미리 가져오기 위해 끝에 도달했는지를 검사해야 하는데 이를 스크롤이 발생할 때 마다 하는건 매우 비효율 적이다. 실제 이벤트 발생보다 덜 빈번하게 주기를 낮춰서 검사하는 것이 좋은데 이때 사용할 수 있다.
requestAnimationFrame(rAF)
throttle
과 동일한 효과를 내는 브라우저 native API이다. 매 프레임 마다 실행 되는데 기본적으로 16ms(60fps)마다 실행이 된다. 차이가 있다면 무엇보다 requestAnimationFrame
은 브라우저 API라는 점이다. 그렇기 때문에 사용이 편하고 브라우저가 렌더링 스케줄에 대한 최적화를 하기 때문에 렌더링에 있어서는 더 좋을 수 있다. 하지만 모든 브라우저에서 지원하지 않기 때문에 polyfill
이 필요할 수 있고 node.js
에서는 지원하지 않기 때문에 서버에서는 사용할 수 없다. 추가로 rAF
는 다른 두 함수와 다르게 시작 시점을 직접 컨트롤해야 한다는 것이다.
그렇다면 언제 사용하는 것이 좋을까?
rAF
의 경우 위에서 언급했듯이 렌더링과 관련된 처리를 할 때 매우 유용하다. 브라우저 native API인데다 렌더링에 맞추어져 있기 때문이다. 대신 렌더링이 아닌 경우, 예를 들어 서버 API 호출이나 애니메이션 같은 렌더링의 시작이나 종료를 결정해야 하는 경우에는 debounce
나 throttle
이 유용하다. 특히 16ms 보다 덜 빈번하게 주기를 조절해야 하는 경우에는 특히 사용해야 한다.
정리를 해보면,
debounce
는 키입력과 같이 갑자기 이벤트가 몰리는 상황에서 그룹화를 통한 제어가 필요할 때,
throttle
은 정해진 매 주기마다 이벤트 실행을 보장해야 할 때,
requestAnimationFrame
은 throttle과 유사하지만 렌더링과 관련된 (화면에 무언가를 그린다거나 부드러운 애니메이션 효과 등) 작업을 처리할 때 사용하면 좋다.
좀 더 자세한 내용과 실제 예제를 확인하고 싶으면 아래 참고의 링크를 확인하면 된다.
참고
Debouncing and Throttling Explained Through Examples | CSS-Tricks