84 lines
13 KiB
Markdown
84 lines
13 KiB
Markdown
---
|
|
category: Unified
|
|
tags: [auto-consolidated, technical-documentation]
|
|
title: [[React Performance Optimization|React Performance Optimization]]
|
|
last_updated: 2026-05-02
|
|
---
|
|
|
|
# [[React Performance Optimization|React Performance Optimization]]
|
|
|
|
## 📌 Brief Summary
|
|
React 성능 최적화는 브라우저의 렌더링 과정에서 발생하는 레이아웃 계산과 페인팅 비용을 최소화하고, 효과적인 렌더링 전략을 통해 애플리케이션의 반응성을 극대화하는 과정입니다 [1, 2]. 이를 위해 React는 가상 DOM([[Virtual DOM|Virtual DOM]])과 휴리스틱 Diffing 알고리즘, 그리고 Fiber 아키텍처를 도입하여 UI 업데이트를 효율적으로 관리합니다 [3-5]. 궁극적으로 개발자는 CSR, SSR, SSG와 같은 렌더링 방식을 서비스의 특성에 맞게 선택하고, 컴포넌트 기반 설계와 최적화 도구를 활용해 사용자 경험을 획기적으로 향상시킬 수 있습니다 [6, 7].
|
|
|
|
---
|
|
|
|
React 성능 최적화는 불필요한 연산과 재렌더링을 최소화하고 브라우저의 중요 렌더링 경로([[Critical Rendering Path|Critical Rendering Path]])를 효율적으로 관리하여 애플리케이션의 속도 및 응답성을 극대화하는 과정이다 [1, 2]. 이는 렌더링 계단식(Re-render Cascade) 문제 해결, 초기 번들 크기 감소, 리플로우(Reflow) 및 리페인트(Repaint) 제어를 주요 목표로 삼는다 [3-6]. 최근에는 React 18의 자동 배칭(Automatic Batching)과 [[React 19|React 19]] 컴파일러의 자동 메모이제이션 도입으로 인해, 개발자의 수동 최적화 부담이 크게 줄어들고 프레임워크 및 빌드 타임 레벨에서 성능 향상이 이루어지는 추세이다 [7-9].
|
|
|
|
---
|
|
|
|
> 가장 빠른 렌더링은 '하지 않는 렌더링'이다. 필요 없는 업데이트를 차단하고 데이터가 흐를 때만 화면이 출렁이게 하라.
|
|
|
|
## 📖 Core Content
|
|
* **브라우저 렌더링 과정 및 Reflow/Repaint 최소화:** 브라우저는 HTML과 CSS를 파싱하여 DOM과 [[CSSOM|CSSOM]]을 각각 생성하고, 이를 결합하여 화면에 표시될 요소만 담은 [[Render Tree|Render Tree]]를 구축합니다 [8-11]. 이후 각 요소의 정확한 크기와 위치를 계산하는 Layout(Reflow) 단계와 화면에 픽셀로 변환해 그리는 Paint(Repaint) 단계를 거칩니다 [12-15]. 직접적인 DOM 조작은 연산 비용이 높은 Reflow와 Repaint를 반복적으로 유발해 애플리케이션 성능을 저하시킵니다 [1, 16, 17]. 이를 방지하기 위해 CSS transform 속성을 활용하거나 불필요한 DOM 깊이를 줄이고, 리스트 렌더링 시 가상화 기법을 적용하는 최적화 방법이 권장됩니다 [13, 18-20].
|
|
* **[[DOM vs Virtual DOM|DOM vs Virtual DOM]]과 React의 속도 향상 메커니즘:** React는 실제 DOM을 직접 수정하는 대신, 메모리 내에 가벼운 객체 형태인 Virtual DOM을 유지합니다 [1, 5, 21, 22]. 상태가 변경되면 새로운 Virtual DOM을 만들고, 휴리스틱 기반의 O(n) Diffing 알고리즘을 통해 이전 트리와 비교([[Reconciliation|Reconciliation]])합니다 [3, 5, 23]. 이 알고리즘은 요소의 타입과 Key 속성을 바탕으로 변경된 최소한의 노드만 식별한 뒤 실제 DOM에 일괄 적용하므로, 불필요한 Reflow를 막고 렌더링 성능을 크게 높입니다 [3, 24, 25].
|
|
* **React 엔진 최적화 (Fiber 아키텍처 및 최근 기능):** React 16부터 도입된 Fiber 아키텍처는 렌더링 작업을 중단 및 재개 가능한 작은 '작업 단위'로 나누고, 우선순위(Lane 모델)에 따라 처리하는 동시성 렌더링([[Concurrent Rendering|Concurrent Rendering]])을 지원합니다 [4, 26-30]. 또한 React 18에 도입된 자동 일괄 처리(Automatic Batching)는 Promise, setTimeout 등의 비동기 작업 내 여러 상태 업데이트를 단일 리렌더링으로 묶어 효율성을 극대화합니다 [31-34]. 최근 도입된 [[React Compiler|React Compiler]]는 빌드 단계에서 구문 트리를 분석하여 수동 처리 없이 자동으로 메모이제이션을 삽입해 개발자의 성능 최적화 부담을 줄여줍니다 [35-38].
|
|
* **[[CSR vs SSR vs SSG|CSR vs SSR vs SSG]] 전략적 렌더링:**
|
|
* **CSR (Client-Side Rendering):** 브라우저가 빈 HTML과 [[JavaScript|JavaScript]]를 다운로드해 UI를 구성하며, 초기 로딩과 SEO에는 불리하지만 이후 빠르고 매끄러운 상호작용을 제공하여 단일 페이지 애플리케이션(SPA)에 적합합니다 [39-42].
|
|
* **SSR (Server-Side Rendering):** 서버에서 완전한 HTML을 미리 생성하여 브라우저에 전달하므로 초기 콘텐츠 렌더링(FCP)이 빠르고 SEO에 매우 유리합니다 [43-46].
|
|
* **SSG (Static Site Generation):** 빌드 시점에 모든 HTML을 미리 렌더링하여 CDN을 통해 즉시 제공하므로 가장 빠르지만, 실시간 데이터 반영이 어렵습니다 [47-50].
|
|
* **[[React Server Components (RSC)|React Server Components (RSC]]:** 오직 서버에서만 실행되어 클라이언트에 JavaScript 번들을 전혀 전송하지 않는 컴포넌트 구조로, 클라이언트 번들 크기를 대폭 줄이고 서버 리소스에 직접 접근할 수 있습니다 [51-54].
|
|
* **컴포넌트 기반 아키텍처 (CBA):** React의 핵심 설계 원칙으로, 애플리케이션을 독립적이고 캡슐화된 재사용 가능한 컴포넌트 단위로 나눕니다 [55-58]. 이는 시스템의 복잡성을 낮추고, 병렬 개발을 가능하게 하며, 특정 컴포넌트의 렌더링 주기만을 독립적으로 관리 및 최적화할 수 있도록 지원합니다 [59-64].
|
|
|
|
---
|
|
|
|
* **불필요한 재렌더링 방지 및 가상 DOM 최적화**
|
|
부모 컴포넌트의 상태가 변경될 때 모든 자식 컴포넌트가 재렌더링되는 '렌더링 계단식' 문제는 성능 저하의 주된 원인이다 [3, 10]. 이를 방지하기 위해 기존에는 `React.memo`, `useMemo`, `useCallback`과 같은 수동 메모이제이션 기법을 사용하여 참조([[Reference|Reference]])의 동등성을 유지하고 불필요한 비교(Diffing) 연산을 차단했다 [11-13]. 또한, React 18에 도입된 자동 배칭(Automatic [[Batching|Batching]])은 이벤트 핸들러뿐만 아니라 Promise나 `setTimeout` 같은 비동기 작업 내의 여러 상태 업데이트를 단일 렌더링으로 묶어주어 가상 DOM 작업과 렌더링 횟수를 획기적으로 줄여준다 [7, 14, 15].
|
|
|
|
* **빌드 타임 최적화: React 컴파일러([[React Compiler|React Compiler]])**
|
|
React 19 컴파일러는 애플리케이션 코드를 구문 분석(AST)하여 정적 값과 반응형 값을 자동으로 식별하고, 최적의 위치에 메모이제이션 경계를 삽입하는 빌드 타임 도구이다 [8, 9, 16, 17]. 이를 통해 개발자가 수동으로 의존성 배열을 관리하며 겪는 과도한 메모이제이션(Over-memoization)이나 누락 문제를 해결하고, 값이 변경된 특정 부분만 렌더링하는 세밀한 반응성(Fine-Grained Reactivity)을 달성하여 성능 최적화 작업의 90%를 제거한다 [18-20].
|
|
|
|
* **동시성 렌더링과 파이버(Fiber) 아키텍처**
|
|
React 16부터 도입된 파이버 아키텍처는 동기적으로 블로킹되던 기존 렌더링 방식을 벗어나, 렌더링 작업을 작은 단위로 나누고([[Time-Slicing|Time-Slicing]]) 우선순위(Lane Model)를 부여하여 중단 및 재개가 가능하도록 만들었다 [21-24]. 이를 기반으로 하는 `useTransition` 및 `[[useDeferredValue|useDeferredValue]]` 훅을 사용하면, 무거운 데이터 필터링이나 화면 전환 같은 비긴급 업데이트의 우선순위를 낮춤으로써 타이핑과 같은 긴급한 상호작용이 지연 없이 처리되도록 하여 UI의 응답성(INP 개선)을 높일 수 있다 [25-28].
|
|
|
|
* **브라우저 렌더링 최적화: Reflow와 Repaint 최소화**
|
|
React가 가상 DOM을 업데이트한 후, 브라우저가 화면을 그리는 과정에서 레이아웃 계산(Reflow)과 시각적 업데이트(Repaint)는 큰 비용을 수반한다 [5, 6, 29]. 렌더링 성능을 개선하려면 React Fragment를 사용해 불필요한 DOM 노드 래퍼를 줄이고 DOM의 깊이를 얕게 유지해야 한다 [30, 31]. 100개가 넘어가는 긴 리스트의 경우 화면에 보이는 노드만 렌더링하는 가상화(Virtualization) 라이브러리를 도입하여 다중 노드 생성 비용을 극적으로 줄일 수 있다 [32, 33]. 더불어 애니메이션 구현 시 레이아웃을 다시 계산하는 속성 대신 `transform` 속성 등을 활용해 GPU 가속을 적용하면 리플로우를 피할 수 있다 [34-36].
|
|
|
|
* **번들 사이즈 제어 및 렌더링 전략 고도화**
|
|
초기 로딩 속도(LCP)를 개선하려면 다운로드해야 할 [[JavaScript|JavaScript]] 번들 크기를 최소화해야 한다. `React.lazy()`를 활용한 라우트 레벨의 코드 스플리팅을 적용하면 초기 번들 크기를 30~50%가량 줄일 수 있다 [37]. 한 걸음 더 나아가 서버에서만 실행되는 React Server Components(RSC)를 활용하면 무거운 라이브러리나 정적 데이터 페칭 로직이 브라우저로 전송되지 않아 JavaScript 번들 크기를 '0 바이트'에 가깝게 줄이고 수화([[Hydration|Hydration]]) 비용을 완전히 제거할 수 있다 [38-40].
|
|
|
|
---
|
|
|
|
- **Memoization (메모이제이션)**:
|
|
- **React.memo**: 상위 컴포넌트가 변해도 내 Props가 같다면 그리기를 거부한다.
|
|
- **useMemo**: 비용이 큰 연산 결과(예: 복잡한 필터링)를 저장해두고 재사용한다.
|
|
- **useCallback**: 함수 객체의 변동을 막아 자식 컴포넌트의 불필요한 리렌더링을 방지한다.
|
|
- **Windowing (가상 리스트)**:
|
|
- 수천 개의 리스트 아이템이 있어도 사용자의 눈에 보이는 수십 개만 실제 DOM에 렌더링한다. (예: `react-window`, `react-virtualized`).
|
|
- **상태의 위치 선정 ([[State|State]] Colocation)**:
|
|
- 전역 상태가 바뀔 때마다 앱 전체가 들썩이지 않게 하라. 상태는 그것을 사용하는 가장 하위 컴포넌트 근처로 내려라.
|
|
|
|
## ⚖️ Trade-offs & Caveats
|
|
- 모든 곳에 `memo`를 쓰는 것은 메모리 낭비다. 리액트의 기본 렌더링 성능은 이미 매우 뛰어나다. 병목 현상이 '실제로 관측'될 때만 최적화를 적용하는 것이 원칙이다.
|
|
|
|
## 🔗 Knowledge Connections
|
|
- **Related Topics:** [[Critical Rendering Path|Critical Rendering Path]], Virtual DOM, React Fiber Architecture, [[React Compiler|React Compiler]], [[Hydration|Hydration]]
|
|
- **Projects/Contexts:** [[SPA (Single Page Application)|SPA (Single Page Application]], [[Next.js|Next.js]]
|
|
- **Contradictions/Notes:** SSR은 검색 엔진 최적화(SEO) 및 빠른 초기 콘텐츠 렌더링(FCP) 측면에서 유리하지만 [43, 65], 사용자가 시각적으로 완성된 페이지를 보더라도 클라이언트가 JavaScript 번들을 다운로드하고 실행하는 [[Hydration|Hydration]](수화) 과정이 완료되기 전까지는 상호작용이 불가능하므로, TTI(Time to Interactive) 지표에서는 CSR보다 수치가 낮게 나타나는 렌더링 병목 현상이 존재합니다 [66-69].
|
|
|
|
---
|
|
*Last updated: 2026-04-25*
|
|
|
|
---
|
|
|
|
- **Related Topics:** [[Virtual DOM|Virtual DOM]] (가상 DOM), Critical Rendering Path (중요 렌더링 경로), React Compiler (React 컴파일러), React Server Components (RSC), [[Concurrent Rendering|Concurrent Rendering]] (동시성 렌더링)
|
|
- **Projects/Contexts:** 코어 웹 바이탈([[Core Web Vitals|Core Web Vitals]]) 개선 프로젝트, 프론트엔드 컴포넌트 기반 아키텍처(CBA) 구축
|
|
- **Contradictions/Notes:** React 18의 자동 배칭(Automatic Batching) 기능은 기본적으로 활성화되어 렌더링 최적화에 기여하지만, 사용자가 즉각적인 시각적 피드백(예: 입력 포커스, 폼 값 즉각 업데이트)을 필요로 하는 경우에는 `[[flushSync|flushSync]]` API를 사용하여 의도적으로 배칭을 우회하고 동기적 렌더링을 강제해야 한다 [28, 41, 42]. 한편 기존 React 생태계에서는 `useMemo`와 같은 수동 최적화가 필수적이었으나, React 컴파일러 도입 이후에는 이들이 불필요해지며 의도적인 제어나 서드파티 라이브러리 대응과 같은 예외적 상황에서만 사용하는(Escape Hatch) 방식으로 패러다임이 바뀌고 있다 [19, 43-45].
|
|
|
|
---
|
|
*Last updated: 2026-04-25*
|
|
|
|
---
|
|
|
|
- Related: [[WebWorker_Performance|WebWorker_Performance]] , [[System_Debugging_Protocol|System_Debugging_Protocol]]
|
|
- Foundation: [[React_Mental_Model|React_Mental_Model]]
|