노트

동시성 렌더링

Concurrent Rendering

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

쉽게 말하면

동시성 렌더링은 긴 숙제를 하다가도 전화가 오면 잠깐 펜을 내려놓고 먼저 받는 것과 같아요. 무거운 화면 갱신을 잘게 쪼개 두고, 타이핑 같은 급한 일을 먼저 처리해서 화면이 멈추지 않죠.

비유가 깨지는 곳 숙제와 달리 하던 렌더를 아예 버리고 다시 하기도 해요. 그래서 렌더는 여러 번 돌아도 괜찮게 순수해야 해요. 계산이 빨라지는 게 아니라 반응성을 지키려고 일의 순서를 바꾸는 거예요.

동시성 렌더링(Concurrent Rendering)은 React가 렌더를 중단·재개·폐기할 수 있게 하고, 업데이트에 우선순위를 매겨 급한 것(입력)을 먼저 처리하는 렌더링 방식이다. React 18에서 본격 도입됐고 Fiber가 그 기반이다.

  • 중단 가능한 렌더: 렌더를 작은 단위로 쪼개 사이사이에 브라우저에 제어권을 돌려준다. 긴 렌더가 메인 스레드를 오래 막지 않는다(타임 슬라이싱(Time Slicing), 이벤트 루프)
  • 우선순위: 타이핑·클릭 같은 긴급 업데이트가 무거운 결과 렌더보다 먼저 처리된다. 개발자는 useTransition과 useDeferredValue로 "급하지 않음"을 표시한다
  • 자동 배칭(Automatic Batching): React 18부터는 setTimeout, Promise, 네이티브 이벤트 안의 여러 setState도 한 번의 렌더로 묶인다. 이전에는 React 이벤트 핸들러 안에서만 묶였다
  • Suspense, 스트리밍 SSR, 선택적 하이드레이션이 같은 기반 위에서 동작한다
  • 대가: 렌더가 여러 번 돌거나 버려질 수 있으니 렌더는 순수해야 한다(React의 규칙과 렌더 순수성). React 밖의 스토어를 렌더 중에 읽으면 컴포넌트마다 다른 값을 보는 상태 찢어짐(Tearing)이 생길 수 있다

동시성은 "빠르게 계산"이 아니라 "반응성을 지키도록 일의 순서를 조정"하는 것이다. 사용자가 느끼는 응답성 기준은 도허티 임계·INP(Interaction to Next Paint)와 연결된다.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

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

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

  • useSyncExternalStore

    useSyncExternalStore는 React 밖에 있는 상태(외부 스토어(External Store), 브라우저 API(Application Programming Interface))를 구독해 컴포넌트와 동기화하는 훅이다. 동시성 렌더링(Concurrent Rendering)에서도 모든 컴포넌트가 같은 스냅샷을 보게 보장해 tearing을 막는다(React 18+).

  • React 서버 컴포넌트(RSC)

    React 서버 컴포넌트(React Server Components, RSC)는 서버에서만 실행되고, 컴포넌트 코드가 아니라 실행 결과(직렬화된 엘리먼트 트리)만 클라이언트로 보내는 컴포넌트다. Next.js App Router에서는 'use client'를 붙이지 않은 컴포넌트가 기본으로 서버 컴포넌트다.

  • Effect가 필요 없는 경우

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

  • Render Props 패턴

    Render Props는 무엇을 그릴지를 컴포넌트가 정하지 않고, prop으로 받은 함수가 정하게 하는 로직 재사용 패턴이다. 컴포넌트는 상태와 동작만 맡고 그 데이터를 함수에 넘긴다.

보기 옵션