"매 layout thrashing = read DOM geometry → write style → read DOM 매 반복 — 매 force sync layout 매번". 매 브라우저 매 batch reflow 의 X — 매 즉시 reflow 강제 — 매 100x 느림. 매 해결 = 매 read 모두 batch → 매 write 모두 batch.
매 핵심
매 트리거 (read = force layout)
offsetTop/Left/Width/Height.
clientTop/Left/Width/Height.
scrollTop/Left/Width/Height.
getBoundingClientRect().
getComputedStyle() (some properties).
innerText (특정 case).
매 메커니즘
매 write (el.style.x = ...) — 매 layout invalidate, 매 brower 매 batch 대기.
매 read (el.offsetWidth) — 매 latest geometry 필요 — 매 강제 reflow.
매 loop 안 read/write alternate — 매 매번 reflow — 매 thrashing.
매 해결
Batch: read 모두 → write 모두.
Cache: 매 1회 read, 매 변수 저장.
rAF: read in current frame, write in next frame.
FastDOM library — read/write queue.
CSS containment: contain: layout — 매 thrashing 매 isolate.
💻 패턴
Anti — 매 thrashing
constitems=document.querySelectorAll('.item');items.forEach(el=>{// 매 read → 매 write → 매 read → 매 write — 매 thrashing
el.style.width=el.offsetWidth+10+'px';});// 매 100 items → 매 100 layouts
Fix — batch
constitems=document.querySelectorAll('.item');// 매 phase 1: read 모두
constwidths=Array.from(items).map(el=>el.offsetWidth);// 매 phase 2: write 모두
items.forEach((el,i)=>{el.style.width=widths[i]+10+'px';});// 매 1 layout
rAF read/write split
functionsyncSizes(){// 매 current frame: read
constheights=Array.from(rows).map(r=>r.offsetHeight);requestAnimationFrame(()=>{// 매 next frame: write
rows.forEach((r,i)=>{r.style.minHeight=heights[i]+'px';});});}
FastDOM
importfastdomfrom'fastdom';fastdom.measure(()=>{constw=el.offsetWidth;fastdom.mutate(()=>{el.style.width=w+10+'px';});});// 매 internally batch — 매 1 layout per frame
ResizeObserver (매 read 필요 X)
constro=newResizeObserver(entries=>{for(constentryofentries){const{width,height}=entry.contentRect;// 매 already computed
entry.target.dataset.width=width;// 매 write — 매 layout 의 X
}});ro.observe(element);
CSS Containment (isolate)
.widget{contain:layout;/* 매 widget 내부 변경 — 매 outer 매 reflow 의 X */}
DevTools 측정
performance.mark('layout-start');heavyOperation();performance.mark('layout-end');performance.measure('layout','layout-start','layout-end');// 매 DevTools Performance panel — 매 purple "Layout" bar — 매 thrashing 표시
Virtual list (대량 item)
// 매 모든 item layout — 매 X
// 매 visible 만 render — 매 react-virtual / @tanstack/virtual
import{useVirtualizer}from'@tanstack/react-virtual';constrowVirtualizer=useVirtualizer({count:10000,getScrollElement:()=>parentRef.current,estimateSize:()=>40,});
매 결정 기준
상황
접근
Loop 안 size 읽고 변경
batch read → batch write
비동기 read/write
rAF split
Element resize 감지
ResizeObserver
Component-level isolation
contain: layout
1000+ rows
Virtualization
Library 매 abstraction
FastDOM
기본값: read all → write all + 매 ResizeObserver (size 감지) + 매 Virtual list (대량).