Files
2nd/10_Wiki/Topics/Frontend/성능 최적화(Reflow & Repaint).md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

5.1 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-repaint 성능 최적화(Reflow & Repaint) 10_Wiki/Topics verified self
Reflow
Repaint
Layout Thrash
레이아웃 트래싱
none A 0.93 applied
frontend
performance
browser
rendering
dom
2026-05-10 pending
language framework
javascript browser

성능 최적화(Reflow & Repaint)

매 한 줄

"매 layout(=reflow) 의 비싸고, paint 의 cheap-er, composite 의 cheapest". 매 DOM/CSS write 의 invalidate 의 trigger — geometry change → reflow + repaint, color-only change → repaint, transform/opacity → composite-only. Layout thrashing 의 batch read/write 의 fix.

매 핵심

매 cost ladder

  1. Composite only (cheap, 60fps): transform, opacity, filter (some).
  2. Paint (medium): color, background-color, box-shadow, border-radius.
  3. Layout (Reflow) (expensive): width, height, top/left, margin, padding, font-size, display.
  4. Full reflow trigger: <html> font change, viewport resize.

매 reflow triggers (write)

  • DOM 의 add/remove.
  • display/position change.
  • size/box-model property change.
  • font/text content change.
  • pseudo-class (:hover) 의 layout-affecting style.

매 forced sync layout (read)

  • offsetTop/Left/Width/Height, clientTop/..., scrollTop/....
  • getComputedStyle(), getBoundingClientRect().
  • 매 pending invalidation 의 있을 때 read → 매 browser 의 immediate layout 의 trigger.

💻 패턴

Layout thrash 의 fix (read-then-write)

// X — N reflow (each iteration forces layout)
boxes.forEach(b => {
  const w = b.offsetWidth;
  b.style.width = (w + 10) + 'px';
});

// O — 1 reflow (read all, then write all)
const widths = boxes.map(b => b.offsetWidth);
boxes.forEach((b, i) => b.style.width = (widths[i] + 10) + 'px');

requestAnimationFrame batching

let pending = false;
function update(el) {
  if (pending) return;
  pending = true;
  requestAnimationFrame(() => {
    el.style.transform = `translateX(${nextX}px)`;
    pending = false;
  });
}
window.addEventListener('scroll', () => update(stickyEl));

Detach → mutate → reattach (huge DOM ops)

const list = document.getElementById('list');
const fragment = document.createDocumentFragment();
for (const item of items) {
  const li = document.createElement('li');
  li.textContent = item.name;
  fragment.appendChild(li);
}
list.appendChild(fragment); // 1 reflow, not N

transform 의 substitute (animation)

/* X — top change → reflow per frame */
@keyframes slide-bad { from { top: 0 } to { top: 100px } }

/* O — transform → composite only */
@keyframes slide-good { from { transform: translateY(0) } to { transform: translateY(100px) } }

will-change (sparingly)

/* 매 animation 직전 의 hint, 매 finish 후 remove */
.card { will-change: transform; }
.card.done { will-change: auto; }

contain (CSS containment)

/* 매 subtree 의 layout/paint 의 isolate — outer 의 invalidation 의 not propagate */
.widget { contain: layout paint; }

Position fixed/sticky (composite layer)

.toolbar {
  position: sticky; top: 0;
  /* GPU layer — scroll 시 reflow 없음 */
}

IntersectionObserver (no scroll handler)

const io = new IntersectionObserver((entries) => {
  for (const e of entries) {
    if (e.isIntersecting) e.target.classList.add('in-view');
  }
}, { rootMargin: '0px 0px -10% 0px' });
images.forEach(img => io.observe(img));

매 결정 기준

변경 Cost
transform / opacity composite only — 60fps OK
background-color paint — usually OK
top/left/width/height layout — animation 의 avoid
display layout — modal toggle 의 OK, animation 의 X
font-size (root) full document reflow — extreme cost

기본값: 매 animation → transform/opacity 만, batch read/write, large insert → DocumentFragment, off-screen → content-visibility / IntersectionObserver.

🔗 Graph

🤖 LLM 활용

언제: layout thrash 의 detect (read-write interleave pattern), animation property 의 review. 언제 X: actual paint profiling — Chrome DevTools Performance/Layers panel 의 use.

안티패턴

  • will-change everywhere: 매 GPU memory exhaustion.
  • top/left animation: 매 reflow per frame — transform 의 substitute.
  • scroll handler 의 layout read: 매 thrash — IntersectionObserver 의 use.
  • innerHTML 의 loop: 매 N reflow — fragment 의 build.

🧪 검증 / 중복

  • Verified (web.dev/articles/animations-guide, Paul Lewis "Avoid Large, Complex Layouts", CSSOM View spec).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — reflow trigger + 8 패턴 + 결정 기준 의 정리