- Published On
Debounce와 Throttle의 차이점 및 활용법
웹 애플리케이션에서 이벤트가 너무 자주 발생하는 것을 방지하기 위해 Debounce
와 Throttle
를 자주 사용합니다.
이 두 가지는 비슷해 보이지만 작동 방식과 목적에 차이가 있습니다.
이 글에서는 각각의 정의와 차이점, 사용 예제, 그리고 React에서의 활용 및 구현 방법에 대해 알아보겠습니다.
Debounce와 Throttle의 차이점
항목 | Debounce | Throttle |
---|---|---|
동작 방식 | 마지막 이벤트 이후 일정 시간 대기 후 실행 | 일정한 주기마다 한 번씩 실행 |
주요 목적 | 이벤트의 과도한 호출을 방지 | 자주 발생하는 이벤트를 일정 주기로 제한 |
사용 예시 | 검색어 자동완성 , 버튼 중복 클릭 방지 | 스크롤 이벤트 , 윈도우 리사이즈 이벤트 |
Debounce란?
Debounce
는 연속된 이벤트가 발생할 때, 일정 시간 동안 추가 입력이 없을 경우에만 마지막 이벤트를 실행하는 기법입니다. 사용자가 짧은 시간 안에 여러 번 버튼을 클릭하거나 입력 필드를 수정하는 경우, 불필요한 이벤트 호출을 줄이기 위해 유용합니다.
Debounce 사용 예시:
검색 자동완성
: 사용자가 검색어를 입력할 때마다 API 요청을 보내는 대신, 입력이 끝나고 일정 시간 동안 멈췄을 때만 API 요청을 보냅니다.버튼 클릭 방지
: 사용자가 같은 버튼을 빠르게 여러 번 누르는 것을 막아주는 기능입니다.
Throttle란?
Throttle
는 연속된 이벤트가 발생해도 일정한 주기마다 한 번만 이벤트를 실행하는 기법입니다. 스크롤 이벤트나 윈도우 크기 조정과 같이 자주 발생하는 이벤트에서 성능 최적화를 위해 주로 사용됩니다.
Throttle 사용 예시:
스크롤 이벤트 처리
: 사용자가 페이지를 스크롤할 때 일정 시간 간격으로만 이벤트를 처리합니다.윈도우 리사이즈 이벤트
: 창 크기 조정 중 이벤트가 너무 자주 발생하지 않도록 제한합니다.
코드 구현
이 글에서는 throttleHelper
와 같은 일반적인 구현 방식이 아닌 React를 활용한 훅 방식
으로 구현하였습니다.
utils.tsjavascript
import { useState, useEffect, useRef } from "react";
// Debounce Hook 구현
export const useDebounce = <T,>(value: T, delay: number = 500): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer); // 타이머 해제
}, [value, delay]);
return debouncedValue;
};
// Throttle Hook 구현
export const useThrottle = <T,>(value: T, delay: number = 500): T => {
const [throttledValue, setThrottledValue] = useState<T>(value);
const lastRan = useRef<number>(Date.now()); // 마지막 실행 시간 저장
useEffect(() => {
const handler = setTimeout(() => {
if (Date.now() - lastRan.current >= delay) {
setThrottledValue(value);
lastRan.current = Date.now();
}
}, delay - (Date.now() - lastRan.current));
return () => clearTimeout(handler); // 타이머 해제
}, [value, delay]);
return throttledValue;
};
debounce 사용 예제
import { useState, useEffect, ChangeEvent } from "react";
import { useDebounce } from "./utils"; // Debounce Hook 임포트
export default function SimpleDebounceExample() {
const [inputValue, setInputValue] = useState < string > ""; // 입력 값 상태
const debouncedValue = useDebounce < string > (inputValue, 500); // Debounce된 값 생성
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value); // 입력 값 업데이트
};
// debouncedValue가 변경될 때 콘솔에 로그 출력
useEffect(() => {
console.log(`Debounced Value: ${debouncedValue}`);
}, [debouncedValue]);
return (
<div style={{ padding: "20px" }}>
<h1>간단한 Debounce 예제</h1>
<div style={{ marginBottom: "20px" }}>
<label htmlFor="search">텍스트 입력:</label>
<input
id="search"
type="text"
value={inputValue}
onChange={handleChange}
placeholder="Type something..."
/>
</div>
<div>
<p>Debounced Value: {debouncedValue}</p>
</div>
</div>
);
}
throttle 사용 예제
import { useState, useEffect } from "react";
import { useThrottle } from "./utils"; // Throttle Hook 임포트
export default function ScrollThrottleExample() {
const [scrollPosition, setScrollPosition] = useState < number > 0; // 스크롤 위치 상태
// Throttled 스크롤 핸들러 정의
const throttledScrollPosition = useThrottle < number > (scrollPosition, 1000); // 1초마다 업데이트
useEffect(() => {
const handleScroll = () => {
setScrollPosition(window.scrollY); // 현재 스크롤 위치 업데이트
};
window.addEventListener("scroll", handleScroll); // 스크롤 이벤트 리스너 등록
return () => window.removeEventListener("scroll", handleScroll); // 언마운트 시 이벤트 리스너 해제
}, []);
return (
<div style={{ height: "200vh", padding: "20px" }}>
<h1>Throttle을 사용한 스크롤 이벤트 예제</h1>
<p>현재 스크롤 위치: {throttledScrollPosition}px</p>
</div>
);
}
일반 함수(throttleHelper)와 훅(useThrottle)의 차이점과 장단점
throttleHelper
와 같은 일반적인 구현 방식과 useThrottle
과 같은 React 훅 방식
은 사용 목적과 상황에 따라 각각의 장단점이 있습니다.
항목 | 일반 함수 (throttleHelper / debounceHelper ) | React 훅 (useThrottle / useDebounce ) |
---|---|---|
사용 환경 | React 외부나 다른 라이브러리에서도 사용 가능 | React 컴포넌트 내부에서만 사용 가능 |
코드 복잡성 | 단순하고 짧은 코드로 구현 가능 | 훅과 상태 관리를 포함해 다소 복잡함 |
상태 관리 | 상태 관리와 연계 어려움 | React 상태와 자연스럽게 통합 가능 |
생명주기 제어 | 생명주기 제어가 불가능 | useEffect 로 생명주기 제어 가능 |
메모이제이션 | 직접 메모이제이션 관리 필요 | useCallback , useRef 등을 활용한 최적화 가능 |
재사용성 | 프레임워크 독립적으로 사용 가능 | React 프로젝트 내에서만 사용 가능 |
다음 포스트
클로저와 렉시컬 스코프연관된 포스트 구경가기
1. React 란?2. Redux3. Virtual DOM(가상 DOM)이란?4. React hook 이란?5. Debounce와 Throttle의 차이점 및 활용법6. 클로저와 렉시컬 스코프7. React hooks - useEffect8. React hooks - useState9. React hooks - useRef
간략히