번역 자료 / / 2025. 5. 26. 17:30

[react 번역] useDeferredValue

출처: https://react.dev/reference/react/useDeferredValue


개요

useDeferredValue는 UI의 일부 업데이트를 지연(Deferred)시킬 수 있게 해주는 React Hook입니다.

const deferredValue = useDeferredValue(value)

Reference

useDeferredValue(value, initialValue?)

컴포넌트의 최상위에서 useDeferredValue를 호출하면, 해당 값의 지연된 버전을 얻을 수 있습니다.

import { useState, useDeferredValue } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  // ...
}

파라미터

  • value: 지연시키고 싶은 값. 어떤 타입이든 가능.
  • initialValue(선택): 컴포넌트의 최초 렌더 시 사용할 값. 생략하면 최초 렌더에서는 지연이 적용되지 않습니다.

반환값

  • currentValue: 최초 렌더에서는 initialValue 또는 전달한 값 자체를 반환합니다. 업데이트 시에는 이전 값을 먼저 반환하고, 백그라운드에서 새 값으로 다시 렌더를 시도합니다.

주의사항

  • 트랜지션(Transition) 내에서 업데이트가 발생하면, useDeferredValue는 항상 새 값을 반환하며 별도의 지연 렌더를 생성하지 않습니다.
  • 전달하는 값은 원시값(문자열, 숫자 등)이나 렌더링 외부에서 생성된 객체여야 합니다. 렌더링 중에 새 객체를 만들어 바로 전달하면, 매 렌더마다 값이 달라져 불필요한 백그라운드 렌더가 발생할 수 있습니다.
  • 값이 바뀌면(비교는 Object.is) 현재 렌더에서는 이전 값을 사용하고, 백그라운드에서 새 값으로 렌더를 시도합니다. 이 백그라운드 렌더는 인터럽트(중단)될 수 있습니다.
  • Suspense와 통합되어 있습니다. 백그라운드 렌더가 suspend되면, fallback이 아닌 이전 값을 계속 보여줍니다.
  • useDeferredValue 자체는 네트워크 요청을 지연시키지 않습니다.
  • useDeferredValue는 고정된 지연 시간을 두지 않습니다. 원래 렌더가 끝나면 즉시 백그라운드 렌더를 시작합니다.
  • 백그라운드 렌더가 커밋되기 전까지 Effect는 실행되지 않습니다.

사용법

새 데이터가 로딩되는 동안 이전(오래된) 콘텐츠 보여주기

import { useState, useDeferredValue } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  // ...
}

업데이트 시, deferred 값은 최신 값보다 "한 박자 느리게" 바뀝니다. React는 먼저 이전 값으로 렌더링한 뒤, 백그라운드에서 새 값으로 다시 렌더를 시도합니다.


최신 쿼리와 결과가 다를 때 시각적으로 표시하기

deferred 값이 최신 값과 다를 때, 예를 들어 opacity를 낮추는 등 시각적으로 "로딩 중"임을 표시할 수 있습니다.

const isStale = query !== deferredQuery;
return (
  <div style={{ opacity: isStale ? 0.5 : 1 }}>
    <SearchResults query={deferredQuery} />
  </div>
);

UI 일부의 리렌더링만 지연시키기 (성능 최적화)

입력 필드와 같이 빠른 반응이 필요한 UI와, 느리게 렌더링되는 컴포넌트(예: 대용량 리스트)를 분리할 때 유용합니다.

function App() {
  const [text, setText] = useState('');
  const deferredText = useDeferredValue(text);
  return (
    <>
      <input value={text} onChange={e => setText(e.target.value)} />
      <SlowList text={deferredText} />
    </>
  );
}

이렇게 하면 입력 필드는 즉시 반응하고, 리스트는 입력값을 따라가며 "한 박자 느리게" 업데이트됩니다. 리스트가 느리게 렌더링되어도 입력이 끊기지 않습니다.

주의: 이 최적화는 SlowList가 memo로 감싸져 있어야 효과가 있습니다. memo가 없으면 prop이 바뀔 때마다 무조건 리렌더링됩니다.


useDeferredValue와 디바운스/스로틀의 차이

  • 디바운스(debounce): 사용자가 입력을 멈춘 뒤 일정 시간 후에만 업데이트
  • 스로틀(throttle): 일정 시간마다 한 번씩만 업데이트
  • useDeferredValue: React가 렌더링 우선순위를 조절하여, 입력 등 중요한 작업이 먼저 처리되고, 느린 컴포넌트는 백그라운드에서 따라오게 함. 고정된 지연 시간이 없고, 사용자의 기기 성능에 따라 반응성이 달라짐. 백그라운드 렌더는 언제든 인터럽트될 수 있음.

출처: https://react.dev/reference/react/useDeferredValue

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유