🛠️ 처음부터 만드는 Debounce — 연속 입력을 마지막 한 번만 처리하기
왜 Debounce가 필요한가?
검색창에 글자를 입력할 때마다 API 요청을 보낸다면? 100글자를 입력하려고 100번의 API 호출이 일어납니다. 이는 서버 부하와 낭비입니다.
Debounce는 사용자가 입력을 멈춘 후 특정 시간이 지났을 때만 작업을 실행합니다.
```javascript
// 검색 입력 예시
input.addEventListener('input', debounce((e) => {
api.search(e.target.value); // 사용자가 0.5초 동안 입력을 멈춘 후에만 호출
}, 500));
```
Debounce 구현하기
```javascript
function debounce(func, wait) {
let timeoutId = null;
return function debounced(...args) {
// 이전 타이머 취소 (새 입력이 들어오면 대기시간을 초기화)
if (timeoutId) clearTimeout(timeoutId);
// 새로운 타이머 설정
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, wait);
};
}
// 사용법
const handleSearch = debounce((query) => {
console.log('검색:', query);
}, 500);
input.addEventListener('input', (e) => handleSearch(e.target.value));
```
Throttle과의 차이
| | Debounce | Throttle |
|---|----------|----------|
| 목적 | 마지막 호출만 실행 | 일정 시간마다 호출 |
| 사용 사례 | 검색, 폼 저장, 리사이즈 | 스크롤, 마우스 이동 |
| 동작 | 입력 멈춘 후 대기 | 일정 주기마다 반복 |
실제 사용 사례
```javascript
// 1. 폼 자동저장
const saveNote = debounce(async (content) => {
await api.saveNote(content);
}, 2000);
textarea.addEventListener('input', (e) => saveNote(e.target.value));
// 2. 자동완성 검색
const fetchSuggestions = debounce(async (query) => {
const results = await api.suggest(query);
showDropdown(results);
}, 300);
searchInput.addEventListener('input', (e) => fetchSuggestions(e.target.value));
```
고급: 즉시 실행 옵션
```javascript
function debounceAdvanced(func, wait, immediate = false) {
let timeoutId = null;
return function debounced(...args) {
const callNow = immediate && !timeoutId;
if (timeoutId) clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if (!immediate) func.apply(this, args);
timeoutId = null;
}, wait);
if (callNow) func.apply(this, args);
};
}
// 버튼 클릭 시 즉시 피드백, 그 후 0.5초 동안 중복 클릭 방지
const submit = debounceAdvanced(() => api.submit(), 500, true);
```
핵심 개념
1. 클로저: `timeoutId`는 반환된 함수 내에서만 유지됨
2. 메모리 정리: 새 입력이 들어올 때마다 이전 타이머 제거
3. this 바인딩: `apply(this, args)`로 원래 컨텍스트 유지
Lodash의 `debounce`도 이와 같은 원리로 작동합니다. 간단한 경우는 직접 구현하고, 복잡한 옵션(maxWait, leading, trailing)이 필요하면 라이브러리를 사용하세요.
👁 0 views
Comments (0)
💬
No comments yet.
Be the first to comment!