chore: scaffold subdirectories for new Wiki categories
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# Datacollector - NotebookLM 자동 재인증 검증 강화 및 동시 복구 잠금
|
||||
|
||||
- 작성 시각: 2026-04-25 22:17:33 KST
|
||||
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
|
||||
- 관련 파일: `scripts/mcp_bridge.mjs`
|
||||
|
||||
## 상황
|
||||
|
||||
인증 브라우저 유지와 오래된 `.env` 쿠키 우선순위 문제를 해결한 뒤에도, 실제 작업 중 인증이 풀렸을 때 완전히 자동으로 재인증되지 않는 문제가 남아 있었다.
|
||||
|
||||
화면에서는 작업은 진행되지만 사용자가 기대한 "인증 만료 감지 -> 자동 재인증 -> 원래 작업 재시도" 흐름이 안정적으로 보장되지 않았다.
|
||||
|
||||
## 원인
|
||||
|
||||
브리지에는 자동 복구 로직이 있었지만 두 가지 빈틈이 있었다.
|
||||
|
||||
- `refresh_auth` 호출이 성공해도 실제 NotebookLM API 호출이 가능한지 검증하지 않았다.
|
||||
- `/api/re-auth`와 `/api/check-connection` 같은 요청이 동시에 들어오면 각각 MCP 재시작과 인증 복구를 시도해서 프로세스 재시작 경합이 생길 수 있었다.
|
||||
|
||||
추가로 인증 오류 판별 문자열에 `expired`, `RPC Error 16`, `csrf`, `만료` 같은 케이스가 충분히 포함되지 않아 일부 인증 만료 메시지가 일반 오류로 처리될 가능성이 있었다.
|
||||
|
||||
## 조치
|
||||
|
||||
`scripts/mcp_bridge.mjs`에서 다음을 수정했다.
|
||||
|
||||
- 재인증 성공 기준을 `refresh_auth` 성공이 아니라 실제 `notebook_list` 호출 성공으로 강화했다.
|
||||
- 인증 만료 감지 시 `refreshAuth({ allowExternalAuth: true })`를 통해 자동 CLI 인증 복구까지 이어지도록 정리했다.
|
||||
- 주기적 인증 점검도 필요 시 외부 인증 CLI 복구를 허용하도록 변경했다.
|
||||
- `_refreshAuthPromise` 잠금을 추가해 동시 재인증/재시작 요청이 서로 충돌하지 않게 했다.
|
||||
- 인증 오류 감지 키워드에 `expired`, `rpc error 16`, `csrf`, `unauthorized`, `forbidden`, `인증`, `만료`를 추가했다.
|
||||
|
||||
## 검증
|
||||
|
||||
다음 검증을 완료했다.
|
||||
|
||||
```bash
|
||||
node --check scripts/mcp_bridge.mjs
|
||||
npm run lint
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/re-auth
|
||||
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
- `/api/re-auth`: `success: true`
|
||||
- `/api/check-connection`: `success: true`
|
||||
|
||||
또한 `/api/re-auth`와 `/api/check-connection`을 동시에 호출해도 둘 다 성공하는 것을 확인했다.
|
||||
|
||||
## 운영 메모
|
||||
|
||||
이제 인증이 풀린 상태에서 NotebookLM MCP 호출이 인증 오류를 반환하면 브리지가 다음 순서로 자동 복구한다.
|
||||
|
||||
1. MCP의 `refresh_auth` 실행
|
||||
2. 실제 `notebook_list` 호출로 인증 유효성 검증
|
||||
3. 실패 시 MCP 프로세스 재시작 후 재검증
|
||||
4. 그래도 실패하면 `notebooklm-mcp-auth` CLI 실행
|
||||
5. 인증 캐시 정리 후 MCP 재시작 및 실제 호출 검증
|
||||
|
||||
NotebookLM 브라우저 세션이 완전히 로그아웃된 상태라면 자동 CLI도 브라우저 로그인을 요구할 수 있다. 이 경우 사용자가 열린 NotebookLM Chrome 창에서 로그인만 해두면 이후 자동 복구가 다시 이어질 수 있다.
|
||||
@@ -0,0 +1,23 @@
|
||||
# [[Concurrent Rendering]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Concurrent Rendering(동시성 렌더링)은 메인 스레드를 블로킹하지 않고 UI의 여러 부분을 병렬로 렌더링할 수 있게 해주는 React의 핵심 아키텍처 기능입니다 [1]. 렌더링 작업을 'Time Slicing(시간 분할)'을 통해 작은 단위로 쪼개고 중요도에 따라 우선순위를 부여하여, 긴급한 사용자 입력에 반응하기 위해 렌더링을 일시 중지하거나 재개할 수 있습니다 [1, 2]. 이를 통해 무거운 연산 중에도 UI가 멈추지 않고 즉각적으로 반응하도록 하여 애플리케이션의 체감 성능을 극대화합니다 [3, 4].
|
||||
|
||||
## 📖 Core Content
|
||||
|
||||
* **Fiber 아키텍처와 Work Loop**
|
||||
Concurrent Rendering은 React 16에서 처음 도입된 Fiber 아키텍처를 기반으로 작동합니다 [5, 6]. 기존의 단일 재귀 호출 기반 동기식 렌더링과 달리, 렌더링 작업을 'Fiber 노드'라는 작은 작업 단위(Unit of Work)로 분할합니다 [2, 7]. React는 Work Loop를 통해 이 트리를 점진적으로 순회하며, 각 작업 단위가 끝날 때마다 브라우저에 제어권을 양보(yield)하여 클릭과 같은 고우선순위 상호작용을 처리할 수 있는지 확인합니다 [8, 9].
|
||||
* **우선순위 기반 스케줄링 (Lane Model)**
|
||||
동시성 작업의 우선순위는 'Lane'이라는 비트마스크 시스템을 통해 체계적으로 관리됩니다 [10, 11]. 타이핑이나 클릭처럼 사용자가 즉각적인 반응을 기대하는 긴급한 업데이트(Sync Lane)는 최우선으로 즉시 처리되며, 스크롤(InputContinuous Lane), 네트워크 응답(Default Lane), 백그라운드 렌더링(Idle Lane) 등은 각각 낮은 우선순위를 부여받아 스케줄링됩니다 [12-14]. 이 과정에서 렌더링 단계(Render phase)는 중단 가능(Interruptible)하므로, 더 높은 우선순위의 작업이 도착하면 기존의 렌더링 작업을 일시 중지, 폐기 또는 재시작할 수 있습니다 [15, 16].
|
||||
* **Concurrent Hooks 활용 (`useTransition`, `useDeferredValue`)**
|
||||
React 18 및 19에서는 개발자가 동시성 렌더링을 직접 제어할 수 있는 훅을 제공합니다 [17, 18]. **`useTransition`**은 개발자가 상태 업데이트를 직접 긴급하지 않은 것(low-priority)으로 지정하여, 수천 개의 데이터 필터링 연산이 백그라운드에서 도는 중에도 사용자의 타이핑 입력이 즉시 반영되도록 돕습니다 [17, 19, 20]. **`useDeferredValue`**는 외부에서 전달받는 값 자체의 렌더링을 지연시켜, 새로운 결과가 준비될 때까지 UI가 동결되는 것을 막고 이전 결과를 표시하게 해줍니다 [19, 21].
|
||||
* **성능 최적화 메커니즘 (체감 성능 향상)**
|
||||
Concurrent Rendering의 핵심은 코드의 실제 연산 속도를 물리적으로 가속하는 것이 아닙니다 [3]. 무거운 연산이 즉각적인 사용자 피드백을 방해하지 않도록 처리 순서를 최적화하여 앱이 **"더 빠르게 느껴지게(feel faster)"** 만드는 데 목적이 있습니다 [3]. 이러한 비차단형(Non-Blocking) 렌더링 방식은 사용자의 입력이 다음 화면 페인트로 이어지는 속도를 측정하는 핵심 웹 지표인 **INP(Interaction to Next Paint)**를 향상시키는 데 직접적으로 기여합니다 [21, 22].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** `[[Fiber Architecture]]`, `[[Time Slicing]]`, `[[Lane Model]]`, `[[useTransition]]`, `[[useDeferredValue]]`
|
||||
- **Projects/Contexts:** `[[React 18 & 19 Performance Optimization]]`
|
||||
- **Contradictions/Notes:** 소스에 따르면 `useTransition` 및 `useDeferredValue`와 같은 동시성 훅은 코드 자체의 속도를 높여주지는 않지만, 무거운 연산이 사용자 피드백을 방해하지 않도록 스케줄링하여 앱의 "체감 성능"을 개선하는 방식으로 작동한다는 점을 명확히 하고 있습니다 [3].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,19 @@
|
||||
# [[DOM]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
DOM(Document Object Model)은 브라우저가 수신한 HTML 문서를 구문 분석하여 구성하는 문서의 구조와 콘텐츠를 나타내는 계층적 트리 구조입니다 [1-3]. 이는 브라우저의 렌더링 과정인 크리티컬 렌더링 패스(CRP)에서 CSSOM과 결합하여 화면에 그려질 렌더 트리(Render Tree)를 생성하는 핵심 기초가 됩니다 [4-6]. JavaScript를 통한 직접적인 DOM 조작은 레이아웃(Reflow)과 페인트 작업을 유발해 성능을 저하시키므로, 최신 프레임워크인 React는 이를 최적화하기 위해 Virtual DOM을 활용합니다 [7].
|
||||
|
||||
## 📖 Core Content
|
||||
* **DOM 트리의 점진적 구축:** 브라우저는 HTML 응답을 받으면 바이트(bytes)를 문자, 토큰(token), 노드(node)로 변환하는 과정을 거쳐 DOM 트리를 구성합니다 [3, 8, 9]. HTML의 시작 태그와 종료 태그는 노드 간의 부모, 자식, 형제 관계와 같은 계층 구조를 정의하며, `<html>` 요소가 문서 트리의 루트 노드가 됩니다 [3, 9]. DOM의 구축은 점진적(incremental)으로 이루어지기 때문에, 브라우저는 데이터를 수신하는 도중에도 트리를 구축할 수 있습니다 [8, 9].
|
||||
* **렌더 트리(Render Tree)의 형성:** DOM은 페이지의 '콘텐츠'를 담고 있으며, 페이지의 '스타일'을 담고 있는 CSSOM(CSS Object Model)과 결합하여 렌더 트리를 완성합니다 [5, 6, 10, 11]. 이 렌더 트리는 화면에 실제로 그려지는 가시적인 노드만을 포함하며, `<head>` 태그나 `display: none` 스타일이 적용된 DOM 노드는 렌더 트리에 포함되지 않습니다 [4, 5, 12, 13].
|
||||
* **DOM 조작과 렌더링 성능(Reflow & Repaint):** DOM 노드의 수가 많고 깊이가 깊을수록 레이아웃 및 페인트와 같은 후속 렌더링 단계에 걸리는 연산 부담이 크게 증가합니다 [2, 3, 10, 14]. 또한, JavaScript로 DOM의 구조를 추가/삭제하거나 크기, 위치 속성을 변경하면 브라우저는 화면의 레이아웃을 다시 계산하는 Reflow(또는 Layout)를 실행하고, 이어 픽셀을 다시 그리는 Repaint 단계를 거치게 되어 막대한 연산 비용이 발생합니다 [7, 14-17].
|
||||
* **성능 최적화 및 접근 최소화 방법:** DOM 조작으로 인한 성능 저하를 막기 위해 DOM 노드나 속성값을 변수에 캐싱(Caching)하여 재사용하거나, 연산을 반복문 외부로 빼내어 DOM 상호작용 횟수를 최소화해야 합니다 [18, 19]. 특히, DOM 값을 읽는 작업(Phase 1)과 수정하는 작업(Phase 2)을 교차로 수행하는 레이아웃 스래싱(Layout thrashing)을 방지하도록 코드를 분리하는 것이 중요합니다 [19-21].
|
||||
* **React의 Virtual DOM 도입 배경:** 위와 같은 직접적인 DOM 조작의 비효율성을 극복하기 위해 React는 메모리상에 존재하는 가벼운 복사본인 Virtual DOM(VDOM)을 도입했습니다 [7, 22]. 상태가 변경되면 React는 새로운 Virtual DOM을 생성하고 이전과 비교(Diffing/Reconciliation)하여 변경된 최소한의 부분만을 실제 DOM에 반영함으로써 렌더링 성능을 극대화합니다 [7, 22, 23].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Virtual DOM]], [[CSSOM]], [[Render Tree]], [[Reflow 및 Repaint]], [[Critical Rendering Path (CRP)]]
|
||||
- **Projects/Contexts:** [[React 렌더링 최적화]], [[브라우저 렌더링 과정]], [[웹 성능 가이드(Web Performance)]]
|
||||
- **Contradictions/Notes:** DOM의 구축은 HTML 데이터를 수신함과 동시에 '점진적(incremental)'으로 이루어지며 렌더링을 차단하지 않는 반면, 스타일을 정의하는 CSSOM의 구축은 후속 규칙이 이전 규칙을 덮어쓸 수 있기 때문에 완전히 구문 분석될 때까지 렌더링을 차단(render-blocking)한다는 점에서 작동 방식의 차이가 있습니다 [2, 8-10].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,27 @@
|
||||
# [[Diffing Algorithm]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Diffing Algorithm(디핑 알고리즘)은 React에서 이전 가상 DOM(Virtual DOM) 트리와 새롭게 계산된 트리를 비교하여 실제 DOM을 가장 효율적으로 업데이트할 방법을 결정하는 과정입니다 [1, 2]. 이론적인 트리 비교 알고리즘은 $O(n^3)$의 시간 복잡도를 가져 실시간 애플리케이션에 부적합하지만, React는 두 가지 휴리스틱 가정을 통해 이를 $O(n)$ 복잡도로 최적화했습니다 [3-5]. 이 알고리즘은 'Reconciliation(재조정)' 과정의 핵심으로, 불필요한 DOM 조작을 최소화하여 렌더링 성능을 극대화하는 역할을 합니다 [1, 2, 6].
|
||||
|
||||
## 📖 Core Content
|
||||
* **알고리즘의 기본 원리 및 가정:**
|
||||
React의 디핑 알고리즘은 두 가지 주요 가정에 기반하여 $O(n)$의 성능을 달성합니다. 첫째, 서로 다른 타입의 요소는 근본적으로 다른 트리를 생성한다고 가정합니다 [3, 5]. 둘째, 개발자가 제공하는 `key` prop을 통해 여러 렌더링 사이클 동안 안정적으로 유지되는 자식 요소를 식별할 수 있다고 가정합니다 [3, 5].
|
||||
|
||||
* **비교(Diffing) 프로세스 메커니즘:**
|
||||
* **다른 타입의 요소:** 루트 요소의 타입이 다를 경우(예: `<a>`에서 `<img>`로 변경), React는 이전 트리를 완전히 허물고 처음부터 새로운 트리를 구축합니다. 이 과정에서 기존 DOM 노드와 연관된 컴포넌트의 상태(State)는 모두 파괴됩니다 [7, 8].
|
||||
* **동일한 타입의 DOM 요소:** 두 요소의 속성을 비교하여 동일한 기본 DOM 노드를 유지한 채 변경된 속성(예: `className`, `color`나 `fontWeight` 같은 `style` 등)만 업데이트합니다 [9, 10].
|
||||
* **동일한 타입의 컴포넌트 요소:** 컴포넌트의 인스턴스가 동일하게 유지되어 상태가 보존됩니다. 새로운 요소에 맞게 prop이 업데이트된 후, 하위 요소들에 대해 재귀적으로 디핑 알고리즘을 수행합니다 [10, 11].
|
||||
|
||||
* **자식 요소의 재귀적 처리와 Key의 역할:**
|
||||
기본적으로 React는 두 하위 요소 목록을 동시에 반복하면서 차이가 있을 때마다 변이를 생성합니다 [11]. 하지만 리스트의 맨 앞에 요소를 추가하는 경우 등 순서가 변경될 때는 전체를 다시 렌더링하는 매우 비효율적인 상황이 발생할 수 있습니다 [12]. 이를 해결하기 위해 고유한 `key` 속성을 사용하면, React는 기존 트리와 새 트리의 자식들을 일치시켜 이동한 요소만 파악하므로 불필요한 DOM 재생성을 방지할 수 있습니다 [12, 13].
|
||||
|
||||
* **트레이드오프 및 주의사항:**
|
||||
이 알고리즘은 휴리스틱에 의존하기 때문에 가정이 충족되지 않으면 성능이 저하될 수 있습니다 [14]. 예를 들어 하위 트리가 형제 요소 사이가 아닌 아예 다른 계층으로 이동하는 경우, 알고리즘은 해당 하위 트리를 완전히 다시 렌더링합니다 [15]. 또한 배열의 인덱스를 키로 사용하거나 `Math.random()` 같은 불안정한 키를 사용하면 리스트가 재정렬될 때 컴포넌트 상태가 꼬이거나 성능 저하가 발생할 수 있습니다 [14, 16].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[React Fiber]]
|
||||
- **Projects/Contexts:** [[React Frontend Development]], [[Component-Based Architecture]]
|
||||
- **Contradictions/Notes:** 일반적인 트리 비교 알고리즘은 $O(n^3)$의 복잡도를 가지지만, React의 디핑 알고리즘은 휴리스틱(Heuristics)을 적용하여 실용적인 $O(n)$ 복잡도로 구현되었다는 점이 핵심적인 기술적 차이입니다 [4, 5]. 배열의 인덱스를 `key`로 사용하는 것은 요소의 순서가 변경되지 않을 때만 유효하며, 재정렬(Reorder) 시에는 비효율적이고 상태 오류를 일으킬 수 있으므로 권장되지 않습니다 [13, 16].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,24 @@
|
||||
# [[Fiber Architecture]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
React 16에서 도입된 Fiber Architecture는 동시성 렌더링(Concurrent Rendering)을 지원하기 위해 근본적으로 재작성된 React의 재조정(Reconciliation) 엔진입니다 [1-3]. 기존의 동기식 렌더링이 메인 스레드를 차단하여 UI가 멈추던 문제를 해결하고자, 렌더링 작업을 '파이버(Fiber)'라는 작은 단위의 노드로 쪼개어 점진적으로 처리합니다 [4, 5]. 이를 통해 React는 렌더링을 일시 중지하거나 브라우저에 제어권을 양보하고, 우선순위가 높은 작업을 먼저 처리한 후 다시 렌더링을 재개하는 타임 슬라이싱(Time-slicing) 스케줄링을 구현할 수 있게 되었습니다 [4-6].
|
||||
|
||||
## 📖 Core Content
|
||||
* **동기식 차단(Synchronous Blocking)의 한계 극복:**
|
||||
Fiber 도입 이전의 React는 '스택 재조정자(Stack Reconciler)'를 사용하여 전체 컴포넌트 트리를 단일 재귀 호출로 동기 처리했습니다 [4]. 이 방식은 대규모 애플리케이션에서 브라우저의 프레임 예산(16.6ms)을 초과할 경우 메인 스레드를 차단하여 사용자 입력이나 애니메이션을 지연시켰습니다 [4]. Fiber는 작업을 작은 단위로 나누어 브라우저가 높은 우선순위의 작업을 가로채 처리할 수 있게 함으로써 이 문제를 해결합니다 [4, 5, 7].
|
||||
* **작업 루프(Work Loop)와 두 가지 렌더링 단계:**
|
||||
Fiber의 재조정 과정은 작업 중단과 우선순위 관리를 위해 두 가지 명확한 단계로 나뉩니다 [8].
|
||||
* **렌더링 단계 (Render Phase):** 이 단계는 비동기적이며 중단할 수 있습니다 [8]. 실제 DOM을 변경하지 않고 메모리 상의 파이버 트리를 순회하면서 이전 상태와 새로운 상태의 차이를 계산하고, 변경이 필요한 파이버들의 목록(Effect list)을 구성합니다 [8, 9]. 더 높은 우선순위 작업이 들어오면 일시 중단, 폐기 또는 재시작될 수 있으므로, 이 단계에서는 사이드 이펙트가 발생해서는 안 됩니다 [8-10].
|
||||
* **커밋 단계 (Commit Phase):** 이 단계는 동기적이며 중단할 수 없습니다 [11]. 렌더링 단계에서 만들어진 변경 사항(삽입, 삭제, 업데이트)을 한 번에 실제 DOM에 적용합니다 [9, 11, 12]. 이 시점에 실제 DOM이 변형되며 각종 생명주기 메서드나 레이아웃 이펙트(`useLayoutEffect`)가 실행됩니다 [11, 12].
|
||||
* **레인(Lane) 모델을 통한 우선순위 스케줄링:**
|
||||
Fiber는 32비트 정수 비트마스크 시스템인 '레인(Lane)'을 사용하여 작업의 우선순위를 정밀하게 관리합니다 [13, 14]. 클릭이나 타이핑 등 즉각적 반응이 필요한 작업(Sync Lane), 스크롤링(InputContinuous Lane), 일반적인 상태 업데이트(Default Lane), 백그라운드 작업(Idle Lane)으로 업데이트를 분류합니다 [6, 15]. 이를 통해 사용자 상호작용과 같은 '긴급한' 업데이트가 데이터 렌더링 같은 '비긴급' UI 전환보다 먼저 처리되도록 보장합니다 [6, 16].
|
||||
* **작업 진행 상태(WIP) 트리 관리:**
|
||||
React는 현재 화면에 그려진 상태를 추적할 뿐만 아니라 작업 중인 상태를 나타내는 WIP(Work-in-progress) 트리를 별도로 관리합니다 [10]. 스케줄러의 우선순위에 따라 메인 스레드가 바쁘면 이 WIP 트리의 작업을 일시 중지하고, 브라우저가 유휴 상태일 때 다시 재개할 수 있습니다 [10].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[Concurrent Rendering]], [[Critical Rendering Path]]
|
||||
- **Projects/Contexts:** [[React 16+ Core Engine]], [[브라우저 메인 스레드 최적화 및 타임 슬라이싱]]
|
||||
- **Contradictions/Notes:** Fiber의 동시성 렌더링 기능(예: `useTransition`, `useDeferredValue`)은 코드의 물리적인 실행 속도를 높이는 것은 아닙니다 [17]. 무거운 연산으로 인한 병목이 즉각적인 사용자 상호작용을 방해하지 않도록 뒤로 미룸(Deferring)으로써, 체감 성능(Perceived Performance) 측면에서 애플리케이션이 훨씬 "더 빠르게 느껴지도록" 만드는 것이 핵심입니다 [17].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,19 @@
|
||||
# [[Next.js 렌더링 최적화]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Next.js 렌더링 최적화는 애플리케이션의 성능, SEO 및 사용자 경험을 극대화하기 위해 페이지 특성에 맞춰 다양한 렌더링 전략(SSR, SSG, CSR, ISR)을 조합하여 사용하는 과정을 의미합니다 [1-3]. 특히 React Server Components(RSC)를 활용하여 서버에서 렌더링과 데이터 페칭을 처리함으로써 클라이언트로 전송되는 자바스크립트 번들의 크기를 대폭 줄입니다 [4, 5]. 이를 통해 초기 로딩 속도(LCP)를 개선하고 부드러운 상호작용을 보장하는 것이 핵심 목적입니다 [6-8].
|
||||
|
||||
## 📖 Core Content
|
||||
- **하이브리드 렌더링 전략 (Hybrid Rendering):** Next.js는 동일한 애플리케이션 내에서 페이지별 요구사항에 따라 렌더링 방식을 유연하게 혼합할 수 있습니다 [1, 2]. 마케팅 페이지나 공식 문서에는 정적 사이트 생성(SSG)을, 항상 최신 상태를 유지해야 하는 상품 페이지에는 서버 사이드 렌더링(SSR)을, 사용자 대시보드와 같이 인터랙션이 중요한 곳에는 클라이언트 사이드 렌더링(CSR)을 적용하여 성능과 SEO를 최적화합니다 [1, 3].
|
||||
- **점진적 정적 재생성 (ISR):** 정적 생성(SSG)의 압도적인 로딩 속도와 SSR의 데이터 최신화 이점을 결합한 모델입니다 [9, 10]. 전체 사이트를 다시 빌드할 필요 없이 특정 시간 간격이나 요청에 따라 백그라운드에서 개별 정적 페이지를 업데이트하여 최신 상태의 캐시된 콘텐츠를 제공합니다 [10-12].
|
||||
- **React Server Components (RSC) 생태계 도입:** Next.js의 App Router는 기본적으로 컴포넌트를 서버 컴포넌트로 처리합니다 [13]. 정적인 UI는 서버에서 렌더링 되어 HTML과 직렬화된 명령(React Flight 프로토콜)으로만 전달되며, 브라우저로 전송되는 자바스크립트(0 bytes)를 줄여 성능을 크게 향상시킵니다 [4, 5, 14-16]. 인터랙션이 필수적인 부분만 `"use client"` 지시어를 사용해 클라이언트 컴포넌트로 분리합니다 [14, 17, 18].
|
||||
- **데이터 페칭과 병렬 처리:** 서버 컴포넌트를 사용하면 API 계층을 거칠 필요 없이 데이터베이스나 로컬 파일 시스템에서 직접 데이터를 가져올 수 있습니다 [14, 19, 20]. 이를 적절히 설계하면 렌더링 중 부모와 자식 컴포넌트가 독립적으로 데이터를 병렬 호출할 수 있어, 네트워크 워터폴(Waterfall) 현상을 제거하고 응답 속도를 최소화합니다 [21, 22].
|
||||
- **자동화된 최적화 도구 활용:** `next/image` 컴포넌트는 이미지 포맷 자동 변환(WebP/AVIF), 반응형 사이징, 그리고 화면에 보일 때만 이미지를 로드하는 지연 로딩(Lazy Loading)을 지원하여 Core Web Vitals를 향상시킵니다 [7, 23, 24]. 추가로 최신 Next.js 환경에서는 React Compiler를 설정하여 수동 메모이제이션 없이 렌더링 최적화를 자동화할 수도 있습니다 [25].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[React Server Components]], [[점진적 정적 재생성 (ISR)]], [[하이드레이션 (Hydration)]]
|
||||
- **Projects/Contexts:** [[Next.js App Router]], [[전자상거래 플랫폼 (E-commerce Platforms)]]
|
||||
- **Contradictions/Notes:** SSR은 초기 콘텐츠 렌더링(FCP)이 빠르고 SEO에 매우 유리하지만, 자바스크립트를 로드하고 연결하는 '하이드레이션(Hydration)' 과정을 거쳐야 하므로 사용자가 페이지와 상호작용하기까지의 시간(TTI)이 지연될 수 있습니다 [8, 26-28]. 또한, 서버 컴포넌트를 사용하더라도 데이터 의존성이 직렬(Sequential)로 연결되어 있다면 브라우저가 아닌 서버 측에서 워터폴 현상이 발생해 응답 지연이 생길 수 있으므로 병렬 처리를 고려한 설계가 필요합니다 [29, 30].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,25 @@
|
||||
# [[React 18 동시성 렌더링 (Concurrent Rendering)]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
React 18 동시성 렌더링(Concurrent Rendering)은 React가 렌더링 작업을 여러 단위로 나누고, 작업의 우선순위를 평가하여 브라우저의 메인 스레드를 차단하지 않고 UI를 부드럽게 업데이트할 수 있도록 설계된 아키텍처적 패러다임입니다 [1-3]. 이는 Fiber 아키텍처와 스케줄러의 타임 슬라이싱(Time-Slicing) 및 우선순위 레인(Lanes) 시스템을 기반으로 동작합니다 [2, 4, 5]. 이를 통해 개발자는 무거운 데이터 연산 중에도 사용자 입력과 같은 긴급한 상호작용을 즉각적으로 처리하여 애플리케이션의 체감 응답성을 크게 향상시킬 수 있습니다 [6-8].
|
||||
|
||||
## 📖 Core Content
|
||||
* **동기식 블로킹의 한계 극복 (Fiber 아키텍처 도입):**
|
||||
과거의 React는 한 번 렌더링이 시작되면 전체 컴포넌트 트리가 처리될 때까지 멈출 수 없어, 무거운 작업 시 메인 스레드가 차단되고 UI가 응답하지 않는 문제가 있었습니다 [4]. 이를 해결하기 위해 설계된 Fiber 아키텍처는 렌더링 작업을 'Fiber 노드'라는 단위로 잘게 분할하여, 스케줄러가 여러 프레임에 걸쳐 작업을 점진적으로 분산 처리할 수 있도록 지원합니다 [2].
|
||||
|
||||
* **타임 슬라이싱(Time-Slicing)과 렌더링 단계의 분리:**
|
||||
동시성 렌더링은 타임 슬라이싱을 사용하여 렌더링 작업을 나누고, 필요 시 브라우저에 제어권을 양보(yield)합니다 [4, 9]. 렌더링은 두 가지 단계로 나뉘는데, 변경 사항의 목록을 계산하는 '렌더(Render) 단계'는 언제든 일시 중지, 재개 또는 폐기될 수 있습니다 [10, 11]. 반면 실제 DOM에 변경 사항을 적용하는 '커밋(Commit) 단계'는 동기적이고 중단할 수 없는 형태로 한 번에 실행됩니다 [11-13].
|
||||
|
||||
* **우선순위 기반 관리 (Lane 모델):**
|
||||
React는 비트마스크 시스템을 활용한 'Lanes'라는 모델을 통해 작업의 우선순위를 관리합니다 [14, 15]. 클릭이나 타이핑 같은 긴급한 사용자 입력은 'Sync Lane'으로 분류되어 즉시 처리되며, 화면 외부 렌더링이나 무거운 데이터 필터링은 'Idle Lane' 등의 낮은 우선순위로 분류됩니다 [14, 16]. 이 모델을 통해 진행 중이던 낮은 우선순위 작업은 더 중요한 업데이트가 도착하면 중단되거나 우선순위가 조정될 수 있습니다 [17].
|
||||
|
||||
* **동시성 제어를 위한 API (`useTransition`, `useDeferredValue` 등):**
|
||||
개발자는 React에서 제공하는 훅을 활용해 긴급하지 않은 업데이트를 백그라운드로 지연시킬 수 있습니다 [6]. `startTransition`이나 `useTransition`은 특정 상태 업데이트의 우선순위를 낮추어 사용자 입력 같은 긴급한 작업이 먼저 처리되게 합니다 [6, 18]. 상태 업데이트 코드를 직접 제어할 수 없는 경우(예: props로 값을 전달받는 경우)에는 `useDeferredValue`를 사용하여 렌더링 연산을 지연시킴으로써 UI가 멈추는 것을 방지할 수 있습니다 [19, 20]. 긴급히 동기적으로 업데이트를 강제해야 할 때에는 `flushSync`를 사용할 수 있습니다 [21].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[React Fiber]], [[Time-Slicing]], [[Lanes Model]], [[Automatic Batching]], [[Virtual DOM]]
|
||||
- **Projects/Contexts:** [[무거운 데이터 리스트 필터링 구현]], [[타이핑에 즉각 반응해야 하는 검색창 (Search-as-you-type)]]
|
||||
- **Contradictions/Notes:** 소스 [6]에서는 `useTransition` 및 `useDeferredValue` 등 동시성 제어 훅을 "React 19의 기능"으로 설명하고 있으나, 소스 [21]와 [18]에서는 `startTransition`과 `flushSync`를 통한 렌더링 제어가 "React 18에 도입되었다"고 서술합니다. 이는 React 18에서 도입된 동시성 렌더링 기능이 후속 버전에서도 계속 확장 및 핵심 성능 최적화 패턴으로 사용되고 있음을 시사합니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,23 @@
|
||||
# [[React Performance Optimization]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
React 성능 최적화는 브라우저의 렌더링 과정에서 발생하는 레이아웃 계산과 페인팅 비용을 최소화하고, 효과적인 렌더링 전략을 통해 애플리케이션의 반응성을 극대화하는 과정입니다 [1, 2]. 이를 위해 React는 가상 DOM(Virtual DOM)과 휴리스틱 Diffing 알고리즘, 그리고 Fiber 아키텍처를 도입하여 UI 업데이트를 효율적으로 관리합니다 [3-5]. 궁극적으로 개발자는 CSR, SSR, SSG와 같은 렌더링 방식을 서비스의 특성에 맞게 선택하고, 컴포넌트 기반 설계와 최적화 도구를 활용해 사용자 경험을 획기적으로 향상시킬 수 있습니다 [6, 7].
|
||||
|
||||
## 📖 Core Content
|
||||
* **브라우저 렌더링 과정 및 Reflow/Repaint 최소화:** 브라우저는 HTML과 CSS를 파싱하여 DOM과 CSSOM을 각각 생성하고, 이를 결합하여 화면에 표시될 요소만 담은 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과 React의 속도 향상 메커니즘:** React는 실제 DOM을 직접 수정하는 대신, 메모리 내에 가벼운 객체 형태인 Virtual DOM을 유지합니다 [1, 5, 21, 22]. 상태가 변경되면 새로운 Virtual DOM을 만들고, 휴리스틱 기반의 O(n) Diffing 알고리즘을 통해 이전 트리와 비교(Reconciliation)합니다 [3, 5, 23]. 이 알고리즘은 요소의 타입과 Key 속성을 바탕으로 변경된 최소한의 노드만 식별한 뒤 실제 DOM에 일괄 적용하므로, 불필요한 Reflow를 막고 렌더링 성능을 크게 높입니다 [3, 24, 25].
|
||||
* **React 엔진 최적화 (Fiber 아키텍처 및 최근 기능):** React 16부터 도입된 Fiber 아키텍처는 렌더링 작업을 중단 및 재개 가능한 작은 '작업 단위'로 나누고, 우선순위(Lane 모델)에 따라 처리하는 동시성 렌더링(Concurrent Rendering)을 지원합니다 [4, 26-30]. 또한 React 18에 도입된 자동 일괄 처리(Automatic Batching)는 Promise, setTimeout 등의 비동기 작업 내 여러 상태 업데이트를 단일 리렌더링으로 묶어 효율성을 극대화합니다 [31-34]. 최근 도입된 React Compiler는 빌드 단계에서 구문 트리를 분석하여 수동 처리 없이 자동으로 메모이제이션을 삽입해 개발자의 성능 최적화 부담을 줄여줍니다 [35-38].
|
||||
* **CSR vs SSR vs SSG 전략적 렌더링:**
|
||||
* **CSR (Client-Side Rendering):** 브라우저가 빈 HTML과 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):** 오직 서버에서만 실행되어 클라이언트에 JavaScript 번들을 전혀 전송하지 않는 컴포넌트 구조로, 클라이언트 번들 크기를 대폭 줄이고 서버 리소스에 직접 접근할 수 있습니다 [51-54].
|
||||
* **컴포넌트 기반 아키텍처 (CBA):** React의 핵심 설계 원칙으로, 애플리케이션을 독립적이고 캡슐화된 재사용 가능한 컴포넌트 단위로 나눕니다 [55-58]. 이는 시스템의 복잡성을 낮추고, 병렬 개발을 가능하게 하며, 특정 컴포넌트의 렌더링 주기만을 독립적으로 관리 및 최적화할 수 있도록 지원합니다 [59-64].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Critical Rendering Path]], [[Virtual DOM]], [[React Fiber Architecture]], [[React Compiler]], [[Hydration]]
|
||||
- **Projects/Contexts:** [[SPA (Single Page Application)]], [[Next.js]]
|
||||
- **Contradictions/Notes:** SSR은 검색 엔진 최적화(SEO) 및 빠른 초기 콘텐츠 렌더링(FCP) 측면에서 유리하지만 [43, 65], 사용자가 시각적으로 완성된 페이지를 보더라도 클라이언트가 JavaScript 번들을 다운로드하고 실행하는 Hydration(수화) 과정이 완료되기 전까지는 상호작용이 불가능하므로, TTI(Time to Interactive) 지표에서는 CSR보다 수치가 낮게 나타나는 렌더링 병목 현상이 존재합니다 [66-69].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -1 +1,25 @@
|
||||
{"status":"success","answer":"","conversation_id":"7169ba9e-c01c-4675-ab7b-2786649ef6b8"}
|
||||
# [[React Server Components (RSC)]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
React Server Components(RSC)는 컴포넌트가 오직 서버에서만 실행되고 클라이언트로 JavaScript 번들을 전혀 전송하지 않는 혁신적인 렌더링 아키텍처입니다 [1-3]. 기존의 SSR(Server-Side Rendering)과 달리 상호작용이 필요 없는 정적 컴포넌트의 Hydration(수화) 과정을 생략하며, 직렬화된 UI 표현만을 브라우저로 스트리밍합니다 [2, 4, 5]. 결과적으로 클라이언트의 JavaScript 처리 부하를 대폭 줄이고, 초기 로딩 속도와 상호작용 성능 지표인 INP(Interaction to Next Paint)를 향상시키는 렌더링 최적화의 핵심 기술입니다 [1, 2].
|
||||
|
||||
## 📖 Core Content
|
||||
|
||||
* **아키텍처와 작동 원리 (Architecture & Mechanics)**
|
||||
RSC는 브라우저가 아닌 서버 환경에서 완전히 실행되므로 데이터베이스, 로컬 파일 시스템, 비공개 환경 변수에 직접 접근할 수 있습니다 [6, 7]. 렌더링 결과물은 단순한 HTML뿐만 아니라, 클라이언트가 UI를 조립하는 데 사용하는 직렬화된 React 지시어(React Flight 프로토콜)와 함께 브라우저에 전달됩니다 [5]. 브라우저는 이 결과물을 받아 즉시 화면에 렌더링하며, 이 과정에서 해당 서버 컴포넌트의 JavaScript 코드는 0바이트로 클라이언트에 전송되지 않습니다 [1, 3, 6].
|
||||
* **SSR과의 본질적 차이점 및 Hydration 제거**
|
||||
전통적인 SSR은 서버에서 HTML을 미리 생성해 초기 콘텐츠 표시 속도(FCP)를 높이지만, 브라우저가 페이지를 대화형으로 만들기 위해 여전히 전체 JavaScript 번들을 다운로드하고 'Hydration' 과정을 거쳐야만 합니다 [8, 9]. 반면 순수한 RSC는 브라우저에서 실행될 JS 코드가 애초에 존재하지 않으므로 Hydration 단계 자체가 생략되며 클라이언트 메인 스레드의 연산 부담을 극적으로 줄여줍니다 [2, 4, 7].
|
||||
* **Client Components와의 하이브리드 아키텍처**
|
||||
상태(State) 관리나 이벤트 핸들러(onClick 등), 브라우저 API 접근이 필요한 대화형 요소는 파일 최상단에 `"use client"` 지시어를 선언하여 클라이언트 컴포넌트로 분리합니다 [6, 10, 11]. 서버 컴포넌트는 클라이언트 컴포넌트를 렌더링할 수 있지만, 클라이언트 컴포넌트는 서버 컴포넌트를 직접 임포트할 수 없다는 엄격한 단방향 의존성 규칙(서버 → 클라이언트)을 따릅니다 [12-14]. 이를 통해 무거운 비상호작용 UI는 서버에 남겨두고 상호작용에 필수적인 부분만 브라우저로 전송하여 번들 크기를 최적화할 수 있습니다 [6, 13].
|
||||
* **데이터 페칭(Data Fetching)의 최적화**
|
||||
RSC 환경에서는 컴포넌트 내부에서 별도의 API 중간 계층 없이 데이터베이스에 직접 비동기 요청(async/await)을 수행할 수 있습니다 [15, 16]. 또한 서버 환경의 이점을 살려 렌더링 중 데이터를 병렬로 가져옴으로써, 전통적인 클라이언트 렌더링(CSR)에서 발생하던 데이터 페칭 워터폴(Waterfall) 문제를 효과적으로 제거할 수 있습니다 [17, 18].
|
||||
* **제약 사항 및 구현 시 주의점 (Pitfalls)**
|
||||
서버 컴포넌트는 브라우저 API나 상태(State)를 가질 수 없으므로 대화형 인터랙션을 구현할 수 없습니다 [19]. 또한 렌더링 및 데이터 구조를 잘못 설계하여 서버 내에서 순차적으로 데이터를 페칭하게 되면, 기존 클라이언트의 워터폴 문제가 '서버 측 워터폴(Server-Side Waterfalls)'로 그대로 전이되어 응답 지연을 유발할 수 있습니다 [20, 21]. 구조적 문제를 우회하기 위해 `"use client"`를 무분별하게 남용하면 대규모 JS 번들이 다시 클라이언트로 전송되어 RSC 도입의 최적화 이점이 완전히 사라지게 됩니다 [22].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Server-Side Rendering (SSR)]], [[Client-Side Rendering (CSR)]], [[Hydration]], [[Component-Based Architecture (CBA)]], [[Interaction to Next Paint (INP)]]
|
||||
- **Projects/Contexts:** [[Next.js App Router]], [[React 19]], [[React Flight Protocol]]
|
||||
- **Contradictions/Notes:** 소스는 RSC가 단순히 "향상된 SSR"이 아니라고 명확히 선을 긋습니다. SSR은 여전히 클라이언트에 자바스크립트를 전송하고 하이드레이션을 수행해야 하지만, RSC는 특정 컴포넌트의 클라이언트 측 자바스크립트와 하이드레이션 자체를 완전히 제거한다는 점에서 본질적인 차이가 있습니다 [7, 9]. 또한 서버 컴포넌트를 도입한다고 자동으로 성능이 최적화되는 것은 아니며, 데이터 의존성을 직렬로 잘못 구성하면 서버 상에서 동일한 워터폴 현상(Server-Side Waterfalls)을 일으켜 병목을 초래할 수 있다고 경고합니다 [20, 21, 23].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,25 @@
|
||||
# [[React 성능 최적화]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
React 성능 최적화는 불필요한 리렌더링을 방지하고 번들 크기를 줄여 애플리케이션의 로딩 속도와 상호작용 반응성을 향상시키는 일련의 과정입니다 [1, 2]. 주요 원인인 리렌더링 캐스케이드와 큰 초기 자바스크립트 번들을 해결하기 위해 메모이제이션, 코드 분할, 가상화 등의 기술이 활용됩니다 [1-5]. 최근에는 React 18의 자동 배칭(Automatic Batching)과 동시성(Concurrent) 기능, React 19의 자동 메모이제이션을 지원하는 React Compiler가 도입되어 성능 최적화 작업이 더욱 자동화되고 효율적으로 발전하고 있습니다 [6-9].
|
||||
|
||||
## 📖 Core Content
|
||||
* **성능 저하의 주요 원인**: 부모 컴포넌트의 상태 변경 시 속성(props) 변경 여부와 관계없이 모든 자식 컴포넌트가 다시 렌더링되는 '리렌더링 캐스케이드(Re-Render Cascade)'가 가장 일반적인 원인입니다 [1]. 또한 대규모 자바스크립트 번들로 인한 초기 로드 지연, 렌더링 시마다 실행되는 무거운 데이터 연산, 인라인 객체 및 함수 생성 등도 성능을 저하시킵니다 [2, 10, 11].
|
||||
* **주요 성능 최적화 기법**:
|
||||
* **코드 분할 (Code Splitting)**: `React.lazy()`와 Suspense를 라우트 수준에서 활용하면 애플리케이션을 작은 청크로 나누어 로드할 수 있어 초기 번들 크기를 30~50%까지 줄이고 LCP(최대 콘텐츠풀 페인트)를 개선할 수 있습니다 [3].
|
||||
* **메모이제이션 (Memoization)**: `React.memo`, `useMemo`, `useCallback`을 사용하여 변경되지 않은 속성에 대한 불필요한 리렌더링을 방지합니다 [4, 12].
|
||||
* **리스트 가상화 (Virtualization)**: 화면에 수천 개의 항목이 있는 리스트를 렌더링할 때, 뷰포트에 보이는 항목과 약간의 버퍼만 실제 DOM 노드로 렌더링하여 DOM 크기와 렌더링 시간을 대폭 단축합니다 [5, 13].
|
||||
* **DOM 구조 최적화**: React Fragment(`<></>`)를 사용하여 구조를 위한 불필요한 래퍼(wrapper) DOM 노드 추가를 방지하고 누적 레이아웃 이동(CLS) 지표를 향상시킵니다 [14, 15].
|
||||
* **렌더링 전략 활용 (SSR, SSG, RSC)**: 서버 사이드 렌더링(SSR)이나 정적 사이트 생성(SSG)을 도입해 자바스크립트 실행 전 초기 화면 표시 속도를 높입니다 [10, 16, 17]. 특히 React Server Components(RSC)는 클라이언트 번들에 자바스크립트를 전혀 포함하지 않고 서버에서 독점적으로 실행되어 상호작용 속도를 크게 높입니다 [18-20].
|
||||
* **React 버전별 최적화 기능의 진화**:
|
||||
* **React 18**: 여러 상태 업데이트를 하나로 묶어 리렌더링을 최소화하는 '자동 배칭(Automatic Batching)'이 네이티브 이벤트뿐만 아니라 비동기 작업에도 기본 적용되었습니다 [7, 21, 22]. 또한, `useTransition`과 `useDeferredValue` 훅을 통해 무거운 연산이 메인 스레드를 차단하지 않고 렌더링을 지연시킬 수 있는 동시성(Concurrent) 기능이 도입되었습니다 [6, 23, 24].
|
||||
* **React 19 (React Compiler)**: 개발자가 수동으로 작성하던 메모이제이션을 빌드 타임에 AST(추상 구문 트리)를 분석하여 자동으로 처리해 주는 컴파일러가 도입되었습니다 [8, 9, 25]. 이를 통해 개발자는 코드의 유지보수성을 높이면서도 세밀한 반응성(fine-grained reactivity)을 확보할 수 있습니다 [8, 26].
|
||||
* **측정 기반의 최적화**: 직관에 의존하는 대신 React DevTools Profiler, Lighthouse 등 측정 도구를 활용하여 실제 렌더링 병목 지점과 Core Web Vitals 지표를 먼저 파악한 후 최적화를 진행해야 합니다 [27-31].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Virtual DOM]], [[Core Web Vitals]], [[React Compiler]], [[React Server Components]], [[Automatic Batching]]
|
||||
- **Projects/Contexts:** [[Next.js]], [[Meta Quest Store]] (React Compiler를 제품에 적용하여 초기 로드 12% 및 상호작용 속도 2.5배 개선 [32]), [[Sanity Studio]] (React Compiler 적용으로 렌더링 시간 20-30% 단축 [33])
|
||||
- **Contradictions/Notes:** 여러 소스에 따르면 메모이제이션(`useMemo`, `useCallback`, `React.memo`)은 리렌더링 방지에 강력한 도구이지만, 프로파일링 측정 없이 모든 컴포넌트에 무분별하게 적용할 경우 오히려 연산 오버헤드와 메모리 사용량을 가중시켜 애플리케이션의 성능을 저하시키는 원인(안티 패턴)이 될 수 있다고 공통적으로 경고합니다 [12, 34].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -0,0 +1,34 @@
|
||||
# [[Reflow / Repaint]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
**Reflow(레이아웃)**는 브라우저가 화면에 표시될 DOM 요소들의 정확한 위치와 기하학적 크기를 재계산하는 과정이며, **Repaint(페인트)**는 레이아웃의 변화 없이 요소의 색상이나 그림자 같은 시각적 속성만을 화면에 다시 그리는 과정입니다 [1-6]. 이 두 과정은 웹 페이지 렌더링에 필수적이지만 연산 비용이 높아 과도하게 발생할 경우 애플리케이션의 성능 저하와 버벅거림(Jank)을 유발하므로 프론트엔드 최적화의 핵심 대상이 됩니다 [7-9].
|
||||
|
||||
## 📖 Core Content
|
||||
|
||||
* **Reflow (Layout) 개념 및 발생 원인**
|
||||
* Reflow는 문서 흐름 내에서 요소의 위치, 크기(width, height, margin, padding, border 등)를 계산하는 과정입니다 [1, 4, 6].
|
||||
* DOM 요소의 추가 및 제거, 브라우저 창 크기 조절, 폰트 크기 변경, 또는 레이아웃에 영향을 주는 CSS 속성 변경 시 트리거됩니다 [4-6, 10].
|
||||
* 웹 문서는 연속적인 흐름으로 구성되어 있어, 단일 요소의 구조적 변화가 부모나 자식 요소 등 DOM 트리 전체에 걸친 재계산을 연쇄적으로 유발할 수 있으므로 연산 비용이 매우 높은 사용자 차단(User-blocking) 작업입니다 [1, 3, 5, 6].
|
||||
|
||||
* **Repaint (Paint) 개념 및 발생 원인**
|
||||
* Repaint는 레이아웃에 영향을 주지 않고, 요소의 가시성, 배경색, 텍스트 색상, 그림자 등의 시각적 스타일만 변경될 때 발생합니다 [2, 4, 6].
|
||||
* 기하학적 재계산이 필요하지 않아 Reflow보다는 상대적으로 비용이 적지만, 애니메이션 처리 중 불필요하게 자주 발생하면 여전히 프레임 드랍이나 성능 저하를 초래할 수 있습니다 [7, 9, 11].
|
||||
|
||||
* **Reflow / Repaint 최소화 및 렌더링 최적화 방법**
|
||||
* **DOM 조작 일괄 처리(Batching) 및 레이아웃 스래싱(Layout Thrashing) 방지**: DOM 읽기 및 쓰기 작업을 혼합하지 않고 한 번에 처리하여 브라우저가 레이아웃을 여러 번 재계산하는 것을 방지해야 합니다 [2, 8, 9, 12, 13].
|
||||
* **GPU 가속 활용 (Compositing)**: `top`, `left`와 같은 레이아웃 속성 대신 `transform`을, 색상 변경 대신 `opacity`를 사용하여 애니메이션을 구현하면 Reflow나 Repaint 없이 브라우저가 별도 레이어에서 요소를 처리할 수 있습니다 [8, 9, 11].
|
||||
* **구조 및 스타일 최적화**: DOM 트리의 깊이를 줄이고, 연산이 많이 필요한 복잡한 CSS 선택자(특히 자손 선택자)의 사용을 지양해야 합니다 [14]. 레이아웃 변화 없이 요소를 숨기려면 `display: none` (Reflow 유발) 대신 `visibility: hidden`을 사용하는 것이 좋습니다 [15].
|
||||
* **문서 흐름(Flow)에서 분리**: 애니메이션 등 복잡한 렌더링 변경이 일어나는 요소는 `position: absolute` 또는 `position: fixed`를 사용하여 주변 요소의 Reflow에 영향을 주지 않도록 격리해야 합니다 [14].
|
||||
|
||||
* **React의 렌더링 메커니즘과 성능 최적화**
|
||||
* 기존의 직접적인 DOM 조작은 매 변경마다 비용이 높은 Reflow와 Repaint를 유발하기 때문에 느릴 수밖에 없습니다 [16].
|
||||
* React는 **Virtual DOM**을 사용하여 메모리 상에서 이전 상태와 새로운 상태를 비교(Diffing)한 뒤, 변경된 최소한의 부분만 실제 DOM에 일괄 반영함으로써 렌더링 파이프라인의 낭비를 방지합니다 [16, 17].
|
||||
* 또한 React 18부터 도입된 **자동 일괄 처리(Automatic Batching)** 기능은 비동기 작업(Promise, setTimeout 등) 내에서 발생하는 여러 상태 업데이트를 단 한 번의 리렌더링으로 묶어서 처리하여 DOM 연산 횟수를 획기적으로 줄여줍니다 [18-20].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[DOM vs Virtual DOM]]
|
||||
- **Projects/Contexts:** [[React 기반 싱글 페이지 애플리케이션(SPA)의 렌더링 최적화]], [[Automatic Batching을 통한 React 18 성능 최적화]]
|
||||
- **Contradictions/Notes:** 소스 문서들에 따르면 `display: none`은 요소를 렌더 트리에서 완전히 제거하므로 전체적인 레이아웃 계산(Reflow)을 유발하지만, 시각적으로만 보이지 않게 처리하는 `visibility: hidden`을 사용하면 Reflow를 피할 수 있다고 권장하고 있습니다 [15, 21].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -1 +1,22 @@
|
||||
{"status":"success","answer":"","conversation_id":"65683a4c-14a1-4a03-b043-9aee964a292f"}
|
||||
# [[Server-Side Rendering (SSR)]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Server-Side Rendering (SSR)은 사용자의 요청이 있을 때마다 서버 측에서 웹 페이지의 전체 HTML을 렌더링하여 클라이언트 브라우저로 전송하는 웹 렌더링 방식입니다 [1-3]. 브라우저는 완성된 HTML을 받아 즉시 화면에 표시하며, 이후 JavaScript를 다운로드하여 페이지를 상호작용 가능하게 만드는 하이드레이션(Hydration) 과정을 거치게 됩니다 [1, 4-6]. 이 방식은 검색 엔진 최적화(SEO)와 초기 화면 표시에 매우 유리하지만, 서버 부하 증가와 상호작용 지연(TTI)이라는 성능적 트레이드오프를 동반합니다 [1, 7-9].
|
||||
|
||||
## 📖 Core Content
|
||||
* **작동 원리와 하이드레이션 (Hydration):**
|
||||
SSR 환경에서 사용자가 페이지를 요청하면, 서버는 라우팅 로직을 처리하고 데이터베이스나 API로부터 데이터를 가져와 완성된 HTML 문서를 생성하여 응답합니다 [2, 6]. 브라우저는 이 HTML을 즉시 화면에 렌더링하므로 사용자는 콘텐츠를 바로 볼 수 있지만, 이 시점의 페이지는 상호작용할 수 없는 정적인 상태입니다 [6]. 이후 브라우저가 JavaScript 번들을 다운로드하고 실행하면, React와 같은 프레임워크가 가상 DOM(Virtual DOM)을 렌더링된 HTML 구조에 매핑하여 이벤트 리스너를 연결하고 상태를 동기화합니다. 이 과정을 '하이드레이션'이라고 부릅니다 [1, 5, 10].
|
||||
|
||||
* **성능 및 사용자 경험적 이점:**
|
||||
SSR의 가장 큰 장점 중 하나는 탁월한 검색 엔진 최적화(SEO)입니다. 검색 엔진 크롤러가 JavaScript 실행을 기다리거나 빈 화면을 볼 필요 없이 완전히 렌더링된 HTML 콘텐츠에 즉시 접근하여 색인을 생성할 수 있기 때문입니다 [1, 11, 12]. 또한 첫 콘텐츠 풀 페인트(FCP) 성능이 우수하여 사용자가 빈 화면 대신 즉각적으로 시각적 요소를 볼 수 있으며, 이는 대역폭이 제한된 모바일이나 느린 3G 네트워크 환경에서 사용자 경험을 크게 개선합니다 [9, 11, 12]. 매 요청마다 서버에서 렌더링이 이루어지므로, 뉴스 사이트나 전자상거래의 제품 페이지처럼 항상 최신의 동적 데이터를 제공해야 하는 환경에 이상적입니다 [13-15].
|
||||
|
||||
* **인프라 한계 및 성능 트레이드오프:**
|
||||
모든 사용자 상호작용이나 페이지 요청 시 서버가 렌더링 연산을 수행해야 하므로 트래픽 급증 시 서버 컴퓨팅 부하가 급격히 커지며, 이는 호스팅 인프라 비용 증가와 복잡성 확대로 이어집니다 [7, 8, 16]. 서버 측에서의 HTML 생성 작업으로 인해 첫 바이트 도달 시간(TTFB)이 약 100~300ms가량 늘어날 수 있습니다 [9, 17]. 무엇보다 사용자가 가장 불편함을 느낄 수 있는 단점은 '상호작용 지연'입니다. 화면의 시각적 요소는 빠르게 로드되지만, JavaScript가 다운로드되고 하이드레이션이 완료될 때까지(기기에 따라 2~5초가량 소요될 수 있음) 페이지가 클릭이나 입력 등의 상호작용에 반응하지 않는 상호작용 시간(TTI) 저하 현상이 발생합니다 [1, 9, 10, 16].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Client-Side Rendering (CSR)]], [[Static Site Generation (SSG)]], [[Hydration]], [[Virtual DOM]], [[Search Engine Optimization (SEO)]], [[First Contentful Paint (FCP)]], [[Time to Interactive (TTI)]]
|
||||
- **Projects/Contexts:** [[Next.js]], [[React Server Components (RSC)]], [[E-commerce Platforms]]
|
||||
- **Contradictions/Notes:** 소스 문헌들은 공통적으로 SSR이 시각적 로드(FCP)를 빠르게 만들어 사용자에게 즉각적인 응답을 제공하지만, 하이드레이션 병목 현상으로 인해 실질적인 상호작용(TTI)은 CSR보다 지연된다는 성능적 역설을 주의해야 한다고 지적합니다 [9, 18].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -1 +1,18 @@
|
||||
{"status":"success","answer":"","conversation_id":"fd149a47-bca0-4e71-a17a-f69d677b2958"}
|
||||
# [[Time to Interactive (TTI)]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Time to Interactive (TTI)는 사용자의 초기 페이지 요청(DNS 조회 및 TCP 연결) 시점부터 웹 페이지가 50ms 이내에 사용자의 상호작용에 응답할 수 있는 상태가 되기까지 걸리는 시간을 측정하는 성능 지표입니다 [1]. 시각적인 콘텐츠가 화면에 표시되는 것을 넘어, 필요한 JavaScript가 모두 다운로드되고 실행되어 버튼 클릭 등의 입력에 즉각적으로 반응할 수 있는 시점을 의미합니다 [1, 2]. 특히 서버 사이드 렌더링(SSR) 환경에서는 화면이 먼저 보이지만 JavaScript가 연결(Hydration)될 때까지 상호작용이 불가능한 지연 현상이 발생하므로 TTI 최적화가 매우 중요합니다 [2, 3].
|
||||
|
||||
## 📖 Core Content
|
||||
* **TTI의 정의와 메인 스레드의 역할:** TTI는 페이지의 First Contentful Paint (FCP) 이후, 사용자의 입력(스크롤, 터치 등)에 50ms 이내로 응답할 수 있게 되는 시점을 측정합니다 [1]. 브라우저의 메인 스레드가 JavaScript를 파싱, 컴파일, 실행하느라 점유되어 있다면, 페이지는 시각적으로 완성되었더라도 상호작용할 수 없는 상태가 됩니다 [1, 4].
|
||||
* **SSR(Server-Side Rendering)과 Hydration에 따른 TTI 지연:** SSR은 서버에서 미리 렌더링된 HTML을 제공하므로 초기 콘텐츠 표시(FCP)가 빠르지만, TTI 측면에서는 불리할 수 있습니다 [2, 3, 5]. 화면의 요소가 클릭 가능해 보이더라도, JavaScript 번들이 다운로드되고 정적 HTML에 이벤트 리스너와 상태를 연결하는 'Hydration' 과정이 완료될 때까지는 반응하지 않기 때문입니다 [2, 3, 6]. JavaScript 번들 크기가 크거나 기기 성능이 낮을 경우 이 과정에 2~5초가 소요될 수 있으며, 이는 사용자에게 답답한 경험을 제공할 수 있습니다 [2, 5-7].
|
||||
* **CSR(Client-Side Rendering)과의 비교:** CSR의 경우, 초기에 브라우저가 빈 HTML 셸을 받고 JavaScript를 다운로드해야 하므로 초기 화면 표시는 느릴 수 있습니다 [8, 9]. 하지만 JavaScript 로드 후 클라이언트 측에서 렌더링이 완료되면 즉각적인 상호작용이 가능해지므로 초기 로드 이후의 TTI는 향상되는 특징을 가집니다 [10, 11].
|
||||
* **성능 최적화 관점:** TTI를 개선하기 위해서는 메인 스레드의 점유 시간을 최소화해야 합니다 [4]. 이를 위해 점진적/선택적 Hydration 기법을 적용하여 중요한 상호작용 요소를 먼저 로드하거나 [12, 13], React Server Components(RSC)를 활용하여 브라우저로 전송되는 JavaScript 번들 크기 자체를 줄임으로써 Hydration에 소요되는 비용을 원천적으로 제거할 수 있습니다 [14, 15].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Hydration]], [[Server-Side Rendering (SSR)]], [[Client-Side Rendering (CSR)]], [[First Contentful Paint (FCP)]], [[메인 스레드 (Main Thread)]]
|
||||
- **Projects/Contexts:** [[렌더링 최적화 개념 설명 자료]], [[React가 빠른 이유]]
|
||||
- **Contradictions/Notes:** 소스에 따르면 SSR과 CSR은 뚜렷한 트레이드오프를 가집니다. SSR은 FCP(초기 콘텐츠 표시)가 빠르지만 Hydration 오버헤드로 인해 TTI가 느려지는 반면, CSR은 초기 로드 속도는 느리지만 로드 이후의 상호작용(TTI 향상)은 더 부드럽고 즉각적이라는 특징이 있습니다 [11, 16-18].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
@@ -1 +1,26 @@
|
||||
{"status":"success","answer":"","conversation_id":"e1f5e242-69b1-4c49-8f3d-af31c15be109"}
|
||||
# [[Total Blocking Time (TBT)]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
Total Blocking Time(TBT)는 브라우저의 메인 스레드가 자바스크립트 실행 등으로 인해 차단되어 사용자 상호작용(입력, 클릭 등)을 처리할 수 없는 시간을 측정하는 핵심 성능 지표입니다 [1, 2]. 이 지표는 Lighthouse 성능 점수의 30%를 차지하며, 사용자 경험과 SEO 순위에 직접적인 영향을 미칩니다 [1]. 특히 React 환경에서는 서버 사이드 렌더링(SSR) 이후 전체 페이지를 한 번에 하이드레이션(Hydration)할 때 TBT가 급증하여 심각한 성능 저하와 입력 지연을 유발할 수 있습니다 [1, 3].
|
||||
|
||||
## 📖 Core Content
|
||||
|
||||
* **하이드레이션(Hydration)과 TBT의 상관관계**
|
||||
* React는 기본적으로 사용자 화면에 즉시 보이지 않는 컴포넌트까지 포함하여 전체 페이지를 동시에 하이드레이션합니다 [1].
|
||||
* 이러한 접근 방식은 불필요한 자바스크립트 실행을 유발하여 브라우저의 메인 스레드를 차단(Block)하게 되고, 결과적으로 긴 TBT와 Lighthouse 점수 하락으로 이어집니다 [1, 3].
|
||||
* TBT가 길어지면 사용자가 페이지 로드 직후 버튼을 클릭해도 즉각적으로 반응하지 않는 심각한 입력 지연(Input lag)을 경험하게 됩니다 [1, 4].
|
||||
* **중요 렌더링 경로(CRP)에서의 차단 시간**
|
||||
* TBT는 하이드레이션뿐만 아니라 브라우저의 초기 렌더링 과정과도 관련이 있습니다.
|
||||
* CSSOM을 구축하는 과정에서 CSS 선택자(Selector)의 복잡성은 렌더링 속도에 영향을 미치므로, 선택자의 명시성(specificity)을 최적화하고 CSS를 최소화(minify)하는 것은 중요 렌더링 경로(CRP)의 총 차단 시간을 줄이는 기본적인 최적화 기술입니다 [5].
|
||||
* **TBT를 최소화하는 렌더링 최적화 전략**
|
||||
* **선택적 하이드레이션 및 점진적 로딩 (Selective Hydration & Progressive Loading):** 모든 것을 한 번에 하이드레이션하는 대신, 스크롤 상단(above-the-fold) 콘텐츠를 우선 처리하고 덜 중요한 컴포넌트는 지연시킵니다 [6]. Next.js의 동적 가져오기(`next/dynamic`)를 활용하면 자바스크립트 실행을 분산시켜 메인 스레드 차단을 막고 TBT를 크게 줄일 수 있습니다 [6, 7].
|
||||
* **가시성 기반 지연 하이드레이션 (Lazy Hydration Based on Visibility):** 화면 하단 콘텐츠가 뷰포트에 들어올 때만 하이드레이션되도록 지연시키는 방법(예: IntersectionObserver 활용)을 통해 특정 애플리케이션에서 TBT를 최대 40%까지 단축할 수 있습니다 [7, 8].
|
||||
* **React 서버 컴포넌트 (React Server Components) 활용:** App Router와 같은 환경에서 서버 컴포넌트를 사용하면 클라이언트 측에서 전혀 자바스크립트가 실행되지 않으므로 하이드레이션 과정 자체가 필요 없어져 TBT와 자바스크립트 페이로드를 획기적으로 줄일 수 있습니다 [8].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[Hydration]], [[Critical Rendering Path (CRP)]], [[Server-Side Rendering (SSR)]], [[React Server Components]]
|
||||
- **Projects/Contexts:** [[Next.js]], [[Lighthouse]]
|
||||
- **Contradictions/Notes:** 소스의 내용 간 상충되는 부분은 없으며, 모든 소스가 자바스크립트의 과도한 실행이 메인 스레드를 차단하여 TBT를 악화시킨다는 점에 동의합니다. 또한, 이를 방지하기 위해 렌더링 최적화(점진적 하이드레이션, 서버 컴포넌트 사용 등)가 필수적임을 강조합니다.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
Reference in New Issue
Block a user