본문 바로가기

cs/react

[React] Debounce

목차

1. Debounce란

2. 구현

3. 동작원리


 

Debounce란

디바운스란, 사용자 입력 또는 빈번하게 API 호출이 발생하는 이벤트의 성능을 최적화시키기 위한 방법입니다.

 

즉, 연이어 호출되는 함수들 중 마지막 함수만 호출하도록 하는 것입니다.

 

검색창에 검색어를 입력했을때 조회 api를 호출하는 경우 하나의 글자를 입력하는 이벤트마다 api호출이 된다면 네트워크 부담과 자원 부하가 클 것입니다.

 

하지만 debounce 기법을 사용한다면, 키워드를 모두 입력했을 경우에만 api를 호출 할 수 있도록 지연시킬 있습니다.

구현

debounce기법을 활용한 검색어 입력 예시입니다.

import React, {useCallback, useEffect, useState} from "react";

export default function DebounceHook() {

    const [query, setQuery] = useState("");
    const [debounceValue, setDebounceValue] = useState("");


    //디바운스 함수
    useEffect(()=> {

        console.log("query: ",query);
        const timer = setTimeout(()=>{
            setDebounceValue(query);
        }, 500)

        return () => {
            clearTimeout(timer);
        }
    },[query])

    const handleChange = (e) => {
        const value = e.target.value;

        setQuery(value);
        // delayedSearch(value);
    }

    useEffect(() => {
        console.log("debounceValue: ",debounceValue);
    }, [debounceValue]);

    return (
        <>
            <input type="text" value={query} onChange={handleChange} placeholder="검색어를 입력하세요..."/>
        </>
    )
}

debounce 기법 적용 결과

키워드 입력시 상태 query의 값은 바로 업데이트가 되고 있습니다. 하지만 상태 debounce는 마지막 키워드만 출력되고 있습니다. 즉, 마지막 키워드만 api로 호출되어 검색 결과를 반환할수 있게 되는 것입니다.

 

query의 값을 빈번하게 api호출 하는 것 보다, debounce 기법을 이용한 값을 api 호출하는 것이 성능적으로 더 최적화된 방법입니다.


동작원리

  1. 키워드 '오' 입력시 input태그 이벤트로 인해 handleChange함수 호출
  2. 함수(handleChange)에서 상태 query 업데이트
  3. query업데이트로 인한 재랜더링
  4. 위 3번에서 발생한 랜더링의 commit phase 이후 의존 배열이 상태 query인 useEffect 실행 (effect 단계)
  5. 상태 debounceValue를 업데이트 하기 위해 타이머가 500ms 대기
  6. 다음 입력 '오ㄴ'입력시(100ms 후) 위와 동일한 흐름
  7. 아직 실행되지 않은 첫번째 타이머를 clear (cleanup phase)
  8. 두번째 타이머 생성 (effect 단계)
  9. 500ms 후 debounceValue 업데이트
  10. 의존성 배열 debounceValue인 useEffect 호출로 로그 출력 (effect 단계)

 

코드 레벨 동작 흐름

선 입력 이후 두번째 입력일때 상황입니다.

위의 동작원리에서 6번부터의 상황입니다.

export default function DebounceHook() {

    const [query, setQuery] = useState("");
    const [debounceValue, setDebounceValue] = useState("");


    //[3] 렌더링 후 Effect 단계에서 useEffect 호출(effect 단계)
    useEffect(()=> {

        console.log("query: ",query);
        //[3.1] 현재 입력값의 타이머 생성
        const timer = setTimeout(()=>{
            setDebounceValue(query);
        }, 500)

        //[2] 이전에 생성된 타이머 제거(clearup phase)
        return () => {
            clearTimeout(timer);
        }
    },[query])

    //[1] 이벤트 발생
    const handleChange = (e) => {
        const value = e.target.value;

        //[1.1] 입력값 업데이트
        setQuery(value);
        // delayedSearch(value);
    }

    useEffect(() => {
        console.log("debounceValue: ",debounceValue);
    }, [debounceValue]);

    return (
        <>
            <input type="text" value={query} onChange={handleChange} placeholder="검색어를 입력하세요..."/>
        </>
    )

 

debounce 기법의 핵심은 이벤트 타겟값인 query를 의존성 배열로 가지는 useEffect의 clear부분입니다.

    useEffect(()=> {

        console.log("query: ",query);
        //debounceValue업데이트를 위한 타이머 생성
        const timer = setTimeout(()=>{
            setDebounceValue(query);
        }, 500)

        //debounce 기법의 핵심
        return () => {
            clearTimeout(timer);
        }
    },[query])

query 업데이트로 인해 cleanup phase에서 useEffect의 clean이 동작하면서 이전 타이머가 제거됩니다. 이어지는 effect 단계에서 query의 새로운 타이머가 생성되면서 마지막에 입력한 query가 debounceValue로 업데이트 되는 원리입니다.

 

효과

  • API 호출 횟수 감소
  • 네트워크 부하 감소
  • UX 감소

참고

https://velog.io/@seesaw/React%EC%97%90%EC%84%9C-Debouncing-%EC%A2%80-%EB%8D%94-%EC%9E%98-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0

 

React에서 Debouncing 좀 더 잘 적용해보기 / Custom Hook

리액트에서 함수 실행과 관련해 최적화를 위해 디바운싱을 적용했다가 오히려 문제가 생겼던 경험과, 이를 해결하기 위해 리액트의 특성을 고려해 다양한 훅을 활용해 디바운싱을 구현하기 위

velog.io

 

'cs > react' 카테고리의 다른 글

[React] useTransition  (0) 2026.01.09
[JS] 화살표 함수 반환 규칙  (0) 2026.01.03
[JS] Promise & async & await  (1) 2025.12.09
[JS] JS의 비동기와 콜백 큐  (1) 2025.12.08
[React] React Router  (0) 2025.12.05