feat: wikify new knowledge on browser main thread optimization and time slicing

This commit is contained in:
Antigravity Agent
2026-04-25 23:42:46 +09:00
parent d53665ae7a
commit 714e10c994
43 changed files with 1138 additions and 0 deletions
@@ -0,0 +1,28 @@
# [[Automatic Batching을 통한 React 18 성능 최적화]]
## 📌 Brief Summary
Automatic Batching은 React 18에서 도입된 성능 최적화 기능으로, 여러 상태(state) 업데이트를 단일 리렌더링으로 묶어서 처리합니다 [1-3]. 이전 버전과 달리 프로미스(Promises), `setTimeout`, 비동기 작업 등 업데이트 출처에 관계없이 모든 상태 변경을 일괄 처리하여 불필요한 리렌더링을 방지합니다 [4-6]. 이를 통해 Virtual DOM의 비교(diffing) 작업을 최소화하고 애플리케이션의 성능과 UI 응답성을 크게 향상시킵니다 [1, 4, 7].
## 📖 Core Content
* **작동 원리 및 이전 버전과의 차이점:**
React 18 이전에는 `onClick`이나 `onChange` 같은 네이티브 React 이벤트 핸들러 내에서 발생하는 상태 업데이트만 일괄 처리(배칭)되었으며, `setTimeout`이나 Promise와 같은 비동기 작업에서는 각 업데이트마다 개별적인 리렌더링이 발생했습니다 [2, 6]. 하지만 React 18부터는 자동 배칭(Automatic Batching)이 기본으로 활성화되어, 비동기 작업이나 타임아웃 등 모든 환경에서의 상태 업데이트를 하나의 렌더링 사이클로 그룹화합니다 [4, 5, 8].
* **성능 향상 및 Virtual DOM 최적화:**
여러 상태 변경을 하나로 결합함으로써 React는 Virtual DOM의 diffing 연산과 불필요한 DOM 업데이트 횟수를 최소화합니다 [1, 4, 7]. 실제 데이터 집약적인 대시보드를 대상으로 한 벤치마크 결과에 따르면, 자동 배칭을 활성화할 경우 최대 부하 상태에서 총 렌더링 횟수가 약 40% 감소하고 프레임 속도는 25% 향상되는 성능 개선을 보였습니다 [1, 9]. 이는 깊게 중첩된 컴포넌트를 가진 복잡한 애플리케이션에서 특히 유용합니다 [10].
* **렌더링 제어 API (`flushSync` 및 `startTransition`):**
자동 배칭이 기본 동작이지만, React는 렌더링 시점을 제어할 수 있는 API를 제공합니다 [9, 11].
* `flushSync`: 폼 입력값을 즉시 업데이트하여 사용자에게 지연 없이 보여주거나, 상태 변경 직후 DOM 요소를 포커스 및 측정해야 할 때 자동 배칭을 우회하여 동기적 리렌더링을 강제합니다 [9, 12, 13].
* `startTransition`: 리스트 필터링과 같이 긴급하지 않은 상태 업데이트를 표시하여 타이핑이나 클릭 등 우선순위가 높은 상호작용을 차단하지 않도록 양보(yield)합니다 [9, 12].
* **모니터링 및 베스트 프랙티스:**
성능 최적화를 극대화하려면 관련된 업데이트를 같은 이벤트 내에 그룹화하고 함수형 상태 업데이트(`setState(prev => new)`)를 사용하는 것이 좋습니다 [14]. 예상치 못한 리렌더링이 발생한다면 타사 라이브러리가 React의 이벤트 시스템을 우회하고 있지 않은지 확인해야 하며, React DevTools Profiler를 통해 상호작용에 따른 렌더링 횟수와 업데이트 원인을 디버깅하고 모니터링할 수 있습니다 [15-17].
## 🔗 Knowledge Connections
- **Related Topics:** `[[Virtual DOM]]`, `[[flushSync]]`, `[[startTransition]]`, `[[Concurrent Rendering]]`, `[[useMemo / useCallback]]`
- **Projects/Contexts:** `[[데이터 집약적 대시보드 성능 최적화]]`, `[[React 18 애플리케이션 마이그레이션]]`
- **Contradictions/Notes:** 자동 배칭은 대부분의 경우 렌더링 성능을 개선하지만, 즉각적인 DOM 반영이 필요한 예외 상황에서는 방해가 될 수 있습니다. 이 경우 `flushSync`를 사용해 강제로 배칭을 해제할 수 있으나, 이를 남용할 경우 배칭으로 얻는 성능상 이점이 무효화될 수 있으므로 극히 제한적으로 사용해야 한다고 경고하고 있습니다 [11, 12, 14].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,24 @@
# [[React 18 자동 일괄 처리 및 React 19 컴파일러 최적화 적용]]
## 📌 Brief Summary
React 18의 자동 일괄 처리(Automatic Batching)와 React 19의 컴파일러(React Compiler)는 애플리케이션의 렌더링 성능을 극대화하고 개발자의 부담을 줄이기 위한 핵심 아키텍처 변화입니다. 자동 일괄 처리는 여러 상태 업데이트를 단일 리렌더링으로 묶어 가상 DOM의 비교 연산을 최소화합니다. React 19 컴파일러는 빌드 타임에 코드를 분석하여 수동으로 수행하던 메모이제이션 작업을 자동으로 처리함으로써, 불필요한 연쇄 렌더링을 세밀하게 방지합니다.
## 📖 Core Content
**React 18 자동 일괄 처리 (Automatic Batching)**
* **작동 원리 및 변화:** React 18 이전에는 React 이벤트 핸들러 내에서 발생하는 상태 업데이트만 일괄 처리(Batching)의 대상이었습니다 [1, 2]. 그러나 React 18부터는 프로미스(Promise), `setTimeout`, 비동기 API 호출, 네이티브 이벤트 핸들러 등 출처와 상관없이 동일한 이벤트 루프 내에서 발생하는 모든 상태 업데이트를 자동으로 묶어서 한 번만 리렌더링합니다 [3-6].
* **성능 향상:** 이 기능은 가상 DOM(Virtual DOM)의 diffing 횟수를 줄여 CPU 작업량을 크게 감소시킵니다 [4]. 벤치마크 결과에 따르면, 데이터 집약적인 대시보드에서 자동 일괄 처리를 활성화할 경우 총 렌더링 횟수가 최대 40% 감소하고 피크 로드 시 프레임 속도가 25% 향상되는 성능 이점을 보였습니다 [3, 7].
* **예외 처리 (Opt-out):** 개발자가 즉각적인 DOM 업데이트를 보장받아야 하는 상황(예: 입력 후 즉시 포커스 이동)에서는 `flushSync` API를 사용하여 자동 일괄 처리를 건너뛰고 동기적으로 렌더링을 강제할 수 있습니다 [7-10].
**React 19 컴파일러 최적화 (React Compiler)**
* **수동 메모이제이션의 한계 해결:** 이전에는 렌더링 최적화를 위해 개발자가 `useMemo`, `useCallback`, `React.memo`를 수동으로 적용해야 했습니다 [11, 12]. 이는 인지적 부담을 가중시키고 의존성 배열(dependency array)을 잘못 설정하거나 참조 동일성(referential equality)을 놓쳐 최적화가 깨지는 등 유지보수 문제를 유발했습니다 [13, 14].
* **빌드 타임 자동화 및 AST 분석:** React 19 컴파일러(구 React Forget)는 빌드 도구 단계에서 코드의 추상 구문 트리(AST)를 분석하여 데이터 흐름을 추적합니다 [15, 16]. 코드를 정적 값(Static)과 반응형 값(Reactive)으로 분류하고, 최적의 위치에 자동으로 메모이제이션 경계를 삽입하여 렌더링 최적화 작업의 상당 부분을 제거합니다 [15-17].
* **세밀한 캐싱 (Granular Optimization):** 컴파일러는 전체 컴포넌트를 래핑하는 대신 `<h2>`, `<button>`과 같은 개별 JSX 요소와 특정 계산식들을 독립적으로 분리하여 캐싱합니다 [18, 19]. 결과적으로 속성(Props)이나 상태가 변경되지 않은 하위 컴포넌트의 불필요한 연쇄 리렌더링을 매우 정밀하게 차단합니다 [15, 20].
* **도입 효과:** 수동 메모이제이션 없이도 동일하거나 그 이상의 성능을 제공하며, 상호작용 속도(Interaction to Next Paint, INP)를 크게 개선합니다. 실제로 Meta의 프로덕션 적용 테스트에서 렌더링 횟수 60% 감소 및 사용자 상호작용 속도 2.5배 향상 등의 효과가 입증되었습니다 [21, 22].
## 🔗 Knowledge Connections
- **Related Topics:** [[가상 DOM (Virtual DOM) 및 Diffing 알고리즘]], [[수동 메모이제이션 (useMemo, useCallback, React.memo)]], [[flushSync 및 startTransition]], [[동시성 렌더링 (Concurrent Rendering)]]
- **Projects/Contexts:** [[대규모 데이터 대시보드 성능 최적화]], [[Meta의 프로덕션(Instagram, Quest Store) 최적화 도입 사례]]
- **Contradictions/Notes:** React 컴파일러가 대부분의 수동 메모이제이션을 대체하지만, 매 렌더링마다 새로운 객체 참조를 반환하는 서드파티 라이브러리를 사용할 경우 자동 메모이제이션 체인이 깨질 수 있으므로 이러한 특정 상황에서는 여전히 수동 메모이제이션(`useMemo`, `useCallback`)이 필요할 수 있습니다 [23-25].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,26 @@
# [[React 기반 싱글 페이지 애플리케이션(SPA)의 렌더링 최적화]]
## 📌 Brief Summary
React 기반 SPA의 렌더링 최적화는 브라우저의 중요 렌더링 경로(Critical Rendering Path)를 효율적으로 처리하고, 불필요한 DOM 조작 및 연산을 줄여 사용자와 상호작용하는 성능을 향상시키는 과정입니다 [1-3]. 가상 DOM(Virtual DOM)과 휴리스틱 비교(Diffing) 알고리즘을 통해 실제 DOM 업데이트를 최소화하며, Fiber 아키텍처 및 자동 배칭(Automatic Batching)으로 렌더링 작업을 스마트하게 스케줄링합니다 [4-8]. 최신 생태계에서는 수동 최적화의 한계를 극복하기 위해 React 컴파일러를 통한 자동 메모이제이션 및 React 서버 컴포넌트(RSC)를 활용해 클라이언트의 자바스크립트 번들 부담을 극적으로 줄이는 방향으로 발전하고 있습니다 [9-12].
## 📖 Core Content
* **브라우저 렌더링 과정과 Reflow/Repaint 최소화**
브라우저는 HTML과 CSS를 파싱하여 DOM과 CSSOM을 만들고 이를 결합해 렌더 트리(Render Tree)를 생성합니다 [13-15]. 이어서 요소의 정확한 크기와 위치를 계산하는 레이아웃(Layout 또는 Reflow) 단계와 화면에 픽셀을 그리는 페인트(Paint 또는 Repaint) 단계를 거칩니다 [16-18]. Reflow는 매우 연산 비용이 높고 하위 노드 전체로 파급 효과를 일으킬 수 있기 때문에, 불필요한 DOM 깊이를 줄이고, 레이아웃을 유발하는 속성(width, margin 등) 변경 대신 `transform`을 활용하여 렌더링 성능을 최적화해야 합니다 [17, 19-22].
* **가상 DOM(Virtual DOM)과 재조정(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) 중요도에 따라 우선순위(Lanes)를 부여하여 작업을 중단하거나 재개할 수 있는 렌더 단계(Render Phase)를 구현했습니다 [25, 27, 30-32]. 더불어 `useTransition``useDeferredValue`와 같은 동시성 훅(Hooks)은 긴급한 사용자 상호작용이 무거운 비긴급 UI 업데이트 때문에 지연되지 않게 하여 반응성을 향상시킵니다 [33-35].
* **리렌더링 캐스케이드(Cascade) 방지와 최적화 자동화**
상태가 변할 때 부모가 리렌더링되면 모든 자식이 함께 리렌더링되는 문제는 큰 성능 낭비를 초래합니다 [36, 37]. 이를 최적화하기 위해 도입된 기능이 **자동 배칭(Automatic Batching)**이며, Promise나 `setTimeout` 내의 여러 상태 업데이트를 단일 렌더링으로 묶어 DOM 렌더링 횟수를 대폭 줄입니다 [6, 38-40]. 또한 `React.memo``useMemo` 같은 기존 수동 메모이제이션이 가진 유지보수 부담과 한계를 극복하기 위해, 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) 비용을 완전히 제거할 수 있습니다 [9, 10, 52-54].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Critical Rendering Path]], [[Fiber Architecture]], [[React Compiler]], [[React Server Components (RSC)]], [[Automatic Batching]], [[Reflow and Repaint]]
- **Projects/Contexts:** [[Next.js]], [[React 18 & 19]], [[Single-Page Applications (SPA)]]
- **Contradictions/Notes:**
- 상태 업데이트 병합 시, React 18의 자동 배칭(Automatic Batching)이 기본 적용되지만 폼 입력 등 즉각적인 반영이 필수적인 경우 `flushSync`를 사용해 배칭을 의도적으로 우회(Opt-Out)하고 DOM 업데이트를 강제할 수 있습니다 [55-57].
- 수동 메모이제이션 방식(`React.memo`, `useMemo`)은 남용할 경우 비교 연산 및 메모리 저장이라는 자체적인 비용(Overhead)으로 인해 오히려 렌더링보다 더 큰 지연을 유발할 수 있다고 주장됩니다 [41]. 하지만 React 19부터 도입된 React Compiler는 이를 빌드 도구가 정적 분석을 통해 자동으로 최적화해 주어, 오버-메모이제이션의 함정 없이 성능을 보장할 수 있다고 설명합니다 [11, 44, 58].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,40 @@
# [[React 기반 프론트엔드 성능 최적화]]
## 📌 Brief 시 Summary
React 기반 프론트엔드 성능 최적화는 불필요한 연산과 네트워크 페이로드를 최소화하여 빠르고 반응성 높은 사용자 경험을 제공하기 위한 일련의 기술적 접근이다 [1, 2]. 브라우저의 렌더링 경로(CRP)에서 발생하는 병목 현상을 줄이는 기초적인 최적화부터, 가상 DOM(Virtual DOM)의 재조정(Reconciliation) 과정과 리렌더링을 제어하는 React 고유의 최적화 기법을 포괄한다 [2-4]. 현대의 React는 Fiber 아키텍처, 자동 배칭, React Compiler를 통한 자동 메모이제이션, 그리고 React Server Components(RSC)를 활용하여 LCP, INP, CLS와 같은 핵심 웹 지표(Core Web Vitals)를 개선하고 애플리케이션의 성능을 극대화한다 [1, 5-9].
## 📖 Core Content
**1. 브라우저 렌더링 과정 (Critical Rendering Path) 및 Reflow/Repaint 최소화**
브라우저가 화면을 그리는 렌더링 경로는 HTML 파싱을 통한 **DOM 트리 생성**, CSS 파싱을 통한 **CSSOM 트리 생성**, 이 둘을 결합한 **Render Tree 생성**, 요소의 크기와 위치를 계산하는 **Layout(Reflow)**, 픽셀을 화면에 그리는 **Paint(Repaint)**, 그리고 레이어를 합성하는 **Compositing** 단계로 이루어진다 [10-13].
* **Reflow (Layout):** 요소의 크기(width, height)나 위치, 여백(margin, padding)이 변경될 때 발생하며, 문서 내 다른 요소들의 기하학적 구조까지 다시 계산해야 하므로 연산 비용이 매우 크다 [12, 14, 15]. DOM 노드의 깊이를 줄이고 레이아웃 스래싱(Layout Thrashing)을 방지하는 것이 중요하다 [14, 16].
* **Repaint (Paint):** 배경색(background-color), 그림자(box-shadow) 등 시각적 속성만 변경될 때 발생하며 레이아웃 변경은 수반하지 않으나, 과도하게 발생할 경우 렌더링 파이프라인을 방해할 수 있다 [14, 17, 18].
* **최적화 방법:** Reflow와 Repaint를 최소화하기 위해 DOM 상호작용을 줄이고, 애니메이션 구현 시 `top`이나 `left` 대신 GPU 가속을 받을 수 있는 `transform` 속성을 사용하는 것이 권장된다 [18-21].
**2. React가 빠른 이유: Virtual DOM과 재조정(Reconciliation)**
React는 실제 DOM을 직접 조작하는 것의 비효율성을 극복하기 위해 메모리 내에 가벼운 UI 표현인 **가상 DOM(Virtual DOM)**을 유지한다 [22, 23]. 상태가 변경되면 React는 새로운 가상 DOM 트리를 생성하고 이전 트리와 비교(Diffing)하여 변경된 부분만 실제 DOM에 적용한다 [22, 23]. 이 "재조정" 과정은 $O(n^3)$의 복잡도를 가지는 기존 트리 비교 알고리즘 대신, 요소의 타입이 다르면 트리를 완전히 새로 구축하고 리스트에서는 `key` prop을 통해 요소를 추적하는 휴리스틱 기반의 **$O(n)$ 최적화 알고리즘**을 사용하여 처리 속도를 비약적으로 높였다 [24-27].
**3. Fiber 아키텍처와 동시성 렌더링(Concurrent Rendering)**
React 16부터 도입된 **Fiber 아키텍처**는 기존의 동기적이고 차단적인 렌더링을 개선하기 위해 렌더링 작업을 중단하고 재개할 수 있는 '작업 단위(Unit of Work)'로 분할한다 [28-30].
* **렌더 단계(Render Phase):** 부수 효과(Side effect) 없이 가상 DOM 트리를 순회하며 변경 사항을 계산하는 단계로, 높은 우선순위의 작업이 들어오면 언제든 중단되거나 재시작될 수 있다 [31, 32].
* **커밋 단계(Commit Phase):** 계산된 변경 사항을 실제 DOM에 동기적으로 한 번에 적용하며, 이 단계는 중단할 수 없다 [32, 33].
Fiber는 우선순위 시스템(Lanes)을 통해 사용자 입력과 같은 긴급한 작업을 데이터 페칭 같은 덜 긴급한 작업보다 먼저 처리할 수 있게 한다 [34, 35]. React 19의 `useTransition``useDeferredValue` 훅은 이 아키텍처를 활용하여 무거운 연산 중에도 메인 스레드를 차단하지 않고 UI 반응성(INP 지표)을 유지하는 동시성 기능을 제공한다 [36-38].
**4. 리렌더링 통제와 React Compiler의 도입**
컴포넌트의 상태가 변경될 때마다 하위 트리의 모든 컴포넌트가 다시 렌더링되는 '리렌더링 폭포(Re-render Cascade)' 현상은 React 성능 저하의 주요 원인이다 [4, 39].
* **수동 메모이제이션:** 기존에는 이를 막기 위해 `React.memo`, `useMemo`, `useCallback`을 사용하여 props가 변경되지 않았을 때의 렌더링을 수동으로 차단했다 [40-42]. 하지만 이 방식은 코드 복잡도를 높이고 참조 일치성 관리에 따른 잦은 실수를 유발했다 [43].
* **React Compiler (자동 메모이제이션):** React 19부터 도입된 React Compiler는 빌드 타임에 AST(추상 구문 트리)를 분석하여 데이터 흐름을 파악하고, 필요한 곳에 자동으로 메모이제이션 경계를 삽입한다 [8, 9, 44, 45]. 이를 통해 개발자는 성능 최적화 코드를 직접 작성하지 않아도 세밀한 반응성(Fine-Grained Reactivity)을 얻어 최대 60% 이상의 불필요한 리렌더링을 줄일 수 있다 [8, 46, 47].
* **자동 배칭(Automatic Batching):** React 18부터는 Promise나 setTimeout 같은 비동기 콜백 내에서 여러 상태 업데이트가 발생하더라도 이를 묶어 단 한 번의 리렌더링만 트리거하는 자동 배칭이 기본적으로 적용되어 성능을 최적화한다 [7, 48-50].
**5. 렌더링 전략의 진화 (CSR vs SSR vs SSG vs RSC)**
* **CSR (Client-Side Rendering):** 자바스크립트를 다운로드한 후 브라우저에서 UI를 렌더링하므로 상호작용이 빠르지만, 초기 로드(FCP)가 느리고 SEO에 불리하다 [51-53].
* **SSR (Server-Side Rendering) & SSG (Static Site Generation):** 서버에서 HTML을 완성하여 전송해 초기 표시 속도와 SEO를 개선한다 [54-56]. 브라우저는 HTML을 화면에 그린 후, 자바스크립트를 실행해 이벤트 리스너를 연결하는 **Hydration** 과정을 거쳐 페이지를 상호작용 가능하게 만든다 [54, 57-59].
* **React Server Components (RSC):** 서버에서만 실행되고 클라이언트로 자바스크립트 코드를 일절 보내지 않는(Zero-Bundle) 새로운 컴포넌트 패러다임이다 [60-63]. 무거운 데이터 페칭이나 정적인 UI 렌더링을 서버가 전담하므로, 번들 크기를 비약적으로 줄이고 Hydration 비용 자체를 제거하여 성능을 극대화한다 [62, 64, 65]. 대규모 애플리케이션에서는 서버 컴포넌트와 클라이언트 컴포넌트를 혼합하여 각 실행 환경의 장점을 모두 취할 수 있다 [62, 66].
## 🔗 Knowledge Connections
- **Related Topics:** [[Critical Rendering Path]], [[Virtual DOM]], [[React Fiber Architecture]], [[Hydration]], [[React Compiler]], [[React Server Components]]
- **Projects/Contexts:** [[Next.js 기반 하이브리드 렌더링 (SSR/SSG/ISR)]], [[React 18/19 마이그레이션 및 동시성 렌더링 적용]]
- **Contradictions/Notes:** 수동 메모이제이션 방식에 대해 소스 18은 "모든 컴포넌트를 무분별하게 메모이제이션(`React.memo` 등)하는 것은 오버헤드를 증가시켜 역효과를 낼 수 있으므로 프로파일링 후 제한적으로 적용해야 한다"고 주의를 줍니다. 반면 최신 기술인 React Compiler를 다룬 소스 336과 341에 따르면, 컴파일러는 코드 분석을 통해 "실제로 혜택을 제공할 수 있는 지점에 지능적으로 메모이제이션을 삽입"하여 개발자의 오버헤드나 오류 없이 성능을 자동으로 획기적으로 개선한다고 설명합니다.
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[React 렌더링 최적화]]
## 📌 Brief Summary
React 렌더링 최적화는 애플리케이션의 불필요한 재렌더링을 방지하고 초기 로드 및 상호작용 속도를 향상시켜 사용자 경험을 개선하는 과정입니다 [1-3]. 기본적으로 부모 컴포넌트의 상태가 변경되면 모든 자식 컴포넌트가 다시 렌더링되는 폭포수(Cascade) 문제가 발생할 수 있습니다 [1, 2]. 이를 해결하기 위해 메모이제이션, React 18의 자동 배칭(Automatic Batching), 동시성 렌더링, 그리고 최근 도입된 React Compiler와 같은 기술을 활용하여 성능 병목을 최소화합니다 [4-8].
## 📖 Core Content
* **가상 DOM과 재조정(Reconciliation):** React는 DOM의 상태를 추상화한 **가상 DOM(Virtual DOM)**을 메모리에 유지하며, 상태가 변경될 때 이전 트리와 새로운 트리를 비교하여 실제 DOM에 필요한 최소한의 변경 사항만 업데이트합니다 [9-11]. 이 비교 과정에서는 **요소의 타입이 다르면 트리를 처음부터 다시 구축하고, 고유한 `key`를 사용하여 리스트 항목의 변경을 추적**하는 O(n) 복잡도의 휴리스틱 알고리즘을 사용합니다 [12-15].
* **Fiber 아키텍처와 동시성 렌더링(Concurrent Rendering):** 기존의 동기식 렌더링이 메인 스레드를 차단하는 문제를 해결하기 위해 도입된 **Fiber 아키텍처는 렌더링 작업을 작은 '작업 단위(units of work)'로 나누어 처리**합니다 [16-18]. 중요도(Lane)에 따라 긴급한 상호작용을 우선 처리하고 무거운 작업은 양보하는 '타임 슬라이싱(Time-slicing)'을 지원합니다 [17, 19, 20]. React 19의 `useTransition``useDeferredValue` 훅을 사용하면 무거운 연산 중에도 메인 스레드를 차단하지 않고 UI 반응성을 유지할 수 있습니다 [5, 21, 22].
* **메모이제이션(Memoization):** 컴포넌트의 불필요한 재렌더링을 막기 위해 **`React.memo`, `useMemo`, `useCallback`을 사용하여 이전 계산 결과나 컴포넌트 상태를 캐싱**합니다 [4, 23, 24]. 그러나 매 렌더링마다 인라인 객체나 함수를 생성하면 참조 동등성(reference equality)이 깨져 메모이제이션이 무효화될 수 있습니다 [25-27]. 무분별한 메모이제이션은 오히려 비교 연산 및 메모리 오버헤드를 발생시키므로, 반드시 프로파일링을 통해 병목 지점을 찾은 후 선택적으로 적용해야 합니다 [23, 28].
* **자동 배칭(Automatic Batching):** React 18부터는 네이티브 이벤트 핸들러뿐만 아니라 **Promise, `setTimeout` 등 비동기 작업 내에서 발생하는 여러 상태 업데이트를 단일 재렌더링으로 묶어 처리**합니다 [6, 29-31]. 이를 통해 렌더링 횟수를 대폭 줄여 프레임 드롭을 방지할 수 있으며, 즉각적인 DOM 업데이트가 필요한 경우에는 `flushSync` API를 사용하여 배칭에서 예외 처리할 수 있습니다 [32-34].
* **React Compiler를 통한 자동화:** React 19에 도입된 React Compiler는 빌드 타임에 코드의 추상 구문 트리(AST)를 분석하여 **필요한 곳에 자동으로 메모이제이션 경계를 삽입**합니다 [7, 35-38]. 개발자가 수동으로 의존성 배열(dependency array)을 관리할 필요성이 사라지며, 성능 향상은 물론 코드의 가독성과 유지보수성도 크게 개선됩니다 [7, 23, 39].
* **기타 구조적 최적화 기법:**
* **코드 스플리팅:** `React.lazy()`를 활용해 초기 번들 크기를 줄여 LCP(Largest Contentful Paint) 속도를 개선합니다 [40, 41].
* **가상화(Virtualization):** `react-window` 등을 사용하여 수천 개의 리스트 중 화면에 보이는 DOM 노드만 렌더링합니다 [42, 43].
* **DOM 노드 감소 및 상태 분리:** 불필요한 래퍼를 줄이는 React Fragment의 사용과, 렌더링 파급력을 최소화하기 위해 Context를 업데이트 빈도에 따라 분리하는 기법이 있습니다 [44-46].
* **React Server Components (RSC):** 상호작용이 없는 정적 컴포넌트를 서버에서 전적으로 렌더링해 클라이언트 측으로 전송되는 JavaScript 페이로드를 원천적으로 차단합니다 [47-49].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[Fiber Architecture]], [[Automatic Batching]], [[React Compiler]], [[React Server Components]]
- **Projects/Contexts:** [[프론트엔드 성능 최적화]], [[Core Web Vitals 개선 전략]], [[대규모 단일 페이지 애플리케이션(SPA) 구축]]
- **Contradictions/Notes:** 기존에는 `useMemo``useCallback`과 같은 수동 메모이제이션이 렌더링 최적화의 핵심으로 여겨졌으나, 새로운 React Compiler의 등장으로 이러한 수동 제어는 대부분 불필요해지거나 오히려 안티 패턴이 될 가능성이 제기되었습니다 [23, 39, 50]. 다만 서드파티 라이브러리의 불안정한 참조 반환 등 일부 엣지 케이스에서는 여전히 수동 메모이제이션이 이스케이프 해치(Escape hatch)로 사용됩니다 [51-53].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,30 @@
# [[“React가 빠른 이유” 및 렌더링 최적화 개념]]
## 📌 Brief Summary
React가 빠른 핵심 이유는 브라우저의 무거운 실제 DOM 조작을 최소화하기 위해 가벼운 메모리 내 표현인 Virtual DOM을 사용하고, 효율적인 Reconciliation(조정) 알고리즘을 통해 변경된 부분만 갱신하기 때문입니다 [1-4]. 렌더링 최적화의 근본적인 목표는 연산 비용이 높은 브라우저의 Reflow(레이아웃)와 Repaint를 줄이는 것이며 [5-7], 최근 React는 Fiber 아키텍처, 자동 배칭(Automatic Batching), React Compiler 등을 도입하여 개발자의 수동 개입 없이도 동시성 렌더링과 메모이제이션을 자동화해 UI 성능을 극대화하고 있습니다 [8-11].
## 📖 Core Content
**브라우저 렌더링 과정 (Critical Rendering Path) 및 병목**
브라우저는 HTML을 파싱하여 DOM(Document Object Model)을 구축하고, CSS를 파싱하여 CSSOM을 만든 뒤 이 둘을 결합하여 화면에 보일 요소들만 포함하는 렌더 트리(Render Tree)를 생성합니다 [12-15]. 이 트리를 바탕으로 각 요소의 정확한 크기와 위치를 계산하는 Layout(또는 Reflow) 단계를 거쳐, 최종적으로 화면에 픽셀을 그리는 Paint(또는 Repaint) 작업을 수행합니다 [5, 16-20]. 요소의 너비, 높이, 위치 등을 변경하면 전체 페이지의 레이아웃을 다시 계산해야 하는 Reflow가 발생하며, 이는 매우 연산 비용이 높고 렌더링 성능 저하의 주된 원인이 됩니다 [5, 6, 21, 22].
**Virtual DOM과 Reconciliation (조정 알고리즘)**
직접적인 DOM 조작의 비효율성을 극복하기 위해 React는 Virtual DOM(VDOM)이라는 가상의 UI 트리를 메모리에 유지합니다 [1, 2, 4]. 상태가 변경되면 React는 새로운 Virtual DOM을 생성하고 이전 트리와 비교(Diffing)합니다 [2, 23]. React의 조정 알고리즘은 O(n)의 시간 복잡도를 가지며, "서로 다른 타입의 요소는 다른 트리를 생성한다"는 가정과 리스트 렌더링 시 `key` 속성을 사용하여 변경, 추가, 삭제된 최소한의 노드만 식별해 실제 DOM에 패치(Patch)합니다 [1, 3, 24-26]. 이를 통해 불필요한 Reflow와 Repaint를 방지합니다.
**Fiber 아키텍처와 우선순위 기반 스케줄링**
React 16부터 도입된 Fiber 아키텍처는 동기식 렌더링의 한계를 해결하기 위해 렌더링 작업을 'Fiber 노드'라는 작은 작업 단위로 나눕니다 [8, 27-30]. 이 구조는 '타임 슬라이싱(Time-Slicing)'을 가능하게 하여, 렌더링 도중에도 사용자 입력이나 애니메이션 같은 긴급한 작업(Sync Lane)이 발생하면 기존 작업을 중단(Pause) 및 양보(Yield)하고 우선순위가 높은 작업을 먼저 처리할 수 있도록 돕습니다 [27, 30-34]. 그 결과 메인 스레드 차단을 막아 끊김 없는 UI(동시성 렌더링)를 제공합니다.
**React 최신 버전의 자동 렌더링 최적화**
* **자동 배칭 (Automatic Batching):** React 18은 이벤트 핸들러뿐만 아니라 Promise, setTimeout 등 모든 출처에서 발생하는 상태 업데이트를 묶어서 단 한 번의 리렌더링으로 처리합니다 [9, 35-38]. 이로 인해 Virtual DOM 디핑 연산과 실제 DOM 업데이트 횟수가 크게 줄어듭니다.
* **React Compiler:** React 19에서 도입된 컴파일러는 빌드 타임에 코드의 AST(추상 구문 트리)를 분석하여 정적 값과 반응형 값을 식별하고 자동으로 메모이제이션을 삽입합니다 [10, 39-41]. 이는 상위 컴포넌트의 상태 변경으로 인한 하위 컴포넌트의 연쇄 리렌더링(Re-render Cascade)을 차단하며, 개발자가 직접 `useMemo``useCallback`을 작성하는 수고를 덜어줍니다 [10, 11, 42-44].
**서버 컴포넌트 (React Server Components, RSC)**
기존 CSR(클라이언트 사이드 렌더링)이나 SSR(서버 사이드 렌더링) 환경에서는 클라이언트가 결국 방대한 크기의 JavaScript 번들을 다운로드하고 실행(Hydration)해야 하는 부담이 있었습니다 [45-48]. React Server Components는 서버에서 컴포넌트를 실행한 뒤 직렬화된 UI와 HTML만을 클라이언트로 스트리밍합니다 [49-51]. 결과적으로 서버 컴포넌트는 클라이언트 측 자바스크립트 번들에 0바이트를 추가하며, 브라우저의 다운로드 및 실행 부담을 없애 무거운 데이터 연산이나 정적 UI 렌더링 속도를 극대화합니다 [49, 51-53].
## 🔗 Knowledge Connections
- **Related Topics:** `[[Virtual DOM]]`, `[[Reconciliation]]`, `[[Critical Rendering Path]]`, `[[React Fiber]]`, `[[Hydration]]`, `[[Reflow and Repaint]]`
- **Projects/Contexts:** `[[React 18 Automatic Batching]]`, `[[React 19 Compiler]]`, `[[React Server Components]]`, `[[Next.js Rendering Strategies]]`
- **Contradictions/Notes:** 이전까지는 불필요한 렌더링을 막기 위해 개발자가 `useMemo`, `useCallback`, `React.memo`를 사용한 수동 메모이제이션을 구현하는 것이 필수적인 최적화 기법이었습니다 [43, 54, 55]. 그러나 React 19 컴파일러의 등장으로 이러한 수동 메모이제이션의 90% 이상이 불필요해졌으며, 컴파일러가 최적의 메모이제이션 경계를 자동으로 판단하여 적용합니다 [10, 44, 56, 57]. 단, 타사 라이브러리(Third-party library)가 렌더링마다 불안정한 참조를 반환하는 경우 컴파일러 최적화가 실패할 수 있어, 여전히 제한적인 상황에서는 수동 제어가 필요할 수 있습니다 [58, 59].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,26 @@
# [[브라우저 메인 스레드 최적화 및 타임 슬라이싱]]
## 📌 Brief Summary
브라우저 메인 스레드 최적화 및 타임 슬라이싱은 단일 스레드로 동작하는 브라우저의 특성상 발생할 수 있는 UI 멈춤(Jank) 현상을 방지하고 상호작용성을 높이기 위한 아키텍처 접근 방식입니다 [1, 2]. 거대한 렌더링 작업을 중단 불가능한 하나의 동기적 작업으로 처리하는 대신, 타임 슬라이싱을 통해 작업을 작은 청크(단위)로 분할합니다 [1, 3]. 이를 통해 메인 스레드는 무거운 렌더링 작업을 중간에 일시 중지하고 사용자 입력과 같은 긴급한 고우선순위 작업을 먼저 처리한 후 남은 렌더링을 재개할 수 있어 애플리케이션의 반응성을 극대화합니다 [1, 4, 5].
## 📖 Core Content
- **메인 스레드의 한계와 동기적 블로킹 문제:**
브라우저는 기본적으로 단일 스레드(Single-threaded) 환경에서 작동하며, 한 번에 하나의 태스크를 처음부터 끝까지 실행합니다 [2]. 메인 스레드는 HTML/CSS 파싱, 자바스크립트 실행, 스타일 계산, 레이아웃(Reflow) 및 페인트(Paint) 등의 렌더링 파이프라인을 모두 책임집니다 [6, 7]. 부드러운 스크롤과 상호작용을 유지하려면 16.67ms(60 FPS) 이내에 프레임 렌더링을 완료해야 합니다 [1, 7]. 그러나 대규모 컴포넌트 트리 업데이트를 단일 재귀 호출로 처리하면 이 프레임 예산을 초과하여 메인 스레드를 오랫동안 점유하게 되며, 이는 TTI(Time to Interactive)를 늦추고 브라우저가 사용자 입력에 반응하지 못하게 만듭니다 [1, 8, 9].
- **타임 슬라이싱(Time-Slicing)과 Fiber 아키텍처:**
이러한 메인 스레드 블로킹 문제를 해결하기 위해 React는 렌더링 작업을 작은 '작업 단위(Units of Work)'로 나누는 Fiber 아키텍처를 도입했습니다 [1, 10]. 타임 슬라이싱은 무거운 업데이트 작업을 작은 청크로 쪼개는 기법입니다 [3]. 작업 루프(Work loop)는 각 작업 단위를 처리한 후 브라우저에 남은 여유 시간이 있는지, 또는 사용자 입력과 같은 긴급한 작업이 들어왔는지 확인합니다 [4]. 만약 시간이 부족하면 렌더링 작업을 일시 중지하고 메인 스레드의 제어권을 브라우저에게 양보(Yield)합니다 [4, 11].
- **스케줄링과 우선순위(Lanes) 제어:**
스케줄러는 UI 업데이트의 우선순위를 지능적으로 관리하는 역할을 합니다 [3]. 사용자 입력(클릭, 타이핑)과 같은 작업은 가장 높은 우선순위(Sync Lane)에 할당되어 즉시 처리되며, 백그라운드 데이터 처리나 무거운 리스트 필터링 등은 낮은 우선순위로 밀려납니다 [12-14]. 스케줄러는 메인 스레드가 바쁘거나 더 높은 우선순위의 작업이 도착하면 현재 진행 중인 작업(WIP Fiber)을 일시 중지(Pause)시키고, 메인 스레드가 유휴 상태가 되었을 때 중단된 지점부터 다시 재개(Resume)합니다 [5]. 이 과정에서 `requestIdleCallback`과 같은 브라우저 API를 활용하여 UI가 멈추지 않도록 방지합니다 [11].
- **최적화 지표 및 동시성 렌더링(Concurrent Rendering):**
이러한 타임 슬라이싱과 우선순위 제어를 바탕으로 React 19의 `useTransition``useDeferredValue`와 같은 동시성 기능이 작동합니다 [15, 16]. 이 기능들은 무거운 연산을 비긴급 업데이트로 분류하여 메인 스레드가 사용자 입력에 즉각적으로 반응할 수 있는 공간을 확보해 줍니다 [15, 17]. 이는 자바스크립트 실행 속도 자체를 물리적으로 높이는 것은 아니지만, 긴급한 사용자 피드백이 지연되지 않게 하여 앱이 "더 빠르게 느껴지도록(Feel faster)" 인지적 성능을 크게 향상시키며, 결과적으로 INP(Interaction to Next Paint) 코어 웹 바이탈 지표를 직접적으로 개선합니다 [17, 18].
## 🔗 Knowledge Connections
- **Related Topics:** [[React Fiber Architecture]], [[Concurrent Rendering]], [[Critical Rendering Path]]
- **Projects/Contexts:** [[React 18/19]], [[Core Web Vitals (INP, TTI)]]
- **Contradictions/Notes:** 과거 React의 스택 리컨실러(Stack Reconciler)는 렌더링 작업이 한 번 시작되면 트리를 끝까지 동기적으로 순회해야 했기 때문에 메인 스레드를 블로킹하는 치명적 단점이 있었으나, Fiber 도입 이후 이를 중단 및 재개 가능한(Interruptible) 렌더링 모델로 개선했다는 사실이 소스 전반에 걸쳐 강조됩니다 [1, 19, 20]. 타임 슬라이싱은 코드 자체를 빠르게 만드는 것이 아니라 메인 스레드 가용성을 확보하여 체감 성능을 향상시키는 구조적 접근임을 유의해야 합니다 [18].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,31 @@
# [[프론트엔드 성능 최적화 전략]]
## 📌 Brief Summary
프론트엔드 성능 최적화 전략은 브라우저의 렌더링 과정(Critical Rendering Path)을 효율적으로 관리하고, 불필요한 연산과 네트워크 다운로드를 줄여 사용자에게 빠르고 매끄러운 웹 경험을 제공하는 기술적 접근 방식이다 [1, 2]. 이를 위해 개발자는 초기 로딩 속도 개선, 렌더링 시 발생하는 Reflow 및 Repaint의 최소화, 효율적인 상태 관리 및 적절한 웹 렌더링 전략(CSR, SSR, SSG 등)을 종합적으로 고려해야 한다 [1, 3-6]. 궁극적인 목표는 LCP(최대 콘텐츠 풀 페인트), INP(다음 페인트에 대한 상호작용), CLS(누적 레이아웃 이동)와 같은 핵심 웹 바이탈(Core Web Vitals) 지표를 개선하여 비즈니스 성과와 사용자 만족도를 높이는 것이다 [7-10].
## 📖 Core Content
* **브라우저 렌더링 최적화 (Critical Rendering Path 관리)**
* 브라우저가 화면을 그리는 과정에서 렌더링 차단 리소스(CSS, 동기식 JavaScript)를 최소화하여 페이지 초기 렌더링 속도를 앞당겨야 한다 [11-13].
* DOM 트리 및 CSSOM 트리를 생성할 때, 불필요한 DOM 노드의 깊이를 줄이고 CSS 선택자 복잡도를 낮추어 연산 부담을 경감시키는 것이 중요하다 [11, 14-19].
* **Reflow 및 Repaint 최소화**
* 브라우저 화면의 레이아웃을 재계산하는 Reflow 연산은 처리 비용이 매우 크므로, 잦은 DOM 조작이나 레이아웃 요소(width, height, margin 등) 변경을 최소화해야 한다 [20-23].
* 애니메이션 적용 시 `top`, `left` 대신 `transform` 속성을 활용하면 GPU 가속을 통해 Reflow를 우회하고 효율적으로 화면을 다시 그릴 수 있다 [21, 23-26].
* DOM 읽기 및 쓰기 작업을 분리하고 일괄 처리(Batching)하여 성능 저하의 주원인인 레이아웃 스래싱(Layout Thrashing)을 방지해야 한다 [27, 28].
* **렌더링 전략의 전략적 선택**
* 애플리케이션의 특성에 맞춰 Client-Side Rendering (CSR), Server-Side Rendering (SSR), Static Site Generation (SSG), Incremental Static Regeneration (ISR) 등의 전략을 적절히 혼합하여 사용해야 한다 [29-36].
* **React Server Components (RSC):** 클라이언트 번들 크기를 '0' 바이트로 유지하면서 서버 인프라에 직접 접근해 데이터를 병렬로 가져오는 최신 아키텍처로, TTI(상호작용까지의 시간)를 크게 향상하고 불필요한 클라이언트 연산을 제거한다 [37-46].
* **상태 관리 및 프레임워크 수준의 최적화**
* 가상 DOM(Virtual DOM) 환경에서 불필요한 리렌더링을 막기 위해 과거에는 `React.memo`, `useMemo`, `useCallback`과 같은 수동 메모이제이션 방식이 주로 쓰였다 [47-50]. 최근 도입된 **React Compiler**는 빌드 시점에 자동으로 메모이제이션 경계를 삽입하여 최적화 작업의 90% 이상을 자동화하고 코드 복잡성을 줄여준다 [51-56].
* **자동 배칭 (Automatic Batching) 및 Concurrent Features:** React 18/19부터는 여러 상태 업데이트를 하나의 렌더링 사이클로 묶어 처리하며 [57-60], Fiber 아키텍처의 레인(Lanes) 기반 우선순위 관리를 통해 `useTransition`이나 `useDeferredValue` 훅으로 무거운 렌더링 작업을 지연시켜 UI 반응성을 유지한다 [61-71].
* **리소스 번들링 및 UI 컴포넌트 다이어트**
* **코드 스플리팅(Code Splitting):** `React.lazy()` 등을 통해 필요한 시점에 라우트 단위나 컴포넌트를 지연 로드하여 초기 자바스크립트 번들 크기를 30~50%까지 줄인다 [72, 73]. 미사용 코드를 제거하는 트리 쉐이킹(Tree Shaking) 기법도 필수적이다 [74].
* 수백, 수천 개의 데이터 목록을 렌더링할 때는 화면에 보이는 항목만 DOM에 올리는 **가상화(Virtualization)** 기술을 통해 성능 지연을 원천 차단한다 [75, 76].
* 용량이 큰 이미지는 WebP/AVIF 같은 차세대 포맷과 네이티브 지연 로딩(`loading="lazy"`)을 통해 초기 페이지 렌더링 방해를 최소화해야 한다 [77, 78].
## 🔗 Knowledge Connections
- **Related Topics:** [[Critical Rendering Path]], [[Reflow and Repaint]], [[Client-Side Rendering (CSR)]], [[Server-Side Rendering (SSR)]], [[React Server Components]], [[Virtual DOM]], [[React Fiber Architecture]], [[React Compiler]], [[Automatic Batching]]
- **Projects/Contexts:** [[Core Web Vitals (LCP, INP, CLS) 최적화 작업]], [[대규모 단일 페이지 애플리케이션(SPA) 아키텍처 설계]]
- **Contradictions/Notes:** 수동 메모이제이션(`useMemo`, `useCallback`)은 오랫동안 프론트엔드 최적화의 필수 원칙이었으나, 가벼운 컴포넌트에서는 얕은 비교 연산 자체가 렌더링보다 높은 오버헤드를 유발할 수 있다 [79, 80]. 최근 React Compiler의 등장으로 인해 개발자가 직접 메모이제이션을 관리할 필요성이 사라지는 방향으로 패러다임이 진화하고 있다 [53, 81]. 또한 SSR은 초기 콘텐츠 로딩(FCP)과 SEO 측면에서 유리하지만, 서버에서 가져온 HTML에 JavaScript를 연결하는 Hydration 과정에서 메인 스레드가 블로킹되면 사용자의 상호작용이 지연되는 병목(높은 TTI) 현상이 일어날 수 있으므로 무조건적인 해결책이 아니라는 점을 유의해야 한다 [30, 82-86].
---
*Last updated: 2026-04-25*