debounce & Throttle 구현해보기
📌 도입
Debounce 와 throttle은 무수히 많은 이벤트로 인해 CPU에 무리가 가는 상황이 발생했을 때, 성능 최적화를 위해 사용되는 프로그래밍 기법이다.
두 기법 모두 “연속적으로 발생하는 이벤트의 실행 빈도를 줄여 불필요한 함수 호출과 리소스 소모를 방지해주는 기법” 으로 동일한 목적을 가지고 있다.
하지만, 최적화를 처리하는 방식에서 차이를 보인다. 각각 어떻게 다른지, 그리고 어떻게 구현할 수 있는지 알아보자.
📌 Debounce 와 Throttle 의 의미와 예시
Debounce
“연속적으로 발생하는 이벤트를 하나의 그룹으로 묶어 처리하는 방식”
마지막 이벤트가 발생한 후 일정 시간이 경과했을 때만 함수를 실행하는 기법이다.
주요 특징
- 이벤트 발생 후 지정된 대기 시간 동안 추가 이벤트가 없을 때만 실행
- 연속적인 호출에서 마지막 호출만 유효하게 처리
- 불필요한 API 요청을 완전히 차단하여, 리소스 부하 감소
사용 예시
- 검색 자동완성 (300-500ms )
- 폼 입력 검증 (500ms )
- 자동 저장 기능 (1000 ~ 2000ms)
- 버튼 중복 클릭 방지 (300ms)
Throttle
*“일정한 시간 간격만 함수를 실행하는 방식”*
이벤트가 연속적으로 발생하더라도, 설정된 주기마다 한 번씩만 함수가 실행되도록 한여, 일정한 간격의 처리를 보장한다.
주요 특징
- 지정된 시간 간격마다 주기적으로 실행
- 연속적인 이벤트에 대해서도 일정 수준의 처리를 보장
- 실시간성이 중요한 이벤트에 적합
사용 예시
- 무한 스크롤 (200 ~ 500ms)
- 스크롤 위치 추적 (100ms)
- 애니메이션 제어 (16ms → 60fps)
- 창 크기 조절 감지 (250ms)

📌 구현
Debounce
구현 인사이트
- 클로저
- setTimeout 을 활용한 타이머 제어
- this를 통한 컨텐스트 유지
구현 포인트
- timeoutId 변수를 클로저로 유지하여 타이머 참조 관리
- 매 호출마다
clearTimeout으로 기존 타이머를 취소 - apply를 사용하여 원본 함수의
this컨텍스트를 유지
구현 코드
function debounce(func: (...args: any[]) => void, delay: number) {
// 클로저로 타이머 변수 저장
let timeout: NodeJS.Timeout;
// 인자를 받아서 타이머 설정
return function (...args: any[]) {
clearTimeout(timeout);
// 타이머 설정
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
Throttle
구현 인사이트
- 상태 플래그 활용한 실행 제어
- this 바인딩
- setTimeout을 활용한 콜백 전달
구현 포인트
- inThrottle 플래그로 실행 가능 상태 관리
- 첫 번째 호출은 즉시 실행, 이후 지정된 시간동안 차단
- 시간 경과 후 플래그 초기화
구현 코드
function throttle(func: (...args: any[]) => void, limit: number) {
let inThrottle = false;
return (...args: any[]) => {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
📌 실무 적용 가이드
- 주의 할점
- React 컴포넌트에서 단순히 debounce, throttle을 사용하면 리렌더링마다 새로운 함수가 생성되기 때문에 효과가 의미 없어진다. 따라서 useCallback을 활용한 메모이제이션이 필요하다.
- 메모리 누수 방지 : React 와 같은 컴포넌트 기반의 선언형 라이브러리에서는 언마운트시 타이머를 정리해주어야 한다.
- 적절한 딜레이 설정
- 너무 짧으면 효과가 거의 없고, 너무 길면 사용자가 끊어지는 경험을 하기 때문에 상황에 따른 적절한 시간 적용이 필요
- 라이브러리 활용
이를 제공하는 주요 라이브러리는 많지만, 대표적인 두가지 lodash와 es-toolkit에 대한 비교이다.
| 항목 | lodash | es-toolkit |
|---|---|---|
| 성능 | 표준적, 충분히 빠름 | 평균 2~3배 더 빠름 |
| 번들 크기 | 상대적으로 큼 | 최대 97% 더 작음 |
| 트리 셰이킹 | lodash-es는 지원, 기본 lodash는 미흡 | 매우 정밀하게 지원 |
| 타입 지원 | 타입스크립트 지원, 일부 any 혼용 | 안전하고 견고한 타입 제공 |
| 테스트 커버리지 | 널리 검증됨 | 100% 커버리지, 신뢰성 강조 |
| 생태계/호환성 | 매우 넓음, 레거시 코드 호환 | 최신 환경에 최적화, 일부 함수 미지원 |
| 사용법 | 오랜 기간 표준, 자료 풍부 | lodash와 거의 동일, 문서화 진행중 |
es-toolkit이 번들 사이즈, 성능 측면에서 더 큰 이점을 가져오기 때문에, es-toolkit을 사용하는 것이 최신 프로젝트에서는 더 좋을 것 같다.
📌 Reference
함께 보면 좋은 콘텐츠
- Engineering Guide
React Complier에 대하여
2025년 10월 1일 React 19.2가 정식으로 출시가 되었다. 더불어 10월 7-8일에 “React Conf 2025” 가 진행되면서 최신 React에 대한 새로운 주제가 많이 발표되었다.
- Engineering Guide
웹 접근성 (Web Accessibility)
최근 배리어프리(Barrire-Free) 라는 말을 많이 들어보았을 것이다.
- Engineering Guide
Streaming SSR
최근 계속 프론트엔드 개발자로 최적화된 사용자 경험을 위한 기술과 렌더링 방식에 대해 공부하며, 관련 개념을 정리하고 있다.