[React18] 디바운스(Debounce)와 스로틀(Throttle) 을 대체할 HOOK

Eddy·2023년 8월 22일
3

React

목록 보기
17/21
post-thumbnail

디바운스(Debounce)와 스로틀(Throttle) 을 대체할 수 있는 react hook인 useDeferredValue와 useTransition를 알아보겠습니다.

React 18의 Concurrent Rendering: useDeferredValue와 useTransition

최신 React 버전인 React 18은 놀라운 성능 개선과 유연성을 제공하는 concurrent rendering 기능을 도입했습니다. 이를 통해 UI 업데이트와 상호작용을 더욱 부드럽게 처리할 수 있게 되었습니다. 이번 글에서는 React 18에서 도입된 중요한 변화 중 하나인 useDeferredValue와 useTransition 훅에 대해 알아보겠습니다.


Concurrent Rendering이란?

Concurrent Rendering은 React 18에서 새롭게 도입된 기능으로, 병렬 처리와 우선순위 조절을 통해 더 나은 사용자 경험을 제공합니다. 이전 버전에서는 UI 업데이트나 상태 변화가 발생하면 그 작업이 완료될 때까지 메인 스레드가 블록되는 문제가 있었습니다. 하지만 Concurrent Rendering은 작업의 우선순위를 조절하여 중요한 작업에 먼저 반응할 수 있도록 합니다.


useDeferredValue 훅

useDeferredValue 훅은 React 18에서 새롭게 도입된 훅 중 하나로, 값의 업데이트 우선순위를 조절하는 데 사용됩니다. 이전 값을 기억하면서도 업데이트를 지연시키므로, 메인 스레드가 블로킹되지 않으면서도 높은 우선순위의 작업을 처리할 수 있습니다.

예를 들어, 검색 자동완성 기능을 가진 애플리케이션에서 useDeferredValue를 활용하면 유저의 검색 쿼리가 변경되더라도 추천 검색어 업데이트가 늦어지지 않습니다. 이전 값을 유지하면서도 추천 검색어 업데이트를 지연시켜 유저 경험을 향상시킬 수 있습니다.

예제 1: 검색 자동완성

import { useState } from 'react';
import { useDeferredValue } from 'react';

function SearchBar() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <SearchSuggestions query={deferredQuery} />
    </div>
  );
}

예제 2: 실시간 데이터 업데이트

import { useState } from 'react';
import { useDeferredValue } from 'react';

function RealtimeDataDisplay() {
  const [data, setData] = useState('');
  const deferredData = useDeferredValue(data);

  // 데이터를 주기적으로 업데이트하는 함수
  const fetchData = async () => {
    const response = await fetch('api/data');
    const newData = await response.json();
    setData(newData);
  };

  return (
    <div>
      <button onClick={fetchData}>새로운 데이터 가져오기</button>
      <DataDisplay data={deferredData} />
    </div>
  );
}

useTransition 훅

useTransition 훅은 상태 변화의 우선순위를 지정하는 데 사용됩니다. isPending와 startTransition을 반환하며, isPending는 작업이 지연되고 있는지 여부를 나타내는 불리언 값이고, startTransition은 낮은 우선순위로 실행될 함수를 받습니다.

예를 들어, 버튼 클릭 시 상태 업데이트를 지연시키고, 그 동안 로딩 스피너를 표시하고자 할 때 다음과 같이 활용할 수 있습니다.

예제 1: 버튼 클릭 처리

import { useState } from 'react';
import { useTransition } from 'react';

function ButtonWithTransition() {
  const [isPending, startTransition] = useTransition();
  const [count, setCount] = useState(0);

  const handleClick = () => {
    startTransition(() => {
      setCount((prevCount) => prevCount + 1);
    });
  };

  return (
    <div>
      {isPending && <Spinner />}
      <button onClick={handleClick}>Increment</button>
      <p>Count: {count}</p>
    </div>
  );
}

예제 2: 로딩 상태와 데이터 표시

import { useState } from 'react';
import { useTransition } from 'react';

function LoadingAndDataDisplay() {
  const [data, setData] = useState(null);
  const [isPending, startTransition] = useTransition();

  const fetchData = async () => {
    startTransition(() => {
      setData(null); // Reset previous data
    });

    const response = await fetch('api/data');
    const newData = await response.json();

    startTransition(() => {
      setData(newData);
    });
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch Data</button>
      {isPending ? (
        <p>Loading...</p>
      ) : (
        <DataDisplay data={data} />
      )}
    </div>
  );
}

디바운스와 스로틀링의 단점

디바운스와 스로틀링은 자주 발생하는 이벤트나 상태 업데이트를 제어하여 성능을 최적화하는데 사용되지만, 여전히 몇 가지 문제점을 가지고 있습니다.

디바운스의 단점

  • 지연 시간 선택의 어려움:
    디바운스에 사용할 지연 시간을 결정하기 어려울 수 있습니다. 지연 시간이 너무 짧으면 의도치 않게 빈번한 처리가 발생할 수 있고, 너무 길면 유저 경험이 느려질 수 있습니다.

스로틀링의 단점

  • 불필요한 호출 제한:
    스로틀링은 일정한 시간 간격으로 이벤트를 처리하여 불필요한 호출을 제한하나, 이로 인해 실제 이벤트가 놓치는 경우가 발생할 수 있습니다.

  • 긴 시간 동안 이벤트 무시:
    스로틀링된 함수가 일시적으로 비활성화되는 동안 긴 시간 동안 이벤트가 무시될 수 있습니다. 이는 사용자 경험에 악영향을 줄 수 있습니다.


useDeferredValue 와 useTransition의 장점

useDeferredValue의 장점

  • 선별적인 업데이트:
    useDeferredValue는 값의 업데이트 우선순위를 조절하여 중요한 작업에 우선순위를 부여할 수 있습니다. 이를 통해 메인 스레드의 블로킹을 방지하면서도 높은 우선순위의 작업을 더 빠르게 처리할 수 있습니다.

  • 고성능 상호작용:
    유저 입력과 같이 중요한 상호작용에 대한 반응성을 높일 수 있습니다.

useTransition의 장점

  • 상태 변화 우선순위 조절:
    useTransition을 활용하면 상태 변화의 우선순위를 지정하여 중요한 작업을 우선적으로 처리할 수 있습니다. 이로써 중요한 상호작용에 우선순위를 부여하면서도 백그라운드 작업을 놓치지 않게 됩니다.

  • 부드러운 사용자 경험:
    유저 입력과 같은 중요한 상호작용을 지연시키지 않으면서도 더 나은 성능과 부드러운 사용자 경험을 제공할 수 있습니다.


결론

디바운스와 스로틀링은 과거에 사용되던 성능 최적화 기술이지만, 그만큼 어려움과 문제점을 안고 있었습니다. React 18에서 도입된 useDeferredValue와 useTransition은 concurrent rendering을 통해 이러한 문제를 해결하고, 더 높은 성능과 유연성을 제공합니다. 디바운스와 스로틀링보다 훨씬 더 강력하고 정교한 처리를 가능하게 함으로써 사용자 경험을 더욱 향상시킬 수 있습니다.

0개의 댓글