[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
+190 -74
View File
@@ -2,95 +2,211 @@
id: wiki-2026-0508-usedeferredvalue
title: useDeferredValue
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: []
aliases: [React useDeferredValue, Deferred Rendering, Stale-While-Revalidate Hook]
duplicate_of: none
source_trust_level: A
confidence_score: 0.92
tags: [uncategorized]
confidence_score: 0.9
verification_status: applied
tags: [react, hook, concurrent, performance, react-19]
raw_sources: []
last_reinforced: 2026-05-08
last_reinforced: 2026-05-10
github_commit: pending
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
tech_stack:
language: unspecified
framework: unspecified
language: typescript
framework: React 19
---
# [[useDeferredValue|useDeferredValue]]
# useDeferredValue
## 📌 한 줄 통찰 (The Karpathy Summary)
`useDeferredValue`는 무거운 연산이 진행되는 동안 즉각적인 사용자 피드백을 방해하지 않고 UI의 반응성을 유지할 수 있도록 돕는 [[React 19|React 19]]의 동시성 렌더링([[Concurrent Rendering|Concurrent Rendering]]) 훅입니다 [1-3]. 상태 업데이트 코드를 직접 제어할 수 없을 때 상태 대신 값 자체를 감싸는 방식으로 사용되며, 부모 컴포넌트로부터 props를 통해 값을 전달받을 때 특히 유용합니다 [4]. 이 훅을 사용하면 비긴급 업데이트를 지연시켜 메인 스레드가 긴급한 사용자 상호작용을 먼저 처리할 수 있게 함으로써 INP(Interaction to Next Paint) 점수를 개선합니다 [3].
## 한 줄
> **"매 useDeferredValue 의 핵심 = 'value 의 stale copy 의 keep 의 background 의 update'."**. React 18 (2022) 의 introduction 의 since 매 useTransition 의 sibling — but 매 ownership 의 invert: 매 value 의 you don't control (props / context). 2026 React 19 era 매 third-party state 의 (TanStack Query data, Zustand store) 의 smooth 의 render.
## 📖 구조화된 지식 (Synthesized Content)
* **동시성 렌더링과 반응성 유지:**
`useDeferredValue`는 긴급한 상호작용(타이핑, 클릭 등)과 긴급하지 않은 업데이트(대규모 목록 필터링, 차트 재계산 등)를 분리하여, 계산이 오래 걸리는 작업 중에도 UI가 멈추는(freezing) 것을 방지합니다 [2, 3]. 새로운 연산 결과가 준비될 때까지 React는 화면에 이전 결과를 계속 표시합니다 [3].
* **`[[useTransition|useTransition]]`과의 구조적 차이점:**
`useTransition`이 상태 업데이트(`set[[State|State]]`) 자체를 감싸는 훅이라면, `useDeferredValue`는 상태에서 파생된 값 자체를 감싸는 용도로 사용됩니다 [3, 4]. 외부 스토어나 부모 컴포넌트의 props를 통해 값이 전달되어 개발자가 상태 업데이트 코드를 직접 제어할 수 없을 때, 값이 렌더링에 소비되는 방식을 지연시키기 위한 더 나은 아키텍처적 선택입니다 [3, 4].
* **성능 및 우선순위 관리 적용:**
이 훅은 코드의 실행 속도 자체를 높이는 것이 아니라, UI가 더 빠르게 '느껴지도록' 만듭니다 [5]. React의 Lane 모델(우선순위 기반 시스템)과 연동되어 업데이트를 더 낮은 우선순위로 표시함으로써, 메인 스레드를 긴급한 작업에 우선적으로 할당합니다 [6].
* **성능 최적화 패턴:**
수만 개 이상의 항목이 포함된 대규모 목록 등을 처리할 때 `useMemo`와 함께 결합하여 사용하면, 사용자가 인지할 수 있는 지연(lag) 없이 매끄러운 렌더링을 달성할 수 있습니다 [3].
## 매 핵심
## 🔗 지식 연결 (Graph)
- **Related Topics:** [[Concurrent Rendering|Concurrent Rendering]], useTransition, Interaction to Next Paint (INP), [[Lane Model|Lane Model]]
- **Projects/Contexts:** [[React 19|React 19]], [[React Performance Optimization|React Performance Optimization]]
- **Contradictions/Notes:** 소스 내용에 모순은 없으며, `useDeferredValue`가 코드를 직접적으로 빠르게 만드는 것이 아니라 체감 속도와 UI 반응성(Responsiveness)을 개선하는 목적으로 설계되었다는 점이 강조되고 있습니다 [5].
---
*Last updated: 2026-04-25*
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
**언제 이 지식을 쓰는가:**
- *(TODO)*
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- **과거 데이터와의 충돌:** 없음
- **정책 변화:** 없음
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
### 매 Signature
```typescript
const deferredValue = useDeferredValue(value, initialValue?);
// initialValue (R19+): 매 first render 의 fallback
```
## 🤔 의사결정 기준 (Decision Criteria)
### 매 Mechanism
- 매 first render: deferredValue === value (or initialValue if 의 provided).
- 매 subsequent re-render with new value:
1. React 의 first re-render 의 with old deferredValue (urgent, cached).
2. Background 의 re-render 의 with new value (interruptible).
3. 매 commit 의 newer one 의 ready when.
- **isStale check**: `value !== deferredValue` → 매 pending state 의 indicate.
**선택 A를 써야 할 때:**
- *(TODO)*
### 매 vs useTransition
1. **Ownership**: useTransition 의 setter 의 own. useDeferredValue 의 value 의 from outside.
2. **Use case**: useTransition for 의 own state. useDeferredValue for 의 props / library state.
3. 매 둘 다 의 same scheduler 의 use.
**선택 B를 써야 할 때:**
- *(TODO)*
## 💻 패턴
**기본값:**
> *(TODO)*
### Pattern 1: Slow-rendering child 의 with prop value
```typescript
import { useDeferredValue, memo } from 'react';
## ❌ 안티패턴 (Anti-Patterns)
function SearchPage({ query }: { query: string }) {
const deferredQuery = useDeferredValue(query);
const isStale = query !== deferredQuery;
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
return (
<div style={{ opacity: isStale ? 0.5 : 1 }}>
<SearchResults query={deferredQuery} />
</div>
);
}
const SearchResults = memo(function SearchResults({ query }: { query: string }) {
// Expensive: filter 100k items
const items = expensiveFilter(query);
return <ul>{items.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
});
```
### Pattern 2: TanStack Query 의 smooth pagination
```typescript
import { useQuery } from '@tanstack/react-query';
import { useDeferredValue } from 'react';
function ProductList({ page }: { page: number }) {
const deferredPage = useDeferredValue(page);
const { data } = useQuery({
queryKey: ['products', deferredPage],
queryFn: () => fetchProducts(deferredPage),
});
const isStale = page !== deferredPage;
return (
<div style={{ opacity: isStale ? 0.6 : 1 }}>
{data?.map(p => <ProductCard key={p.id} {...p} />)}
</div>
);
}
```
### Pattern 3: React 19 initialValue (avoid first-render flash)
```typescript
function Chart({ data }: { data: DataPoint[] }) {
// initialValue: 의 first render 의 empty 의 use, then 의 background 의 real data
const deferredData = useDeferredValue(data, []);
return <HeavyChart data={deferredData} />;
}
```
### Pattern 4: Combine 의 useTransition (own state) + useDeferredValue (derived)
```typescript
function App() {
const [filter, setFilter] = useState('');
const [isPending, startTransition] = useTransition();
return (
<>
<input
value={filter}
onChange={(e) => startTransition(() => setFilter(e.target.value))}
/>
<ChildList filter={filter} isPending={isPending} />
</>
);
}
// Inside library / external component 의 ChildList 의 only props 의 receive
function ChildList({ filter }: { filter: string }) {
const deferred = useDeferredValue(filter);
return <ExpensiveList filter={deferred} />;
}
```
### Pattern 5: Stale indicator with useDeferredValue
```typescript
function Autocomplete({ input }: { input: string }) {
const deferredInput = useDeferredValue(input);
const suggestions = computeSuggestions(deferredInput);
const isStale = input !== deferredInput;
return (
<ul aria-busy={isStale}>
{suggestions.map(s => <li key={s}>{s}</li>)}
{isStale && <li className="loading">Updating...</li>}
</ul>
);
}
```
### Pattern 6: With memo 의 critical
```typescript
// memo() 의 X → useDeferredValue 의 useless (re-render every time anyway)
const Heavy = memo(function Heavy({ value }: { value: string }) {
// Expensive render
return <ComplexViz data={value} />;
});
function Parent({ live }: { live: string }) {
const deferred = useDeferredValue(live);
return <Heavy value={deferred} />; // memo 의 only re-render when 'value' prop changes
}
```
### Pattern 7: Server Component data 의 defer (RSC + Suspense)
```typescript
'use client';
import { useDeferredValue, use, Suspense } from 'react';
function ClientWrapper({ promise }: { promise: Promise<Data> }) {
const deferredPromise = useDeferredValue(promise);
return (
<Suspense fallback={<Skeleton />}>
<Resolved promise={deferredPromise} />
</Suspense>
);
}
function Resolved({ promise }: { promise: Promise<Data> }) {
const data = use(promise); // R19 use() hook
return <DataView data={data} />;
}
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Expensive render of incoming prop | useDeferredValue + memo |
| Library state (TanStack Query, etc.) | useDeferredValue |
| 매 own state setter | useTransition |
| Throttle / debounce input value | lodash.debounce — useDeferredValue 의 X |
| First-render empty placeholder | useDeferredValue with initialValue (R19) |
**기본값**: useDeferredValue + memoized child whenever 의 prop change 의 trigger 의 expensive render.
## 🔗 Graph
- 부모: [[React-Hooks]] · [[Concurrent-React]]
- 변형: [[useTransition]] · [[useMemo]] · [[useSyncExternalStore]]
- 응용: [[Search-UI]] · [[Data-Visualization]]
- Adjacent: [[memo]] · [[Suspense]] · [[React-19-use-Hook]]
## 🤖 LLM 활용
**언제**: identify 의 candidate prop 의 deferral / suggest 의 memo wrapping / migrate 의 throttle 의 useDeferredValue.
**언제 X**: 매 measurement 의 X — 매 Profiler 의 first.
## ❌ 안티패턴
- **No memo on child**: 매 deferred value 의 effect 의 X → child 의 every parent render 의 re-render.
- **Use as throttle**: 매 rate limiting 의 X — 매 latest value 의 always 의 catch up.
- **Defer urgent values**: search input 의 own value 의 defer → input 의 lag.
- **Forget isStale UX**: 매 user feedback 의 없이 → 매 perceived bug.
- **Defer non-expensive value**: 매 simple string render 의 defer → 의 unnecessary complexity.
## 🧪 검증 / 중복
- Verified: react.dev/reference/react/useDeferredValue (React 19), React 19 release notes.
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — canonical useDeferredValue reference (React 19) |