React를 사용하다 보면 사용자 입력 이벤트나 스크롤 이벤트처럼 고빈도로 발생하는 작업을 최적화해야 할 때가 많습니다. 이때 debounce와 throttle은 성능 최적화를 위해 자주 사용하는 기법입니다. 이번 글에서는 debounce와 throttle의 차이점, React에서의 사용법, 그리고 실제 사례를 통해 어떻게 적용할 수 있는지 알아보겠습니다.
1. debounce와 throttle이란?
debounce
Debounce는 특정 이벤트가 연속적으로 발생할 때, 마지막 이벤트가 발생한 이후 일정 시간이 지난 뒤에 단 한 번 실행되도록 만드는 기법입니다. 주로 사용자가 입력 필드를 빠르게 타이핑하거나 검색 요청과 같이 불필요한 중복 작업을 방지해야 할 때 유용합니다.
동작 원리
- 이벤트가 발생할 때마다 타이머를 초기화합니다.
- 일정 시간이 지나도 추가 이벤트가 발생하지 않으면 콜백 함수를 실행합니다.
사용 예시
- 검색어 입력 필드에서 사용자가 입력을 멈춘 후 요청 보내기.
- 창 크기 변경 이벤트 처리.
throttle
Throttle은 특정 이벤트가 연속적으로 발생하더라도, 정해진 시간 간격으로 한 번씩만 실행되도록 만드는 기법입니다. 주로 스크롤 이벤트나 마우스 이동 이벤트처럼 짧은 간격으로 발생하는 작업에서 사용됩니다.
동작 원리
- 이벤트가 발생하면 지정된 시간 동안 추가 이벤트를 무시합니다.
- 지정된 시간이 지나면 다시 이벤트를 처리할 수 있습니다.
사용 예시
- 스크롤 위치에 따라 콘텐츠를 로드할 때.
- 마우스 드래그 이벤트 처리.
2. React에서 debounce와 throttle 사용하기
React에서 debounce와 throttle을 구현하려면 lodash 또는 lodash-es 라이브러리의 debounce와 throttle 함수를 사용하는 것이 일반적입니다. 아래는 각각의 구현 방법입니다.
2.1 debounce 사용하기
설치
먼저 lodash를 설치합니다:
npm install lodash
기본 구현
검색 입력 필드에서 debounce를 적용하는 예제입니다:
import React, { useState, useCallback } from "react";
import _ from "lodash";
function SearchInput() {
const [query, setQuery] = useState("");
// debounce로 최적화된 함수 생성
const handleSearch = useCallback(
_.debounce((searchText) => {
console.log("API 요청: ", searchText);
// 여기에 API 요청 코드를 작성합니다.
}, 500), // 500ms 대기
[]
);
const handleChange = (e) => {
const { value } = e.target;
setQuery(value);
handleSearch(value); // debounce된 함수 호출
};
return (
<div>
<input
type="text"
value={query}
onChange={handleChange}
placeholder="검색어를 입력하세요"
/>
</div>
);
}
export default SearchInput;
주요 포인트
- _.debounce를 사용하여 검색 요청을 제한합니다.
- useCallback으로 메모이제이션하여 컴포넌트가 리렌더링될 때마다 debounce 함수가 재생성되지 않도록 합니다.
2.2 throttle 사용하기
기본 구현
스크롤 이벤트에 throttle을 적용하는 예제입니다:
import React, { useEffect } from "react";
import _ from "lodash";
function ScrollTracker() {
useEffect(() => {
// throttle로 최적화된 함수 생성
const handleScroll = _.throttle(() => {
console.log("스크롤 위치: ", window.scrollY);
}, 200); // 200ms 간격
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return <div style={{ height: "200vh" }}>스크롤 이벤트를 확인하세요!</div>;
}
export default ScrollTracker;
주요 포인트
- _.throttle를 사용하여 스크롤 이벤트의 과도한 호출을 방지합니다.
- useEffect에서 이벤트 리스너를 등록하고 컴포넌트가 언마운트될 때 클린업합니다.
3. 실무에서의 활용 사례
3.1 입력 필드에서 실시간 유효성 검사
사용자가 이메일 주소를 입력할 때 debounce를 사용해 입력이 끝난 후 유효성을 검사할 수 있습니다.
const validateEmail = _.debounce((email) => {
const isValid = /\S+@\S+\.\S+/.test(email);
console.log("이메일 유효성: ", isValid);
}, 300);
3.2 무한 스크롤 구현
스크롤 이벤트에 throttle을 적용하여 일정 위치에 도달할 때만 추가 데이터를 로드합니다.
const handleInfiniteScroll = _.throttle(() => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
console.log("추가 데이터 로드");
// 데이터 로드 함수 호출
}
}, 200);
4. 주의사항
- 타이머 관리: debounce와 throttle은 내부적으로 타이머를 사용하기 때문에 컴포넌트가 언마운트될 때 반드시 클린업을 해야 메모리 누수를 방지할 수 있습니다.
- 적절한 시간 설정: 최적화 수준은 이벤트 발생 빈도와 사용자 경험 사이에서 균형을 맞춰야 합니다. 지나치게 짧거나 긴 간격은 문제를 초래할 수 있습니다.
- 의존성 주의: React의 useCallback과 함께 사용할 때, 의존성 배열을 적절히 관리해야 예상치 못한 동작을 방지할 수 있습니다.
5. 결론
React에서 debounce와 throttle은 사용자 경험을 향상시키고 애플리케이션 성능을 최적화하는 데 필수적인 도구입니다. debounce는 사용자 입력처럼 이벤트의 빈도를 줄이는 데, throttle은 스크롤 이벤트처럼 이벤트 실행 간격을 조절하는 데 적합합니다. 이번 글에서 소개한 예제와 실무 사례를 참고하여 여러분의 프로젝트에 적절히 적용해 보세요!
'React' 카테고리의 다른 글
React에서 함수형 컴포넌트 성능 최적화하기 (0) | 2024.12.12 |
---|---|
React에서 setState 비동기 처리 이해하기 (0) | 2024.12.12 |
React에서 비동기 코드 처리하기 (0) | 2024.12.12 |
React에서 key 속성의 중요성 (0) | 2024.12.12 |
React에서 useMemo 훅 사용법 (0) | 2024.12.12 |