Files
2nd/10_Wiki/Topics/AI_and_ML/브라우저 렌더링 프로세스 (CRP).md
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

5.6 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-브라우저-렌더링-프로세스-crp 브라우저 렌더링 프로세스 (CRP) 10_Wiki/Topics verified self
Critical Rendering Path
CRP
렌더링 파이프라인
none A 0.9 applied
browser
rendering
performance
web
2026-05-10 pending
language framework
javascript web-platform

브라우저 렌더링 프로세스 (CRP)

매 한 줄

"매 byte → pixel 의 6-stage pipeline". CRP는 HTML/CSS/JS bytes 가 actual pixels 가 되기 전 거치는 parse → DOM/CSSOM → Render Tree → Layout → Paint → Composite 단계. 매 stage 차단/지연 의 LCP, INP regression 의 root cause.

매 핵심

매 6-stage pipeline

  • Parse: HTML byte stream → token → DOM. CSS bytes → CSSOM (render-blocking).
  • Render Tree: DOM + CSSOM merge, display:none 제외.
  • Layout (Reflow): 매 element 의 geometric box (x, y, w, h) 계산.
  • Paint: pixels 의 layer 별 raster (text, color, image, shadow).
  • Composite: GPU 의 layer 합성 — transform, opacity 만 매 단계 처리 가능.

매 차단 요소

  • CSS 매 default render-blocking — <head> 의 위치 의 영향.
  • <script> 매 default parser-blocking — defer / async 의 회피.
  • Synchronous JS 매 layout 강제 (forced reflow / layout thrashing).

매 응용

  1. LCP 최적화 — critical CSS inline + preload hero image.
  2. INP 최적화 — long task 분할, requestIdleCallback 활용.
  3. Composite-only animation — transform / opacity 만 60fps 보장.

💻 패턴

Critical CSS inline (LCP < 2.5s)

<head>
  <style>
    /* Above-the-fold critical CSS only */
    body { margin: 0; font: 16px/1.5 system-ui; }
    .hero { height: 100vh; background: #0a0a0a; }
  </style>
  <link rel="preload" href="/fonts/inter.woff2" as="font" crossorigin>
  <link rel="stylesheet" href="/full.css" media="print" onload="this.media='all'">
</head>

Defer non-critical JS

<!-- parse 안 차단 — DOM 완료 후 실행 -->
<script defer src="/app.js"></script>
<!-- 매 즉시 download but execution 매 비동기 -->
<script async src="/analytics.js"></script>

Layout thrashing 회피

// 매 안 좋은 패턴 — read/write interleave 의 N forced reflow
boxes.forEach(box => {
  const w = box.offsetWidth;          // read (force layout)
  box.style.width = (w * 2) + 'px';   // write (invalidate)
});

// 매 fix — batch read, batch write
const widths = boxes.map(b => b.offsetWidth);  // batch read
boxes.forEach((b, i) => b.style.width = widths[i] * 2 + 'px');  // batch write

Composite-only animation

/* 매 GOOD — GPU compositor 의 처리, layout/paint skip */
.slide {
  transform: translateX(0);
  transition: transform 200ms ease-out;
  will-change: transform;  /* hint to compositor */
}
.slide.active { transform: translateX(100%); }

/* 매 BAD — 매 frame 의 layout + paint 야기 */
.slide-bad {
  left: 0;
  transition: left 200ms;
}

CSS containment (scope reflow)

.card {
  contain: layout style paint;  /* 매 card 의 reflow 가 outer 에 전파 안 됨 */
  content-visibility: auto;     /* offscreen skip */
}

INP 최적화 — yield to main thread

async function processLargeList(items) {
  for (let i = 0; i < items.length; i++) {
    process(items[i]);
    if (i % 50 === 0) {
      await new Promise(r => setTimeout(r, 0));  // yield
    }
  }
}

// 매 modern API (2026)
function yieldToMain() {
  return scheduler.yield ? scheduler.yield() : new Promise(r => setTimeout(r));
}

PerformanceObserver — measure CRP

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(entry.name, entry.startTime, entry.duration);
  }
}).observe({ type: 'largest-contentful-paint', buffered: true });

new PerformanceObserver((list) => {
  for (const e of list.getEntries()) {
    if (e.duration > 50) console.warn('Long task:', e);
  }
}).observe({ type: 'longtask', buffered: true });

매 결정 기준

상황 Approach
Hero image LCP 느림 <link rel=preload> + fetchpriority=high
Animation jank transform/opacity 만, will-change hint
큰 list scroll lag content-visibility: auto
Form input INP > 200ms scheduler.yield(), debounce
Third-party script blocking async + Partytown

기본값: defer non-critical JS, inline critical CSS, composite-only animation.

🔗 Graph

🤖 LLM 활용

언제: jank/LCP/INP 회귀 진단, animation 최적화, third-party script 영향 분석. 언제 X: 매 framework-specific reactivity (React reconciler) 매 별도 layer — CRP 만 으로 안 풀림.

안티패턴

  • document.write 사용: parser block, modern browser 의 무시.
  • synchronous XHR: main thread block, INP 파괴.
  • inline script after CSS: CSSOM wait 의 parser stall.
  • animate width/top: 매 frame layout — composite-only 만 사용.
  • @import in CSS: serialize CSS download — <link> 의 사용.

🧪 검증 / 중복

  • Verified (web.dev — Critical Rendering Path, Chrome DevTools Performance panel docs).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — CRP 6-stage pipeline + LCP/INP patterns