Files
2nd/10_Wiki/Topics/AI_and_ML/Critical_Rendering_Path.md
T
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

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
CRP
critical rendering path
browser pipeline
DOM
CSSOM
render tree
reflow
repaint
compositing
none A 0.95 applied
web-performance
browser
dom
cssom
render-tree
reflow
repaint
compositing
frontend-engineering
2026-05-10 pending
language framework
web standards any browser

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.
  • async for 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

🤖 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.

🧪 검증 / 중복

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — 6 step + 매 inline / preload / async / defer / 103 code