본문 바로가기
React

React에서 debounce와 throttle 사용법

by 굿센스굿 2024. 12. 12.
반응형

 

React를 사용하다 보면 사용자 입력 이벤트나 스크롤 이벤트처럼 고빈도로 발생하는 작업을 최적화해야 할 때가 많습니다. 이때 debouncethrottle은 성능 최적화를 위해 자주 사용하는 기법입니다. 이번 글에서는 debounce와 throttle의 차이점, React에서의 사용법, 그리고 실제 사례를 통해 어떻게 적용할 수 있는지 알아보겠습니다.


1. debounce와 throttle이란?

debounce

Debounce는 특정 이벤트가 연속적으로 발생할 때, 마지막 이벤트가 발생한 이후 일정 시간이 지난 뒤에 단 한 번 실행되도록 만드는 기법입니다. 주로 사용자가 입력 필드를 빠르게 타이핑하거나 검색 요청과 같이 불필요한 중복 작업을 방지해야 할 때 유용합니다.

동작 원리

  1. 이벤트가 발생할 때마다 타이머를 초기화합니다.
  2. 일정 시간이 지나도 추가 이벤트가 발생하지 않으면 콜백 함수를 실행합니다.

사용 예시

  • 검색어 입력 필드에서 사용자가 입력을 멈춘 후 요청 보내기.
  • 창 크기 변경 이벤트 처리.

throttle

Throttle은 특정 이벤트가 연속적으로 발생하더라도, 정해진 시간 간격으로 한 번씩만 실행되도록 만드는 기법입니다. 주로 스크롤 이벤트나 마우스 이동 이벤트처럼 짧은 간격으로 발생하는 작업에서 사용됩니다.

동작 원리

  1. 이벤트가 발생하면 지정된 시간 동안 추가 이벤트를 무시합니다.
  2. 지정된 시간이 지나면 다시 이벤트를 처리할 수 있습니다.

사용 예시

  • 스크롤 위치에 따라 콘텐츠를 로드할 때.
  • 마우스 드래그 이벤트 처리.

2. React에서 debounce와 throttle 사용하기

React에서 debounce와 throttle을 구현하려면 lodash 또는 lodash-es 라이브러리의 debouncethrottle 함수를 사용하는 것이 일반적입니다. 아래는 각각의 구현 방법입니다.

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. 주의사항

  1. 타이머 관리: debounce와 throttle은 내부적으로 타이머를 사용하기 때문에 컴포넌트가 언마운트될 때 반드시 클린업을 해야 메모리 누수를 방지할 수 있습니다.
  2. 적절한 시간 설정: 최적화 수준은 이벤트 발생 빈도와 사용자 경험 사이에서 균형을 맞춰야 합니다. 지나치게 짧거나 긴 간격은 문제를 초래할 수 있습니다.
  3. 의존성 주의: React의 useCallback과 함께 사용할 때, 의존성 배열을 적절히 관리해야 예상치 못한 동작을 방지할 수 있습니다.

5. 결론

React에서 debounce와 throttle은 사용자 경험을 향상시키고 애플리케이션 성능을 최적화하는 데 필수적인 도구입니다. debounce는 사용자 입력처럼 이벤트의 빈도를 줄이는 데, throttle은 스크롤 이벤트처럼 이벤트 실행 간격을 조절하는 데 적합합니다. 이번 글에서 소개한 예제와 실무 사례를 참고하여 여러분의 프로젝트에 적절히 적용해 보세요!

반응형