React · 2026-03-08

React에서 Debounce와 Throttle 패턴

입력 지연과 빈도 제한을 통해 React 애플리케이션의 응답성과 비용을 개선하는 디바운스와 쓰로틀 구현 패턴 모음

작성일 : 2026-03-08 ㆍ 작성자 : 관리자
post
목차

개요

입력 최적화 리액트 환경에서 Debounce와 Throttle은 자주 발생하는 이벤트를 제어하는 핵심 패턴이다. 두 기법은 목적과 동작 방식이 다르므로, 상황에 맞게 선택하는 것이 중요하다. 이 글에서는 개념 비교부터 직접 쓸 수 있는 구현 예제, 실전에 가까운 사용법까지 단계별로 설명한다.

Debounce와 Throttle의 차이

Debounce (디바운스)

Debounce는 마지막 이벤트 발생 후 지정한 시간 동안 추가 호출이 없을 때 한 번만 실행하는 방식이다. 주로 검색 입력처럼 사용자가 입력을 멈춘 뒤에 API 호출을 하고 싶을 때 적합하다.

Throttle (쓰로틀)

Throttle은 일정 시간 간격으로 이벤트를 제한해서 실행한다. 스크롤이나 리사이즈처럼 연속 이벤트가 발생해도 초당 호출 횟수를 제어하고 싶을 때 유용하다.

언제 어떤 것을 선택할까

  • 검색 입력: react debounce 구현을 사용해 불필요한 API 호출을 줄인다.
  • 스크롤 감지나 위치 추적: throttle 사용법 react에 따라 호출 빈도를 제한한다.
  • 폼 유효성 검사: 입력 최적화 리액트 방식으로 debounce를 활용하면 사용자 경험 개선에 도움된다.

간단한 구현

순수 자바스크립트로 구현한 debounce와 throttle 예제이다.

function debounce(fn, wait = 300) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, wait);
  };
}

function throttle(fn, limit = 200) {
  let lastCall = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= limit) {
      lastCall = now;
      fn.apply(this, args);
    }
  };
}

React Hook으로 만들기

React에서 재사용 가능하게 만들면 관리가 편해진다. 아래는 useDebounce와 useThrottle의 예시 구현이다.

import { useRef, useEffect } from 'react';

export function useDebounce(callback, delay) {
  const ref = useRef();
  useEffect(() => {
    ref.current = callback;
  }, [callback]);

  return function(...args) {
    if (ref.timer) clearTimeout(ref.timer);
    ref.timer = setTimeout(() => ref.current(...args), delay);
  };
}

export function useThrottle(callback, limit) {
  const ref = useRef({ last: 0, cb: null });
  useEffect(() => {
    ref.current.cb = callback;
  }, [callback]);

  return function(...args) {
    const now = Date.now();
    if (now - ref.current.last >= limit) {
      ref.current.last = now;
      ref.current.cb(...args);
    }
  };
}

사용 예시: 검색 입력

검색 입력에서 debounce를 적용하면 API 호출 횟수가 크게 줄어든다. 아래 예시는 useDebounce를 사용한 컴포넌트 구조이다.

import React, { useState } from 'react';
import { useDebounce } from './hooks';

function Search() {
  const [q, setQ] = useState('');
  const debouncedSearch = useDebounce((val) => {
    // fetch(`/api/search?q=${val}`)...
    console.log('search', val);
  }, 400);

  return (
    <input
      value={q}
      onChange={(e) => {
        setQ(e.target.value);
        debouncedSearch(e.target.value);
      }}
      placeholder="검색어 입력"
    />
  );
}

사용 예시: 스크롤 이벤트

스크롤이나 리사이즈처럼 빈번한 이벤트에는 throttle 사용이 적절하다. 호출 빈도를 제한해 렌더와 계산 부하를 줄인다.

import React, { useEffect } from 'react';
import { useThrottle } from './hooks';

function ScrollTracker() {
  useEffect(() => {
    const onScroll = useThrottle(() => {
      console.log('scroll position', window.scrollY);
    }, 200);
    window.addEventListener('scroll', onScroll);
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return <div>스크롤 상태 추적중</div>;
}

주의사항과 최적화 포인트

  • 클린업: 컴포넌트 언마운트 시 타이머나 이벤트 리스너 제거가 필요하다.
  • 의존성 관리: Hook 내부에서 참조하는 값이 변경되면 콜백 업데이트가 필요하다.
  • 지연 시간 조정: 너무 길면 응답성이 떨어지고, 너무 짧으면 효과가 미미하다.
  • 서버 비용 고려: 입력 최적화 리액트 전략으로 불필요한 네트워크 요청을 줄이면 비용 절감에 기여한다.

결론

react debounce 구현과 throttle 사용법 react은 목적에 따라 선택하면 입력 처리와 성능 개선에 큰 도움이 된다. 검색처럼 마지막 동작을 기다리는 경우에는 Debounce, 지속적인 상태 체크에서는 Throttle이 적합하다. 구현은 단순하지만, 컴포넌트 생명주기와 의존성 관리를 염두에 두면 안정적으로 활용할 수 있다.

react debounce 구현 throttle 사용법 react 입력 최적화 리액트 react 성능 최적화 useDebounce useThrottle 리액트 입력 지연 검색 입력 최적화