d8a80f6272
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해 끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은 과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업. 도구: Datacollect/scripts/link_reconcile_apply.mjs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.2 KiB
8.2 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-critical-rendering-path | Critical Rendering Path (CRP) | 10_Wiki/Topics | verified | self |
|
none | A | 0.95 | applied |
|
2026-05-10 | pending |
|
Critical Rendering Path
매 한 줄
"매 byte → 매 pixel 의 pipeline". 매 DOM + CSSOM → 매 Render Tree → 매 Layout → 매 Paint → 매 Composite. 매 web performance 의 fundamental. 매 each step 의 understand → 매 optimize 의 right tool.
매 핵심 step
1. DOM (Document Object Model)
- 매 HTML 의 incremental parse.
- 매 byte → token → node → tree.
- 매 partial 도 OK.
2. CSSOM (CSS Object Model)
- 매 CSS 의 parse.
- 매 render-blocking (vs DOM 의 incremental).
- 매 FOUC 방지.
3. Render Tree
- 매 DOM + CSSOM 의 결합.
- 매 visible element 만 (display:none 의 X).
4. Layout (Reflow)
- 매 geometry 계산 (position, size).
- 매 expensive — 매 entire subtree 의 trigger.
5. Paint (Repaint)
- 매 pixel 의 color / shadow.
- 매 layer per layer.
6. Compositing
- 매 layer 의 GPU 의 combine.
- 매 transform / opacity 의 composite-only.
Render-blocking resources
- CSS (default).
<script>(sync).- → 매 inline / async / defer 로 매 mitigate.
매 optimization
CSS
- Inline critical CSS: 매 above-fold.
media="print"for print CSS.asyncfor non-critical: deferred.- PurgeCSS / Tree-shake: unused 제거.
JavaScript
async: 매 download parallel + 매 execute when ready.defer: 매 download parallel + 매 execute after DOM.- Module split: code splitting.
- Inline critical: small.
Image
- Lazy loading:
loading="lazy". - Modern format: AVIF, WebP.
- Priority hint:
fetchpriority="high". - Responsive: srcset, sizes.
Font
font-display: swap(or optional).- Preload:
<link rel="preload">. - Subset: 매 unused glyph drop.
Network
- HTTP/2 push (deprecated, use 103 Early Hints).
- HTTP/3: 매 quic.
- CDN: 매 edge.
- Preconnect: 매 third-party.
매 anti-pattern (avoid)
- 매 layout property animate (top, left, width, height).
- 매 sync DOM measurement after write (forced reflow).
- 매
document.write(legacy). - 매 huge inline CSS / JS.
매 measurement
- DevTools Performance tab.
- Lighthouse CRP report.
- web-vitals (LCP, FCP).
💻 패턴
Async / defer JS
<!-- 매 critical inline -->
<script>
// 매 inline + small + critical
document.documentElement.classList.add('js-enabled');
</script>
<!-- 매 third-party analytics: async -->
<script async src="/analytics.js"></script>
<!-- 매 main app JS: defer -->
<script defer src="/app.js"></script>
<!-- 매 ❌ Avoid sync (default) -->
<script src="/legacy.js"></script>
Critical CSS inline
<head>
<style>
/* 매 above-fold critical */
body { font-family: system-ui; }
.hero { display: flex; height: 60vh; }
</style>
<!-- 매 rest async -->
<link rel="preload" href="/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/main.css"></noscript>
</head>
Preload + preconnect
<head>
<!-- 매 critical asset preload -->
<link rel="preload" href="/hero.avif" as="image" fetchpriority="high">
<link rel="preload" href="/inter.woff2" as="font" type="font/woff2" crossorigin>
<!-- 매 third-party preconnect -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">
</head>
Avoid forced reflow
// 매 ❌ Bad — 매 reflow per iteration
for (const el of items) {
el.style.width = el.offsetWidth + 10 + 'px'; // 매 read + write
}
// 매 ✅ Good — 매 batch read, then batch write
const widths = items.map(el => el.offsetWidth); // 매 read all
items.forEach((el, i) => {
el.style.width = widths[i] + 10 + 'px'; // 매 write all
});
Use transform / opacity (composite only)
/* 매 ❌ reflow */
.modal-bad { transition: top 200ms, width 200ms; }
/* 매 ✅ composite only */
.modal-good { transition: transform 200ms, opacity 200ms; }
.modal-good.show { transform: translateY(0); opacity: 1; }
.modal-good.hide { transform: translateY(-20px); opacity: 0; }
will-change hint (sparingly)
.about-to-animate { will-change: transform; }
/* 매 매 animation 완료 시 의 remove */
Image priority + lazy
<!-- 매 LCP candidate (above-fold) -->
<img src="/hero.avif" alt="Hero"
width="1200" height="600"
fetchpriority="high">
<!-- 매 below-fold -->
<img src="/below.avif" alt="Below"
width="800" height="600"
loading="lazy"
decoding="async">
Resource hint priority
<!-- 매 preload (high priority) -->
<link rel="preload" href="/critical.css" as="style">
<!-- 매 prefetch (next page hint) -->
<link rel="prefetch" href="/next-page.html">
<!-- 매 modulepreload -->
<link rel="modulepreload" href="/module.js">
Lighthouse CRP analysis
npx lighthouse https://example.com --only-categories=performance \
--output=json --output-path=./report.json
# 매 매 critical-request-chains 의 review
node -e "
const r = require('./report.json');
console.log(JSON.stringify(r.audits['critical-request-chains'], null, 2));
"
DevTools Performance trace
1. Open DevTools → Performance tab.
2. Click record + reload page.
3. Stop after page loaded.
4. Look at Main thread:
- Long tasks (>50ms).
- Layout thrashing (purple bars).
- Paint cost (green).
5. Identify blocking resources.
Server-Timing (server contribution)
// 매 Express middleware
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
res.set('Server-Timing', `total;dur=${Date.now() - start}`);
});
next();
});
// 매 client 의 visible
performance.getEntriesByType('navigation')[0].serverTiming;
HTTP 103 Early Hints
HTTP/2 103 Early Hints
Link: </critical.css>; rel=preload; as=style
Link: </main.js>; rel=preload; as=script
HTTP/2 200 OK
Content-Type: text/html
...
→ 매 server response 전 의 hint.
🤔 결정 기준
| 상황 | Approach |
|---|---|
| Above-fold | Inline critical CSS + preload hero image |
| Below-fold | Lazy load |
| Animations | transform + opacity only |
| Third-party | Async + preconnect |
| Heavy JS | Defer + code split |
| LCP slow | Preload + SSR + CDN |
| Layout shift | Image dimensions + aspect-ratio |
기본값: 매 inline critical + 매 defer rest + 매 modern image + 매 transform animations.
🔗 Graph
- 부모: Web-Performance · Browser · Frontend
- 변형: Reflow · Repaint · Compositing · Render Tree
- 응용: Core Web Vitals Optimization (INP, LCP 개선) · CSS Animations · Container_Queries
- Adjacent: Bottlenecks · Chrome DevTools 메모리 프로파일링 · Baseline (Web Platform Features) · Case-Study-Allbirds-PWA-Redesign
🤖 LLM 활용
언제: 매 perf audit. 매 frontend optimization. 매 LCP / FCP 의 fix. 언제 X: 매 backend (다른 model).
❌ 안티패턴
- Sync
<script>in head: 매 render block. - Many CSS files: 매 multiple round-trip.
- Layout property animate: 매 jank.
- Forced reflow loop (read-write-read): 매 layout thrashing.
- No image dimension: 매 CLS.
document.write: 매 deprecated, blocking.- Block on font (no swap): 매 invisible text.
🧪 검증 / 중복
- Verified (Ilya Grigorik "High Performance Browser Networking", web.dev CRP).
- 신뢰도 A.
- Related: Core Web Vitals Optimization (INP, LCP 개선) · CSS Animations · Container_Queries · Baseline (Web Platform Features) · Bottlenecks.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — 6 step + 매 inline / preload / async / defer / 103 code |