the img generated by AI and debounce text added by author
React에서 디바운스(Debounce) 구현하기
React 애플리케이션을 개발하다 보면, 상태(state)가 빠르게 여러 번 변경될 때 불필요한 렌더링이나 성능 저하를 방지해야 할 상황이 종종 발생합니다. 이럴 때 유용한 기법이 바로 디바운스(Debounc짧은 시간 안에 여러 번 발생한 호출 중 마지막 호출만 유효하게 처리e) 입니다.
디바운스란?
디바운스는 짧은 시간 안에 여러 번 발생한 호출 중 마지막 호출만 유효하게 처리하는 기법입니다. 주로 다음과 같은 상황에서 사용됩니다:
검색 입력창의 자동완성 API 호출
윈도우 크기 조절 이벤트 처리
스크롤 이벤트 처리
캔버스나 그래프 같은 무거운 UI 업데이트
디바운스를 사용하지 않으면 생기는 문제점
디바운스를 적용하지 않을 경우 다음과 같은 문제가 발생할 수 있습니다:
과도한 API 호출: 사용자가 검색창에 입력할 때마다 매번 API 요청이 발생하면 서버에 불필요한 부하가 걸립니다.
성능 저하: 무거운 렌더링 작업이 자주 발생하면 UI가 느려지고 사용성에 악영향을 미칠 수 있습니다.
리소스 낭비: 네트워크, 메모리, CPU 자원이 불필요하게 소비됩니다.
사용자 경험 저하: 입력 지연, 버벅임, 렌더링 지연 등이 발생하여 사용자 경험이 나빠질 수 있습니다.
❌ 디바운스 없이 구현한 예제
import React, { useState, useEffect } from 'react';
function WithoutDebounce() {
const [inputValue, setInputValue] = useState('');
useEffect(() => {
if (inputValue) {
console.log('API 호출:', inputValue);
// inputValue가 1초에 100번 바뀌면 100번 실행됨.
// 실제 API 호출이 빈번하게 발생
}
}, [inputValue]);
return (
<div style={{ padding: '20px' }}>
<h2>디바운스 없이 입력 처리</h2>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="여기에 입력하세요..."
style={{ padding: '8px', width: '300px' }}
/>
</div>
);
}
export default WithoutDebounce;
문제점: 사용자가 입력할 때마다 useEffect가 즉시 실행되어 과도한 API 호출이 발생합니다.
결과: 네트워크 트래픽 증가, 서버 부하, UI 지연 등의 문제가 발생합니다.
기본적인 디바운스 구현 방법
React에서는 useEffect와 setTimeout, clearTimeout을 활용하여 간단하게 디바운스를 구현할 수 있습니다.
📦 디바운스를 적용한 예제
import React, { useEffect, useState } from 'react';
function DebounceExample() {
const [inputValue, setInputValue] = useState('');
const [debouncedValue, setDebouncedValue] = useState('');
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(inputValue);
}, 500); // 500ms 후에 마지막 입력값 반영
// 클린업 함수: 이전 타이머를 취소
return () => {
clearTimeout(handler);
};
}, [inputValue]);
useEffect(() => {
if (debouncedValue) {
console.log('API 호출 또는 무거운 작업 수행:', debouncedValue);
// API 호출 또는 무거운 작업 수행
}
}, [debouncedValue]);
return (
<div style={{ padding: '20px' }}>
<h2>디바운스 입력 예제</h2>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="여기에 입력하세요..."
style={{ padding: '8px', width: '300px' }}
/>
</div>
);
}
export default DebounceExample;
동작 방식 설명
입력값 변경 감지: inputValue가 변경될 때마다 useEffect가 실행됩니다.
타이머 설정: setTimeout을 통해 지정한 시간(500ms) 후에 debouncedValue를 업데이트합니다.
타이머 초기화: useEffect의 클린업 함수에서 clearTimeout으로 이전 타이머를 취소합니다.
최종 작업 수행: 디바운스된 값(debouncedValue)이 변경될 때만 무거운 작업(API 호출 등)을 수행합니다.
반응형
디바운스 vs 스로틀 (Throttle)
디바운스 (Debounce): 마지막 이벤트만 실행 (입력 필드, 검색 최적화 등)
스로틀 (Throttle): 일정 시간 간격으로 실행 (스크롤, 윈도우 리사이즈 등)
기법 사용 사례 설명
Debounce
검색창 자동완성, 입력 처리
마지막 이벤트만 실행
Throttle
스크롤, 리사이즈
일정 간격으로 실행
마무리
디바운스를 활용하면 불필요한 렌더링과 API 호출을 줄여 애플리케이션의 성능 최적화에 큰 도움이 됩니다. 위의 방법을 활용하면 다양한 상황에서 쉽게 디바운스를 적용할 수 있습니다.
🚀 Tip: 여러 곳에서 디바운스가 필요하다면 커스텀 훅으로 추상화하여 재사용성을 높일 수 있습니다!