Files
2nd/10_Wiki/Topics/Architecture/Concurrent_Rendering.md
T
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

5.3 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-concurrent-rendering Concurrent Rendering 10_Wiki/Topics verified self
React Concurrent
Concurrent Mode
React 18 Concurrent
none A 0.9 applied
react
concurrent
rendering
scheduler
transitions
2026-05-10 pending
language framework
typescript react

Concurrent Rendering

매 한 줄

"매 render 매 interruptible, prioritizable, abandonable". React 18 (2022) 에 stable. Fiber architecture (2017) 의 결실. 2026 현재 React 19+ 의 default; useTransition, useDeferredValue, Suspense, streaming SSR, React Compiler 매 모든 것 위에 빌드.

매 핵심

매 핵심 idea

  • Interruptible — render 중 high-priority work (input, animation) 매 들어오면 yield.
  • Concurrent (NOT parallel) — single-threaded JS 위에서 cooperative scheduling.
  • Time-slicing — 5ms chunk 매 yield to browser (scheduler package).
  • Multiple in-progress trees — current + work-in-progress; double buffering.
  • Lane-based priority — sync, default, transition, idle lane.

매 hook / API

  • useTransition — non-urgent update (filter, navigation).
  • useDeferredValue — debounce-like, 매 lower priority value.
  • startTransition — imperative version.
  • Suspense — async boundary, fallback UI.
  • use hook (React 19) — read promise during render.

매 응용

  1. Search-as-you-type — input 매 sync, list filter 매 transition.
  2. Tab switching — 매 instant feel, 매 expensive subtree 의 background render.
  3. SSR streaming — 매 progressive shell + island hydration.
  4. Route navigation — <Link> prefetch + transition.

💻 패턴

useTransition — heavy filter

function Search() {
  const [query, setQuery] = useState('');
  const [list, setList] = useState<Item[]>(allItems);
  const [isPending, startTransition] = useTransition();

  return (
    <>
      <input
        value={query}
        onChange={(e) => {
          setQuery(e.target.value);                    // urgent
          startTransition(() => {                       // non-urgent
            setList(allItems.filter(i => i.name.includes(e.target.value)));
          });
        }}
      />
      {isPending && <Spinner />}
      <List items={list} />
    </>
  );
}

useDeferredValue

function Page({ query }: { query: string }) {
  const deferred = useDeferredValue(query);
  return <ExpensiveResults query={deferred} />;
}

Suspense + use (React 19+)

function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise);  // suspends if pending
  return <h1>{user.name}</h1>;
}

<Suspense fallback={<Skeleton />}>
  <UserProfile userPromise={fetchUser(id)} />
</Suspense>

Streaming SSR (Next.js 15 / React 19)

// app/page.tsx
export default async function Page() {
  return (
    <>
      <Header />
      <Suspense fallback={<FeedSkeleton />}>
        <Feed />  {/* streamed once data ready */}
      </Suspense>
    </>
  );
}

React Compiler (2026, automatic memoization)

// no useMemo / useCallback needed — compiler inserts
function Cart({ items }: { items: Item[] }) {
  const total = items.reduce((s, i) => s + i.price, 0);  // auto-memoized
  return <div>{total}</div>;
}

Selective hydration

// chat panel hydrates first if user clicks it,
// even if header is still loading
<Suspense fallback={<Sk />}>
  <Header />
</Suspense>
<Suspense fallback={<Sk />}>
  <Chat />
</Suspense>

Cancel stale render (transition supersession)

// older transition automatically discarded when new one starts
startTransition(() => setQuery('a'));   // discarded
startTransition(() => setQuery('ab'));  // wins

매 결정 기준

상황 Approach
Input + heavy derived UI useTransition
External lib slow value useDeferredValue
Async data Suspense + use
SSR with slow data streaming + Suspense islands
Manual memoization (legacy) replace with React Compiler

기본값: React 19+ with Compiler; transitions for any non-urgent update.

🔗 Graph

🤖 LLM 활용

언제: identify component 매 transition 으로 wrap 할 후보, code review 매 missed Suspense boundary. 언제 X: scheduler internals 의 deep debug (need devtools profiler).

안티패턴

  • startTransition for urgent input: input lag.
  • No Suspense fallback: 매 entire tree freeze 까지 falling back.
  • Manual memoization with React Compiler: redundant + sometimes 더 느림.
  • Async setState in transition without race control: stale data.
  • Deferred value of huge object reference: 매 GC pressure.

🧪 검증 / 중복

  • Verified (React 18 release notes 2022, React 19 docs 2026, Acdlite/Sebastian Markbåge talks).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — full content with React 19 + Compiler patterns