티스토리 뷰
Debounce와 Throttle
`Debounce`와 `Throttle`은 이벤트 핸들러를 효율적으로 관리하기 위한 기술이다. 이 두 가지는 비슷하지만, 사용 목적과 동작 방식에서 중요한 차이점이 존재한다.
Debounce
연속적으로 발생하는 이벤트를 일정 시간동안 지연시키고, 이벤트가 발생하지 않을 때, 마지막 한 번만 실행하는 기법이다. 주로 사용자가 입력을 빠르게 할 때, 마지막 입력만 처리하고 싶을 때 유용하다.
동작 방식은 다음과 같다.
- 이벤트가 발생할 때마다 지정된 시간(대기 시간) 동안 대기
- 대기 시간동안 추가적인 이벤트가 발생하지 않으면 마지막 이벤트 처리
- 대기 시간동안 추가 이벤트가 발생하면 대기 시간을 초기화하고 다시 대기
아래의 예시 코드를 보고 조금 더 이해해보자.
입력 필드에서 검색어를 입력할 때마다 API 요청을 방지하기 위해 `Debouncing`을 사용할 수 있다.
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
function handleSearch(event) {
console.log('Search query:', event.target.value);
}
const debouncedSearch = debounce(handleSearch, 300);
document.getElementById('searchInput').addEventListener('input', debouncedSearch);
사용자가 입력 필드에 글을 입력하면 `handleSearch` 함수가 300ms 후에 실행된다. 입력이 계속되면 대기 시간이 초기화되기 때문에, 마지막 입력만 처리된다.
React 예제 코드
import React, { useState, useEffect, useCallback } from 'react';
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
function SearchComponent() {
const [query, setQuery] = useState('');
const handleSearch = useCallback((event) => {
console.log('Search query:', event.target.value);
}, []);
const debouncedSearch = useCallback(debounce(handleSearch, 300), [handleSearch]);
const handleChange = (event) => {
setQuery(event.target.value);
debouncedSearch(event);
};
return (
<input
type="text"
value={query}
onChange={handleChange}
id="searchInput"
placeholder="Search..."
/>
);
}
export default SearchComponent;
`Debounce`는 입력 이벤트를 일정 시간동안 지연시켜 과도한 호출을 방지하는 데 유용하니, 적절한 때에 고려해 볼 필요가 있다.
Throttle
이벤트가 일정 시간 간격으로만 발생하도록 제한하는 기법이다. 주로 스크롤이나 리사이즈와 같은 빈번하게 발생하는 이벤트를 제어할 때 유용하다.
동작 방식은 아래와 같다.
- 이벤트가 발생할 때마다 지정된 시간 간격(제한 시간) 동안 함수 호출 제한
- 제한 시간이 지나면 함수가 호출되고, 이후 같은 시간 간격으로만 함수 호출
예제 코드를 보고 이해해보자.
스크롤 이벤트가 빈번하게 발생하는 것을 제어하기 위해 `Throttling`을 사용할 수 있다.
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
const now = Date.now();
if (!lastRan) {
func.apply(this, args);
lastRan = now;
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (now - lastRan >= limit) {
func.apply(this, args);
lastRan = now;
}
}, limit - (now - lastRan));
}
};
}
function handleScroll() {
console.log('Scroll event');
}
const throttledScroll = throttle(handleScroll, 1000);
window.addEventListener('scroll', throttledScroll);
위 코드를 설명하자면, 사용자가 스크롤을 할 때마다 `handleScroll` 함수는 1초(1,000ms) 간격으로 호출된다. 이로 인해 빈번하게 발생하는 함수 호출을 방지할 수 있다.
React 예제 코드
import React, { useState, useCallback, useEffect } from 'react';
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
const now = Date.now();
if (!lastRan) {
func.apply(this, args);
lastRan = now;
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(() => {
if (now - lastRan >= limit) {
func.apply(this, args);
lastRan = now;
}
}, limit - (now - lastRan));
}
};
}
function ScrollComponent() {
const [scrolling, setScrolling] = useState(false);
const handleScroll = useCallback(() => {
console.log('Scroll event');
setScrolling(true);
}, []);
const throttledScroll = useCallback(throttle(handleScroll, 1000), [handleScroll]);
useEffect(() => {
window.addEventListener('scroll', throttledScroll);
return () => {
window.removeEventListener('scroll', throttledScroll);
};
}, [throttledScroll]);
return (
<div>
<p>Scroll to see the effect in the console</p>
<div style={{ height: '2000px' }}></div>
{scrolling && <p>Scrolling...</p>}
</div>
);
}
export default ScrollComponent;
`Throttle`는 이벤트 호출을 제한하여 성능을 개선할 수 있다. `useState`와 `useCallback`을 사용해 이 기능을 구현할 수 있다.
특성 | Debounce | Throttle |
동작 원리 | 일정 시간동안 이벤트가 없을 때 마지막 한 번만 실행 | 지정된 시간 간격으로만 함수 호출 허용 |
주 사용 사례 | 입력 필드의 자동 검색, 창 크기 조정 등 | 스크롤, 윈도우 크기 조정 등 |
성능 | 자주 발생하는 이벤트를 최적화하여 불필요한 호출 방지 | 일정 간격으로 이벤트 처리하여 호출 빈도 조절 |
아래의 그림으로 다시 한 번 복습해보자.
Debounce 동작 원리
+---------+ +---------+ +---------+
| A | | B | | C | => 마지막 A, B, C 이후 처리
+---------+ +---------+ +---------+
^ ^ ^
| | |
타이머 초기화 타이머 초기화 타이머 초기화
| | |
+---- 300ms ----> 마지막 이벤트 처리
Throttle 동작 원리
+---------+ +---------+ +---------+ +---------+ +---------+
| A | | B | | C | | D | | E | => 1초마다 호출
+---------+ +---------+ +---------+ +---------+ +---------+
^ ^ ^ ^ ^
| | | | |
+---- 1초 ---->+---- 1초 ---->+---- 1초 ---->+---- 1초 ---->+---- 1초
이러한 기법들을 적절히 활용하면 웹 애플리케이션의 성능과 사용자 경험을 크게 향상시킬 수 있다.
'프론트엔드 > JavaScript' 카테고리의 다른 글
기술 지식 3단계 내용 정리 (0) | 2024.08.17 |
---|---|
기술 지식 1단계 내용 정리 (0) | 2024.08.14 |
PoC는 무엇일까? (0) | 2024.07.11 |
크롬 확장 프로그램을 만들면서 겪은 에러 (0) | 2023.07.17 |
컨텍스트 실행을 배워보자 (0) | 2023.06.01 |
- Total
- Today
- Yesterday
- 고민한 부분
- 개발자이력서꿀팁
- 최종추가합격
- Express
- Singleton
- LottieFiles
- 코딩테스트 대비
- 포스텍애플아카데미
- 개발 이력서 지원 팁
- 설명회느낌점
- 원티드 프리온보딩
- 스프링
- Frontend
- DB Error MongooseServerSelectionError
- 원티드 프리온보딩 챌린지
- 조코딩과함께
- PostechAppleDeveloperAcademy
- #포스텍애플디벨로퍼아카데미
- 포스텍애플디벨로퍼아카데미
- Default Branch
- node
- 자바스크립트
- 깃허브 Merge
- React
- javascript
- 그룹인터뷰후기
- if(kakao)dev2022
- 싱글톤
- 신입개발자가 준비해야 할 것들
- 프론트엔드 챌린지
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |