---
type: note
kind: Explainer
title: useDeferredValue 의 보장 범위 — 값은 보장, 반영 시점은 미보장
tags: ['react', 'usedeferredvalue']
status: release
ctime: 2026-06-23
mtime: 2026-09-10
generated: { by: claude/opus-5, at: 2026-09-01T00:00:00Z }
verified: { by: claude/opus-5, at: 2026-08-21T00:00:00Z }
sources:
  - id: react-usedeferredvalue
    resource: https://react.dev/reference/react/useDeferredValue
    title: "useDeferredValue — React"
---

import AutoIframe from '@components/AutoIframe/AutoIframe.astro'

검색어를 치면 입력창은 바로 바뀌어야 하는데, 아래 무거운 목록까지 매번 다시 그리면 입력이 밀린다. `useDeferredValue(value)`는 같은 값을 **한 박자 늦게 따라오는 짝**으로 하나 더 만들어준다.

**언제**: 같은 값을 쓰는 무거운 목록이 입력마다 다시 그려져 입력이 밀릴 때.

**절차**

1. `useDeferredValue(value)` 로 늦은 짝을 만든다.
2. **입력창은 빠른 쪽, 무거운 목록은 늦은 쪽**을 쓴다.
3. 둘이 벌어진 구간(`isStale`)을 알린다 — 보통 화면을 흐리게 해서 아직 이전 값이라는 것을 알린다.

**확인**: 입력창이 즉시 반응하고, 손을 멈췄을 때 목록이 따라잡는가.

## 늦은 쪽이 보여주는 값을 믿어도 되나

**어떻게 동작하는지부터.** 글자를 하나 치면 React가 화면을 **두 번** 그린다. 첫 번째는 빠른 쪽만 새 값으로(`query`는 이미 `"ab"`인데 `deferredQuery`는 아직 `"a"`), 두 번째는 늦은 쪽까지 새 값으로. 두 번째 그리기는 **첫 번째가 끝나자마자** 시작한다 — 기다리는 시간 같은 건 없다. 그리는 도중에 글자를 더 치면 그때까지 그린 걸 버리고 **처음부터 다시** 그린다. 다 그려서 화면에 올리기 전까지는 아무것도 안 보이고 `useEffect`도 실행되지 않는다.[^react-deferred]

- **없는 값을 만들지 않는다** — 늦은 쪽이 보여주는 건 언제나 _내가 실제로 쳤던 것 중 하나_다. 지어내지 않는다.
- **결국 따라잡는다** — 손을 멈추면 따라잡는다. 계속 치는 동안은 다시 그리기가 반복해서 취소돼 **영영 못 따라잡을 수도 있는데, 고장이 아니라 의도된 동작이다.**

둘 다 위 동작에서 그대로 나온다 — **돌려줄 값을 새로 만드는 일이 없으니** 지어낼 수가 없고, **다시 그리기가 늘 최신 값에서 출발하니** 손을 멈추면 그 그리기가 끝까지 간다. **믿어도 된다. 다만 언제 따라잡을지는 모른다.**

**목록을 인라인으로 만들어도 늦은 쪽은 영향받지 않는다.** `items={data.map(...)}`처럼 써서 참조가 매번 새로 생겨도 상관없다 — 그 목록이 늦은 쪽 계산에 아예 안 들어가기 때문이다. 같은 상황에서 망가지는 건 useMemo 캐시 쪽이다 → [578](/memo/578)

<AutoIframe
  src="/iframe/two_clocks_deferred_vs_immediate.html"
  title="입력을 곧바로 따라가는 값과 뒤처지는 값의 두 시간축, 둘이 어긋난 구간이 isStale"
/>

[^react-deferred]: 두 단계 — *"First, React re-renders with the new `query` (`"ab"`) but with the old `deferredQuery` (still `"a"`) … In the background, React tries to re-render with **both** `query` and `deferredQuery` updated."* / 타이밍 — *"There is no fixed delay caused by `useDeferredValue` itself. As soon as React finishes the original re-render, React will immediately start working on the background re-render."* / 중단 — *"The background re-render is interruptible: if there's another update to the value, React will restart the background re-render from scratch."* / Effect — *"does not fire Effects until it's committed to the screen."* ([useDeferredValue — React](https://react.dev/reference/react/useDeferredValue))
