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

6.4 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-reflow-and-repaint Reflow and Repaint 10_Wiki/Topics verified self
Layout Thrashing
Browser Rendering
Compositing
none A 0.9 applied
browser
rendering
performance
dom
web
2026-05-10 pending
language framework
javascript web

Reflow and Repaint

매 한 줄

"매 DOM mutation 의 cost 의 reflow 의 dominate". Browser rendering pipeline 의 layout (reflow) → paint (repaint) → composite. Reflow 의 가장 expensive — geometry recalc 매 children. 2026 의 GPU compositing + Layout API 의 mitigate.

매 핵심

매 Pipeline

  1. Style — CSS 의 element 의 match.
  2. Layout (Reflow) — geometry (width/height/position) compute.
  3. Paint (Repaint) — pixel 의 layer 의 fill.
  4. Composite — layers 의 GPU 의 combine.

매 Reflow triggers

  • Geometric 변화: width, height, top, padding, font-size.
  • DOM mutation: appendChild, removeChild.
  • Read-then-write 패턴: offsetHeight (force sync layout).
  • Window resize, font load.

매 Repaint-only triggers (no reflow)

  • color, background-color, visibility.
  • 매 cheap relative.

매 Composite-only (cheapest)

  • transform, opacity (with will-change or layer promotion).
  • GPU 의 handle — 60fps 의 가능.

매 Layout thrashing

  • 매 read → write → read → write 의 loop → 매 forced sync layout 의 매 step.
  • Fix: 매 batch reads, batch writes.

매 Modern APIs

  • requestAnimationFrame: 매 paint 직전 의 schedule.
  • IntersectionObserver: 매 scroll 의 listen 의 X.
  • ResizeObserver: layout 의 element-level observe.
  • CSS contain: layout/paint: subtree isolation.
  • content-visibility: auto: viewport 외 의 skip render.
  • CSS Houdini Layout API: custom layout — 매 2026 widely available.
  • View Transitions API: smooth page-to-page animation.

매 응용

  1. List virtualization (react-virtual, TanStack Virtual).
  2. Animation 의 transform/opacity-only.
  3. SPA route transition (View Transitions).
  4. Long-list performance (content-visibility).
  5. Charting (Canvas/WebGL 의 DOM 의 avoid).

💻 패턴

Layout thrashing 의 fix

// BAD — 매 iteration 의 forced reflow
for (const el of items) {
  const w = el.offsetWidth;        // read
  el.style.width = (w + 10) + "px"; // write — invalidates layout
}

// GOOD — batch reads, then batch writes
const widths = items.map(el => el.offsetWidth);
items.forEach((el, i) => { el.style.width = (widths[i] + 10) + "px"; });

transform animation (composite-only)

.card { will-change: transform; transition: transform 200ms ease-out; }
.card:hover { transform: translateY(-4px) scale(1.02); }
/* 매 60fps GPU 의 — top/left 의 use 의 X */

content-visibility

.long-article > section {
  content-visibility: auto;
  contain-intrinsic-size: 0 500px;  /* 매 placeholder size */
}
/* 매 viewport 외 의 layout/paint 의 skip — 10x 빠름 매 long page */

IntersectionObserver (lazy)

const io = new IntersectionObserver(entries => {
  entries.forEach(e => {
    if (e.isIntersecting) {
      e.target.src = e.target.dataset.src;
      io.unobserve(e.target);
    }
  });
}, { rootMargin: "200px" });

document.querySelectorAll("img[data-src]").forEach(img => io.observe(img));

View Transitions API (2026)

async function navigate(url) {
  if (!document.startViewTransition) { location.href = url; return; }
  document.startViewTransition(async () => {
    const html = await fetch(url).then(r => r.text());
    document.body.innerHTML = parseBody(html);
  });
}

React virtualization (TanStack)

import { useVirtualizer } from "@tanstack/react-virtual";

function List({ items }: { items: Item[] }) {
  const parentRef = useRef<HTMLDivElement>(null);
  const v = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 40,
    overscan: 5,
  });
  return (
    <div ref={parentRef} style={{ height: 600, overflow: "auto" }}>
      <div style={{ height: v.getTotalSize(), position: "relative" }}>
        {v.getVirtualItems().map(vi => (
          <div key={vi.key} style={{ position: "absolute", top: vi.start,
                                      height: vi.size, width: "100%" }}>
            {items[vi.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}

Profile with PerformanceObserver

new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 50) console.warn("Long task:", entry);
  }
}).observe({ entryTypes: ["longtask"] });

매 결정 기준

상황 Approach
Animate position transform + will-change
Animate color OK (repaint only, cheap)
Long list (>1000) Virtualize (TanStack Virtual)
Static long page content-visibility: auto
Subtree isolation contain: layout paint
Page transition View Transitions API
Charts / heavy draw Canvas / WebGL

기본값: 매 transform/opacity 의 animate, virtualize 매 >100 rows, profile with Chrome Performance panel.

🔗 Graph

🤖 LLM 활용

언제: 매 perf bottleneck explain (read flame chart), code review for layout thrash, CSS containment recommend. 언제 X: actual measurement (Chrome DevTools / Lighthouse 의 use), pixel-level paint debugging.

안티패턴

  • top/left animate: 매 매 frame reflow → 30fps. transform 의 use.
  • Read-write loop: layout thrashing — batch.
  • !important 의 abuse: 매 specificity war 의 reflow rules complex 의.
  • Deep DOM (10k+ nodes): 매 reflow time 의 linear. virtualize.
  • Sync getBoundingClientRect 매 RAF: forces layout — cache.

🧪 검증 / 중복

  • Verified (Chrome DevTools docs, web.dev rendering, MDN content-visibility, View Transitions spec).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — pipeline + 2026 modern APIs