Back to blog
Apr 07, 2026
5 min read

React 동시성(Concurrency) 이해하기 — 1편: Fiber 아키텍처

리액트에서 Fiber 아키텍처를 통해 동시성이 실행되는 과정을 순서대로 이해해봅니다.

어려운 내용은 최대한 빼고 작성하였습니다. 머리로 그림을 그리듯 읽어가면 좋을 것 같습니다.

1. React란

React는 createRoot()를 통해 root 엘리먼트 하위에 JSX를 렌더링하는 UI 프레임워크입니다.

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

내부적으로 JSX는 React.createElement()로 변환되어 일반 객체(React 엘리먼트)가 되고, React는 이를 실제 DOM과 동기화합니다. 이 과정을 재조정(Reconciliation) 이라고 합니다.

JSX 작성

React.createElement() → React 엘리먼트(일반 객체)

Reconciliation (재조정) → 이전 트리와 비교

실제 DOM 업데이트

2. 왜 동시성이 필요했나

JavaScript는 싱글 스레드 언어입니다. 즉, 한 번에 하나의 작업만 처리할 수 있습니다.

React 16 이전의 재조정 방식은 Stack Reconciler 기반이었는데, 콜스택에 올라간 렌더링 작업은 끝날 때까지 중단이 불가능했습니다.

예를 들어, 검색창에 타이핑하면서 10,000개의 리스트를 필터링한다고 가정해봅시다.

[React 16 이전 — 블로킹 렌더링]

메인 스레드
┌─────────────────────────────────────┬───────┬───────┐
│    Rendering (Non-interruptible)    │ Ready │ Input │
└─────────────────────────────────────┴───────┴───────┘
0ms                                  2100ms       2300ms

→ 렌더링이 끝나야만 사용자 입력에 반응 가능
→ 그 사이 타이핑은 멈추거나 버벅임

렌더링이 메인 스레드를 점령하는 동안 사용자 입력은 큐에서 대기하고, 렌더링이 끝나야만 반응할 수 있었습니다.


3. Fiber 아키텍처 (React 16)

이 문제를 해결하기 위해 React 16에서 Fiber 아키텍처가 도입됩니다.

Fiber의 핵심은 렌더링 작업을 잘게 쪼갤 수 있다는 것입니다.

각 컴포넌트는 하나의 Fiber 노드가 되고, 이 노드들이 트리를 이루며 재조정 작업의 단위가 됩니다.

[Fiber 트리 구조]

        HostRoot

        <App />
        /      \
  <Header />  <Main />
                /    \
         <List />  <Footer />

         <Item />  →  <Item />  →  <Item />
         (child)     (sibling)    (sibling)

각 노드(Fiber)는 아래 정보를 가짐
├── 컴포넌트 정보 (type, props, state)
├── 트리 구조    (child, sibling, return)
└── 작업 상태   (어디까지 처리했는지)

React의 렌더링은 내부적으로 세 단계로 나뉩니다.

[React 렌더링 3단계]

  Render       Reconcile        Commit
┌──────────┐  ┌─────────────┐  ┌───────────┐
│ JSX →    │  │  Prev Tree  │  │ Changes   │
│ React    │→ │     vs      │→ │ Reflected │
│ Element  │  │  New Tree   │  │ in DOM    │
└──────────┘  └─────────────┘  └───────────┘
  (객체 생성)   (변경점 파악)   (DOM 업데이트)

Fiber는 이 과정을 단위별로 쪼개서 “여기까지 했다”를 기억할 수 있게 되었습니다.

[Fiber 도입 전 vs 후]

도입 전 (Stack Reconciler)
┌──────────────────────────────────┐
│ App → Header → Main → List → ... │  한 덩어리로 끝까지 실행
└──────────────────────────────────┘

도입 후 (Fiber Reconciler)
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ App  │ │Header│ │ Main │ │ List │  단위별로 쪼개서 실행
└──────┘ └──────┘ └──────┘ └──────┘
  ✓ 완료    ✓ 완료    진행중     대기중

          "여기까지 했다" 기억 가능

단, React 16~17에서는 이 구조를 갖췄지만 여전히 동기적(Sync)으로 순서대로 실행했습니다.

쪼갤 수 있는 구조는 마련됐지만, 우선순위를 부여하는 스케줄러는 아직 비활성화 상태였습니다.


4. 동시성 (React 18)

React 18에서는 Fiber 구조를 활용해 우선순위 기반 스케줄링이 본격적으로 활성화됩니다.

이것이 바로 동시성(Concurrency) 입니다.

[업데이트 우선순위]

긴급한 업데이트 (Urgent)
  └── 사용자 입력, 클릭, 키 입력
  └── 즉각 반응 필요 → 최우선 처리

전환 업데이트 (Transition)
  └── 검색 결과 렌더링, 필터링, 페이지 전환
  └── 잠깐 지연돼도 OK → 후순위 처리

이제 React는 렌더링 도중 더 긴급한 작업이 들어오면 기존 렌더링을 중단하고, 긴급한 작업을 먼저 처리한 뒤 돌아와서 재개합니다.

[React 17 vs React 18 타임라인]

React 17
메인 스레드
┌─────────────────────────────────────┬───────┬───────┐
│    Rendering (Non-interruptible)    │ Ready │ Input │
└─────────────────────────────────────┴───────┴───────┘

React 18
메인 스레드
┌────────┬───────┬────────┬───────┬────────┬───────┬──────────┐
│ Render │ Input │ Render │ Input │ Render │ Input │ Complete │
└────────┴───────┴────────┴───────┴────────┴───────┴──────────┘
  ↑                   ↑
렌더링 중단          긴급한 입력 처리 후 재개

startTransition을 사용하면 어떤 업데이트가 긴급하고, 어떤 게 전환인지 React에 알려줄 수 있습니다.

import { startTransition } from 'react';

// 긴급한 업데이트 — 즉시 반영
setInputValue(input);

// 전환 업데이트 — 후순위로 처리
startTransition(() => {
  setSearchQuery(input);
});

5. 오해하기 쉬운 포인트

“동시성 = 동시에 렌더링한다?”

아닙니다. JavaScript는 여전히 싱글 스레드입니다.

[동시성의 실제 동작]

     실제로 일어나는 일                    사용자 눈에 보이는 것
┌──────────────────────────┐        ┌──────────────────┐
│ Render (5ms)             │        │                  │
│ Input (2ms)              │   →    │  Responsive and  │
│ Render (5ms)             │        │    smooth UI!    │
│ Input (2ms)              │        │                  │
│ ...                      │        └──────────────────┘
└──────────────────────────┘
  빠르게 번갈아 실행 (싱글 스레드)

렌더링을 잘게 쪼개서 우선순위에 따라 빠르게 번갈아 실행하는 것이고, 사용자 눈에는 마치 동시에 처리되는 것처럼 보이는 겁니다.

마치 영화 필름처럼 — 사실은 연속된 사진인데, 빠르게 넘기면 움직이는 것처럼 보이는 것과 같습니다.


마치며

[1편 핵심 요약]

React 15 이전  →  Stack Reconciler
                  렌더링 = 한 덩어리, 중단 불가

React 16~17   →  Fiber 아키텍처 도입
                  렌더링을 Fiber 단위로 쪼갬
                  단, 여전히 동기적으로 실행

React 18      →  Concurrency 활성화
                  Fiber + 우선순위 스케줄러
                  중단 / 재개 / 폐기 가능

✨ 오해 바로잡기
  1. 동시성 ≠ 동시에 실행
  2. 동시성 = 우선순위에 따라 빠르게 번갈아 실행

2편에서는 이 동시성을 기반으로 한 Hydration과 Streaming SSR로 이어집니다.