41 lines
7.7 KiB
Markdown
41 lines
7.7 KiB
Markdown
# [[프론트엔드 렌더링 최적화(Rendering Optimization)]]
|
|
|
|
## 📌 Brief Summary
|
|
프론트엔드 렌더링 최적화는 브라우저가 HTML, CSS, JavaScript를 화면의 픽셀로 변환하는 과정인 중요 렌더링 경로(Critical Rendering Path)를 효율화하여 애플리케이션의 응답성과 화면 표시 속도를 향상시키는 작업입니다 [1-3]. DOM 조작 시 발생하는 비용이 큰 리플로우(Reflow)와 리페인트(Repaint) 연산을 최소화하는 것이 핵심이며, React와 같은 프레임워크에서는 가상 DOM(Virtual DOM)과 파이버(Fiber) 아키텍처를 통해 이를 추상화 및 최적화합니다 [4-6]. 또한, 서비스의 특성에 따라 CSR, SSR, SSG 등의 렌더링 전략을 선택하고 하이드레이션(Hydration) 및 번들 크기를 관리함으로써 사용자 경험(Core Web Vitals)을 극대화하는 데 그 목적이 있습니다 [7-9].
|
|
|
|
## 📖 Core Content
|
|
|
|
**1. 브라우저 렌더링 과정 (Critical Rendering Path)**
|
|
브라우저는 서버로부터 HTML을 수신하면 점진적으로 문서를 파싱하여 DOM(Document Object Model) 트리를 생성하고, CSS를 파싱하여 렌더링 차단 리소스인 CSSOM(CSS Object Model) 트리를 구성합니다 [10-13]. DOM과 CSSOM이 준비되면 화면에 표시될 노드들만 포함하는 렌더 트리(Render Tree)를 합성합니다 [14, 15]. 이후 요소들의 정확한 위치와 크기를 계산하는 레이아웃(Layout 또는 Reflow) 단계를 거쳐, 픽셀을 화면에 그리는 페인트(Paint 또는 Repaint) 및 레이어들을 합성하는 컴포지팅(Compositing) 단계로 화면을 출력합니다 [16-19].
|
|
|
|
**2. 리플로우(Reflow)와 리페인트(Repaint) 최소화**
|
|
* **리플로우 (Layout):** 창 크기 변경, 요소의 추가/제거, 크기나 여백(width, height, margin 등)의 변경은 DOM 트리의 위치나 크기 계산을 다시 하게 만드는 리플로우를 유발하며 이는 계산 비용이 매우 큽니다 [4, 6, 20].
|
|
* **리페인트 (Paint):** 배경색이나 그림자 등 시각적 속성만 변경될 때 발생하며, 리플로우보다 비용이 적지만 과도하면 프레임 드롭(Jank)을 유발합니다 [17, 20, 21].
|
|
* **최적화 전략:** 불필요한 DOM 깊이를 줄이고, 복잡한 CSS 선택자를 피해야 합니다 [22, 23]. 또한 화면을 강제로 재계산하게 하는 동기적 DOM 읽기/쓰기 작업을 분리하여 레이아웃 스래싱(Layout Thrashing)을 방지하고, 애니메이션 구현 시 `transform`과 `opacity`를 활용하여 GPU 가속(Compositing)을 사용하는 것이 유리합니다 [4, 17, 21, 24].
|
|
|
|
**3. 가상 DOM(Virtual DOM)과 재조정(Reconciliation)**
|
|
React는 실제 DOM 조작의 비효율성을 피하기 위해 가상 DOM이라는 경량화된 메모리 내 UI 표현을 사용합니다 [5, 25]. 렌더링 시 이전 가상 DOM과 새로운 가상 DOM을 비교(Diffing)하여 변경된 부분만 실제 DOM에 반영합니다 [5, 25]. 이론상 트리를 비교하는 알고리즘은 O(n^3)의 복잡도를 가지지만, React는 요소 타입이 다르면 하위 트리를 완전히 새로 구축하고 리스트 요소의 경우 고유한 `key` 속성을 통해 식별하는 O(n)의 휴리스틱 알고리즘을 사용해 성능을 최적화합니다 [26, 27].
|
|
|
|
**4. React Fiber와 동시성 렌더링 (Concurrent Rendering)**
|
|
React 16부터 도입된 파이버(Fiber) 아키텍처는 동기식으로 진행되어 메인 스레드를 블로킹하던 기존 렌더링 방식을 개선했습니다 [28-30]. 렌더링 작업을 잘게 쪼개어 중단, 일시 정지, 재개가 가능하게 만들었으며(Time-slicing) [29, 31], 우선순위 레인(Lanes) 시스템을 통해 사용자 입력 같은 긴급한 작업과 데이터 가져오기와 같은 비긴급 작업을 구분하여 동시성 렌더링을 처리합니다 [32-34].
|
|
|
|
**5. 렌더링 전략: CSR, SSR, SSG, ISR**
|
|
웹의 렌더링 방식은 언제 어디서 HTML을 생성하느냐에 따라 나뉘며 각각의 트레이드오프가 존재합니다.
|
|
* **CSR (Client-Side Rendering):** 브라우저가 자바스크립트를 다운로드하고 실행해 UI를 그립니다. 상호작용은 빠르고 부드러우나 초기 로딩(FCP)이 느리고 SEO에 불리합니다 [7, 35, 36].
|
|
* **SSR (Server-Side Rendering):** 서버에서 매 요청마다 HTML을 생성해 보내므로 초기 로딩과 SEO가 우수합니다. 하지만 클라이언트에서 JS를 다운로드하고 이벤트 리스너를 연결하는 하이드레이션(Hydration) 과정이 완료될 때까지 상호작용(TTI)이 지연되는 단점이 있습니다 [37-39].
|
|
* **SSG (Static Site Generation):** 빌드 시점에 정적 HTML을 생성해 CDN을 통해 배포하므로 로딩 속도가 가장 빠르지만 동적 데이터 업데이트에 취약합니다 [40-42].
|
|
* **ISR (Incremental Static Regeneration):** 정적 페이지를 캐싱해 빠르게 제공하면서, 백그라운드에서 점진적으로 HTML을 재생성하여 데이터 최신화를 보완하는 하이브리드 전략입니다 [40, 43].
|
|
|
|
**6. React 성능 최적화 기법 (React 18 & 19)**
|
|
* **컴포넌트 리렌더링 제한 (Memoization):** 부모 컴포넌트의 렌더링이 자식으로 전파되는 계단식 리렌더링(Cascade)을 막기 위해 `React.memo`, `useMemo`, `useCallback`을 사용합니다 [44-46]. 최근 React Compiler(React 19)가 도입되면서 빌드 타임에 AST를 분석하여 정적/반응성 값을 구분하고 최적화 경계를 자동으로 추가함으로써 수동 메모이제이션의 필요성이 크게 줄어들었습니다 [47-49].
|
|
* **자동 배칭 (Automatic Batching):** React 18부터는 이벤트 핸들러뿐만 아니라 비동기 호출이나 타임아웃 내부의 다수 상태 업데이트도 하나의 리렌더링으로 자동 그룹화하여 DOM 업데이트 횟수를 줄입니다 [50-52].
|
|
* **React Server Components (RSC):** 서버에서 독점적으로 실행되고 브라우저로 JavaScript 번들을 전송하지 않는 컴포넌트 아키텍처입니다 [53, 54]. 정적 UI와 데이터 접근 로직을 서버에 두고 대규모 JS 번들 로드와 하이드레이션 단계를 생략하여 초기 성능(INP 등)을 크게 개선할 수 있습니다 [53, 55, 56].
|
|
* **기타 기법:** 화면에 보이지 않는 무거운 컴포넌트나 이미지의 지연 로딩(`React.lazy()`, Lazy Loading), 대규모 리스트의 가상화(Virtualization), 디바운싱(Debouncing) 등이 필수적으로 적용됩니다 [57-60].
|
|
|
|
## 🔗 Knowledge Connections
|
|
- **Related Topics:** [[Critical Rendering Path]], [[Reflow and Repaint]], [[Virtual DOM]], [[React Fiber Architecture]], [[Hydration]], [[Server-Side Rendering (SSR)]], [[Client-Side Rendering (CSR)]], [[React Compiler]], [[React Server Components (RSC)]]
|
|
- **Projects/Contexts:** Next.js 기반 웹 성능 최적화 프로젝트, 대규모 데이터 대시보드 및 이커머스 플랫폼 렌더링 전략 구축
|
|
- **Contradictions/Notes:** 소스에 따르면 CSR은 동적인 상호작용성(Interactive)에 강점이 있으나 초기 로딩 속도와 SEO에 한계가 있는 반면, SSR은 초기 콘텐츠 표시와 SEO에는 유리하지만 하이드레이션(Hydration)이 완료되기 전까지 사용자의 입력이 차단되는(TBT/TTI 지연) 상충 관계(Trade-off)를 갖습니다 [7, 37, 61-64]. 또한 최근 도입된 React Compiler는 자동으로 세분화된 수준(Fine-Grained)의 메모이제이션을 수행하지만, `useLocation`이나 `useMutation` 처럼 렌더링마다 새로운 객체를 반환하여 참조 안정성(Reference Equality)을 깨뜨리는 서드파티 라이브러리를 사용할 경우 자동 최적화가 무력화되어 수동 메모이제이션이 여전히 필요할 수 있습니다 [49, 65-67].
|
|
|
|
---
|
|
*Last updated: 2026-04-25* |