useDeferredValue 파헤치기

공식문서를 통해 알아보는 useDeferredValue 훅
강석우's avatar
Apr 15, 2024
useDeferredValue 파헤치기

useDeferredValue 란?

UI 일부의 업데이트를 지연시킬 수 있는 React 훅이다.

useDeferredValue, 언제 사용해야 할까

  • 새 콘텐츠가 로드되는 동안 오래된 콘텐츠 표시하기

  • 콘텐츠가 오래되었음을 표시하기

  • UI의 일부에 대해 리렌더링 연기하기

useDeferredValue의 구성

const deferredValue = useDeferredValue(value)

Parameters

value : 지연시키려는 값을 나타낸다. 어떤 타입이든 가질 수 있다.

Returns

초기 렌더링 중, 반환된 ‘지연된 값’은 사용자가 제공한 값과 동일하다.
업데이트 발생 시 React는 먼저 이전 값으로 리렌더링을 시도하고 백그라운드에서 다시 새 값으로 리렌더링을 시도한다.

사용시 주의사항

  • useDeferredValue에 전달하는 값은 문자열 및 숫자와 같은 원시값이거나, 컴포넌트의 외부에서 생성된 객체여야 한다.
    렌더링 중에 새 객체를 생성하고 즉시 useDeferredValue에 전달하면 렌더링할 때마다 값이 달라져 불필요한 백그라운드 리렌더링이 발생할 수 있다.

  • useDeferredValue가 현재 렌더링 외에 다른 값(Object.is와 비교)을 받으면 백그라운드에서 새 값으로 다시 렌더링하도록 예약한다. 값에 대한 또 다른 업데이트가 있으면 백그라운드 리렌더링은 중단될 수 있으며 React는 백그라운드 리렌더링을 처음부터 다시 시작할 것이다.
    ex) 차트가 리렌더링 가능한 지연된 값을 받는 속도보다 사용자가 input에 값을 입력하는 속도가 더 빠른 경우, 차트는 사용자가 입력을 멈춘 후에만 다시 렌더링된다.

  • useDeferredValue<Suspense>와 통합됩니다. 새 값으로 인한 백그라운드 업데이트로 인해 UI가 일시 중단되면 사용자에게 폴백이 표시되지 않는다. 데이터가 로드될 때까지 기존의 지연된 값이 계속 표시된다.

  • useDeferredValue는 그 자체로 추가 네트워크 요청을 방지하지 않는다.

  • useDeferredValue 자체로 인한 고정된 지연은 없다. React가 원래의 리렌더링을 완료하자마자 React는 즉시 새로운 지연된 값으로 백그라운드 리렌더링 작업을 시작한다. 그러나 이벤트로 인한 업데이트(예: 타이핑)는 백그라운드 리렌더링을 중단하고 우선순위를 갖는다.

  • useDeferredValue로 인한 백그라운드 리렌더링은 화면에 커밋될 때까지 Effect를 실행하지 않는다. 백그라운드 리렌더링이 일시 중단되면 데이터가 로드되고 UI가 업데이트된 후에 해당 Effect가 실행된다.

사용법

1. 새 콘텐츠가 로드되는 동안 오래된 콘텐츠 표시하기

import { useState, useDeferredValue } from 'react';

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

초기 렌더링 시점에 지연된 값은 사용자가 제공한 값(value)과 동일하며 업데이트가 발생하면, 지연된 값은 최신 보다 “뒤쳐지게” 된다. React는 먼저 지연된 값을 업데이트하지 않은 채 렌더링한 다음, 백그라운드에서 새로 받은 값으로 다시 렌더링을 시도한다.

2. 콘텐츠가 오래되었음을 표시하기

위의 예에서는 최신 쿼리에 대한 결과 목록이 아직 로드 중이라는 표시가 없다. 새 결과를 로드하는 데 시간이 오래 걸리는 경우 오히려 사용자에게 혼란을 줄 수 있기 때문에
결과 목록이 최신 쿼리와 일치하지 않는다는 것을 사용자에게 더 명확하게 알리기 위해 오래된 결과 목록이 표시될 때 시각적 표시를 추가할 수 있다.

<div style={{
  opacity: query !== deferredQuery ? 0.5 : 1,
}}>
  <SearchResults query={deferredQuery} />
</div>

3. UI의 일부에 대해 리렌더링 연기하기

useDeferredValue를 성능 최적화로 적용할 수도 있다.
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리렌더링 속도가 빨라지지는 않는다.
하지만 키 입력을 차단하지 않도록 목록 리렌더링의 우선순위를 낮출 수 있다는 것을 React에 알려준다. 목록은 입력보다 지연되었다가 따라잡는다. 이전과 마찬가지로 React는 가능한 한 빨리 목록을 업데이트하려고 시도하지만, 사용자가 다시 입력하는 것을 차단하지는 않는다.

Share article

석우의 개발블로그