Files
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

153 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-render-tree
title: Render Tree
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Browser-Render-Tree, Layout-Tree]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [browser, rendering, performance, web]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: javascript
framework: web-platform
---
# Render Tree
## 매 한 줄
> **"매 DOM × CSSOM = Render Tree"**. Browser는 매 parsed HTML (DOM) 과 매 styles (CSSOM) 을 매 merge — visible nodes만 매 골라 layout, paint, composite의 input 으로 사용. 2026 Chromium은 매 LayoutNG + RenderingNG로 매 진화.
## 매 핵심
### 매 Pipeline (Critical Rendering Path)
1. **HTML → DOM** (tokenize + tree construct).
2. **CSS → CSSOM** (parse stylesheets, compute cascade).
3. **DOM + CSSOM → Render Tree** — 매 `display: none` 노드는 매 제외, `::before`/`::after` 매 포함.
4. **Layout (Reflow)** — geometry 계산.
5. **Paint** — pixel commands → layers.
6. **Composite** — GPU layer merge → screen.
### 매 Render Tree ≠ DOM
- DOM 의 모든 노드 의 X. `<head>`, `<script>`, `display:none` 매 제외.
- `visibility: hidden` 의 매 포함됨 (매 space 차지).
- Pseudo-elements (`::before`) 매 추가됨 (DOM 에 없음).
### 매 Blocking
- **CSS 의 render-blocking by default**: CSSOM 완성 전에는 매 render tree 못 만듦.
- `<script>` 의 parser-blocking — `defer`/`async`로 완화.
- `<link rel="preload">` + `media` query 매 selective load.
### 매 2026 modern state (RenderingNG)
- **LayoutNG** — fragment tree로 매 incremental, isolation.
- **CompositeAfterPaint (CAP)** — paint ordering 의 매 composite 단계로 통합.
- **Off-main-thread scrolling/animation** — composite-only properties (`transform`, `opacity`) 매 main thread skip.
- **CSS Containment** (`contain: layout paint`) — subtree isolation.
- **content-visibility: auto** — 매 viewport 외 subtree skip layout/paint.
### 매 응용
1. Critical CSS inline → 매 first paint 단축.
2. `content-visibility: auto` 매 long page virtualization.
3. `will-change: transform` 매 layer promotion hint.
## 💻 패턴
### Critical CSS inline
```html
<head>
<style>
/* above-the-fold only */
.hero { font-size: 3rem; color: #111; }
</style>
<link rel="preload" href="/main.css" as="style" onload="this.rel='stylesheet'">
</head>
```
### content-visibility virtualization
```css
article.long-section {
content-visibility: auto;
contain-intrinsic-size: 0 1000px; /* placeholder size */
}
```
### Composite-only animation (avoid layout/paint)
```css
.menu { transform: translateX(-100%); transition: transform 200ms ease; }
.menu.open { transform: translateX(0); }
/* GPU composites; main thread free */
```
### Avoid layout thrashing
```javascript
// BAD: read-write-read-write triggers sync layout each iter
for (const el of items) {
el.style.width = el.offsetWidth + 10 + 'px';
}
// GOOD: batch reads, then batch writes
const widths = items.map(el => el.offsetWidth);
items.forEach((el, i) => { el.style.width = widths[i] + 10 + 'px'; });
```
### CSS Containment
```css
.card {
contain: layout style paint;
/* descendant changes can't affect outside */
}
```
### Render-blocking analysis
```javascript
// Find render-blocking resources via PerformanceObserver
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.renderBlockingStatus === 'blocking') {
console.warn('blocking:', entry.name);
}
}
}).observe({ type: 'resource', buffered: true });
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| First-paint 단축 | Critical CSS inline + async/defer JS |
| Long scrollable page | `content-visibility: auto` |
| Smooth animation | Composite-only (transform/opacity) + `will-change` |
| Widget isolation | `contain: layout paint` |
| Hidden tab UI | `display: none` (full skip) vs `visibility: hidden` (preserve space) |
**기본값**: composite-only animations, defer non-critical CSS/JS, contain on widgets.
## 🔗 Graph
- 부모: [[Browser-Rendering]] · [[Critical-Rendering-Path]]
- 응용: [[Web-Performance]] · [[Core Web Vitals Optimization (INP, LCP, CLS)|Core-Web-Vitals]]
- Adjacent: [[Reflow_and_Repaint]] · [[CSSOM]] · [[DOM]]
## 🤖 LLM 활용
**언제**: performance audit explanations, CSS-perf debugging.
**언제 X**: production profiling은 매 real Chrome DevTools / Lighthouse / WebPageTest 사용 — LLM의 매 verification은 X.
## ❌ 안티패턴
- **Layout thrashing**: read/write 매 interleave → forced synchronous layout.
- **`top`/`left` animation**: triggers layout per frame; use `transform`.
- **거대 inline `<style>`**: matched HTML cache의 invalidation. Critical only.
- **`will-change` overuse**: 매 모든 element 에 적용 → memory blow-up.
## 🧪 검증 / 중복
- Verified (web.dev rendering performance, Chromium RenderingNG docs, MDN CRP).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — full rewrite covering DOM/CSSOM merge, blocking, modern RenderingNG |