# [[React 기반 싱글 페이지 애플리케이션(SPA)의 렌더링 최적화|React 기반 싱글 페이지 애플리케이션(SPA)의 렌더링 최적화]]

## 📌 Brief Summary
React 기반 SPA의 렌더링 최적화는 브라우저의 중요 렌더링 경로([[Critical Rendering Path|Critical Rendering Path]])를 효율적으로 처리하고, 불필요한 DOM 조작 및 연산을 줄여 사용자와 상호작용하는 성능을 향상시키는 과정입니다 [1-3]. 가상 DOM(Virtual DOM)과 휴리스틱 비교(Diffing) 알고리즘을 통해 실제 DOM 업데이트를 최소화하며, Fiber 아키텍처 및 자동 배칭([[Automatic Batching|Automatic Batching]])으로 렌더링 작업을 스마트하게 스케줄링합니다 [4-8]. 최신 생태계에서는 수동 최적화의 한계를 극복하기 위해 React 컴파일러를 통한 자동 메모이제이션 및 React 서버 컴포넌트(RSC)를 활용해 클라이언트의 자바스크립트 번들 부담을 극적으로 줄이는 방향으로 발전하고 있습니다 [9-12].

## 📖 Core Content
*   **브라우저 렌더링 과정과 Reflow/Repaint 최소화**
    브라우저는 HTML과 CSS를 파싱하여 DOM과 [[CSSOM|CSSOM]]을 만들고 이를 결합해 렌더 트리([[Render Tree|Render Tree]])를 생성합니다 [13-15]. 이어서 요소의 정확한 크기와 위치를 계산하는 레이아웃(Layout 또는 Reflow) 단계와 화면에 픽셀을 그리는 페인트(Paint 또는 Repaint) 단계를 거칩니다 [16-18]. Reflow는 매우 연산 비용이 높고 하위 노드 전체로 파급 효과를 일으킬 수 있기 때문에, 불필요한 DOM 깊이를 줄이고, 레이아웃을 유발하는 속성(width, margin 등) 변경 대신 `transform`을 활용하여 렌더링 성능을 최적화해야 합니다 [17, 19-22].
*   **가상 DOM(Virtual DOM)과 재조정([[Reconciliation|Reconciliation]])**
    수동적인 실제 DOM 조작은 레이아웃과 페인트를 즉각적으로 유발하여 느리고 비효율적입니다 [4, 23]. React는 메모리에 가상 DOM이라는 경량화된 UI 구조를 생성한 뒤, 상태가 변경되면 O(n) 복잡도의 휴리스틱 Diffing 알고리즘을 사용해 이전 트리와 비교합니다 [4, 5, 7, 8, 24]. 이 과정을 통해 React는 바뀐 최소한의 DOM 노드나 속성만 실제 브라우저 DOM에 커밋(동기화)하여 리렌더링 오버헤드를 막습니다 [25, 26].
*   **Fiber 아키텍처와 동시성(Concurrent) 기능**
    대규모 앱에서 동기적 렌더링은 브라우저의 메인 스레드를 차단해 화면 응답성을 늦출 수 있습니다 [27-29]. 이를 해결하기 위해 React 16부터 도입된 Fiber 아키텍처는 작업을 작은 단위로 나누고([[Time-Slicing|Time-Slicing]]) 중요도에 따라 우선순위(Lanes)를 부여하여 작업을 중단하거나 재개할 수 있는 렌더 단계(Render Phase)를 구현했습니다 [25, 27, 30-32]. 더불어 `useTransition` 및 `[[useDeferredValue|useDeferredValue]]`와 같은 동시성 훅(Hooks)은 긴급한 사용자 상호작용이 무거운 비긴급 UI 업데이트 때문에 지연되지 않게 하여 반응성을 향상시킵니다 [33-35].
*   **리렌더링 캐스케이드(Cascade) 방지와 최적화 자동화**
    상태가 변할 때 부모가 리렌더링되면 모든 자식이 함께 리렌더링되는 문제는 큰 성능 낭비를 초래합니다 [36, 37]. 이를 최적화하기 위해 도입된 기능이 **자동 배칭(Automatic [[Batching|Batching]])**이며, Promise나 `setTimeout` 내의 여러 상태 업데이트를 단일 렌더링으로 묶어 DOM 렌더링 횟수를 대폭 줄입니다 [6, 38-40]. 또한 `React.memo`나 `useMemo` 같은 기존 수동 메모이제이션이 가진 유지보수 부담과 한계를 극복하기 위해, [[React 19|React 19]] 컴파일러는 빌드 타임에 AST를 분석해 최적의 지점에 자동으로 메모이제이션을 삽입하여 불필요한 렌더링을 차단합니다 [11, 41-45].
*   **초기 로드 속도 개선(Code Splitting 및 RSC 적용)**
    CSR 환경에서 큰 자바스크립트 번들은 초기 로딩(FCP, LCP)과 상호작용(INP)을 늦춥니다 [2, 46-48]. 따라서 `React.lazy()`를 이용한 라우트 단위의 코드 스플리팅(Code Splitting)과, 긴 목록에서 보이는 것만 렌더링하는 가상화(Virtualization) 기술은 체감 성능을 즉시 끌어올립니다 [49-51]. 나아가 React 서버 컴포넌트(RSC)를 채택하면, 데이터 페칭 및 렌더링을 서버 측에서 전담하여 클라이언트 자바스크립트 번들 크기에 0바이트를 기여하며, 클라이언트의 하이드레이션([[Hydration|Hydration]]) 비용을 완전히 제거할 수 있습니다 [9, 10, 52-54].

## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM|Virtual DOM]], Critical Rendering Path, Fiber Architecture, [[React Compiler|React Compiler]], React Server Components (RSC, Automatic Batching, [[Reflow and Repaint|Reflow and Repaint]]
- **Projects/Contexts:** [[Next.js|Next.js]], [[React 18|React 18]] & 19, Single-Page Applications (SPA)
- **Contradictions/Notes:** 
  - 상태 업데이트 병합 시, React 18의 자동 배칭(Automatic Batching)이 기본 적용되지만 폼 입력 등 즉각적인 반영이 필수적인 경우 `[[flushSync|flushSync]]`를 사용해 배칭을 의도적으로 우회(Opt-Out)하고 DOM 업데이트를 강제할 수 있습니다 [55-57]. 
  - 수동 메모이제이션 방식(`React.memo`, `useMemo`)은 남용할 경우 비교 연산 및 메모리 저장이라는 자체적인 비용(Overhead)으로 인해 오히려 렌더링보다 더 큰 지연을 유발할 수 있다고 주장됩니다 [41]. 하지만 React 19부터 도입된 [[React Compiler|React Compiler]]는 이를 빌드 도구가 정적 분석을 통해 자동으로 최적화해 주어, 오버-메모이제이션의 함정 없이 성능을 보장할 수 있다고 설명합니다 [11, 44, 58].

---
*Last updated: 2026-04-25*