노트

useDeferredValue

useDeferredValue

프런트엔드#react · 연결된 개념 5개

쉽게 말하면

useDeferredValue는 값의 '조금 늦게 따라오는 복사본'을 주는 훅이에요. 검색창에 타자를 치면 글자는 바로 찍히고, 무거운 결과 목록은 손이 빌 때 따라 바뀌어서 입력이 버벅이지 않아요.

비유가 깨지는 곳 정해진 시간을 기다리는 디바운스가 아니라 우선순위로 미뤄요. 그래서 빠른 기기에선 거의 안 늦고, 네트워크 요청 수는 못 줄여요. 무거운 컴포넌트를 memo로 감싸야 효과가 나요.

useDeferredValue(value)는 값의 "지연된 버전"을 돌려주는 훅이다. 값이 바뀌면 React는 먼저 이전 값으로 긴급한 부분을 렌더하고, 새 값으로의 렌더는 낮은 우선순위로 백그라운드에서 한다.

const [query, setQuery] = useState('')
const deferredQuery = useDeferredValue(query)
<input value={query} onChange={e => setQuery(e.target.value)} />  // 즉시
<SearchResults query={deferredQuery} />                              // 늦게
const SearchResults = memo(function SearchResults({ query }) { /* 무거움 */ })
  • memo와 같이 써야 효과가 난다. 무거운 컴포넌트가 지연된 값에만 의존하고 memo로 감싸져 있어야 입력이 바뀌는 동안 다시 렌더되지 않는다(memo·useMemo·useCallback)
  • query !== deferredQuery이면 "갱신 중"이니 결과를 흐리게 보여 줄 수 있다. React 19부터 두 번째 인자로 첫 렌더용 초기값을 줄 수 있다

디바운스(Debounce)와 다른 점

디바운스useDeferredValue
기준시간(마지막 입력 후 300ms 등)우선순위
기기 차이빠른 기기도 똑같이 기다림빠른 기기는 거의 지연 없음
중단타이머가 울리면 끝까지 렌더새 값이 오면 진행 중 렌더를 버림
지연값 튜닝필요불필요
  • 네트워크 요청 수는 줄이지 못한다. "API(Application Programming Interface)를 N초에 한 번만" 같은 부수 효과 빈도 제어는 여전히 디바운스·스로틀(Throttle)이 맞다. 서버 쪽 제한은 요청 제한 (Throttling)
  • 이미 가진 값으로 하는 무거운 렌더를 매끄럽게 하는 도구다. 데이터 요청 지연에는 Suspense·useTransition이 더 맞는 경우가 많다
  • setState를 직접 감쌀 수 있으면 useTransition, props처럼 값만 받으면 useDeferredValue. 내부 메커니즘은 같다(동시성 렌더링)

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • use()로 Promise 읽기

    use()는 렌더 중에 Promise나 Context 같은 리소스의 값을 읽는 React 19 API(Application Programming Interface)다. Promise가 아직 pending이면 컴포넌트가 suspend되어 가장 가까운 suspense의 fallback이 보이고, 끝나면 그 값으로 다시 렌더된다. reject되면 가장 가까운 에러 경계(Error Boundary)로 던져진다.

  • 서버 렌더에서 훅이 하는 일

    서버 렌더(Server-Side Rendering, SSR)에서도 컴포넌트 함수는 실제로 호출되고, 그 안의 훅도 호출은 된다. 다만 서버에는 커밋(DOM 반영)이 없어서, 렌더 중 동기적으로 값을 계산하는 훅만 일하고 커밋 뒤에 도는 훅은 아무것도 하지 않는다. "이 훅은 클라이언트에서만 동작한다"는 말은 대개 "Effect 안의 일은 클라이언트에서만 일어난다"는 뜻이다.

  • 내부 가변성과 메모이제이션

    내부 가변성(Interior Mutability)은 객체나 함수의 참조는 그대로인데 안에 숨은 상태가 바뀌는 성질이다. React의 메모이제이션은 "입력이 다른 참조인가"만 보기 때문에, 참조가 같으면 내용이 바뀌어도 바뀌지 않았다고 판단한다. React 공식 문서는 이를 "겉모습은 같은데 몰래 내용물을 바꾸는 상자"에 비유한다.

  • Effect가 필요 없는 경우

    Effect는 외부 시스템과 동기화할 때 쓰는 탈출구(Escape Hatch)다. 렌더 중에 계산할 수 있는 값이나 사용자 이벤트 처리에 Effect를 쓰면 렌더가 한 번 더 일어나고 흐름이 꼬인다. React 공식 문서가 이런 경우를 따로 정리해 두었다.

  • Vue 3와 React 대응표

    React에 익숙한 개발자가 Vue 3(Composition API, script setup)를 빠르게 읽을 수 있게 짝지어 본 표. 가장 큰 차이는 Vue는 반응성(Reactivity)을 자동으로 추적해서 의존성 배열(Dependency Array)이 없다는 점이다.

보기 옵션