forced reflow (layout thrashing)

강정우·2025년 2월 20일
0

JavaScript

목록 보기
55/55

offsetHeight

스크롤 기반의 자소서 사이트를 만드는 과정에서 강도테스트를 진행하던 중 랜덤하게 버그가 발생하는 현상이 나타났다.
주로 display 를 none 혹은 flex(block) 과 opacity 를 사용하는 과정에서 일어났는데 원인을 알아보자.

📝 정의

offsetHeight 는 JS에서 HTML 요소의 레이아웃을 강제로 다시 계산하게 만드는(reflow) 속성 중 하나이다.

🔎 element.offsetHeight 의 주요 목적

브라우저는 보통 여러 스타일 변경을 일괄 처리하려고 하는데, 때로는 이러한 일괄 처리가 원하는 애니메이션 효과를 방해할 수 있다.

그럼 일단 브라우저의 렌더링 최적화와 batching 에 대해 알아보자.

✨ 브라우저의 렌더링 최적화와 일괄 처리(batching) 과정

1. 브라우저의 렌더링 파이프라인

스타일 변경 → Recalculate Style → Layout(Reflow) → Paint → Composite

2. 일괄 처리의 작동 방식

브라우저는 성능 최적화를 위해 마이크로태스크 큐(microtask queue)에 스타일 변경사항들을 모아둔다.
그리고 다음 프레임을 그릴 때(통상 16.67ms, 60fps 기준) 한번에 처리한다.

예를 들어 아래 괕이 style 을 수정한다면 이를 한큐에 처리한다는 것이다.

element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '20px';

하지만 중간에 아래와 같이 offsetHeight 가 들어가 있다면 중간에 브라우저는 offsetHeight 를 정확히 계산하기 위해 그 시점까지의 모든 스타일 변경사항을 즉시 처리해야 한다.

element.style.width = '100px';
console.log(element.offsetHeight);
element.style.height = '100px';

특히 display: none 에서 display: block 으로 변경한 직후에 fade-in 애니메이션을 시작하려면 브라우저에게 실제로 해당 변경사항을 즉시 적용하라고 강제해야한다.

이것이 바로 offsetHeight를 강제 리플로우(forced reflow)를 일으키는 용도로 사용하는 이유이다.
특히 애니메이션에서 display 속성 변경 직후 transition을 적용하려면, 브라우저의 일괄 처리를 기다리지 않고 즉시 레이아웃을 계산하도록 만들어야 하기 때문이다.
이런 forced reflow 는 성능에 영향을 줄 수 있어서 꼭 필요한 경우에만 사용해야 한다는 것이 굉장히 중요한 포인트 이다!!

  • 참고로 offsetHeight 외에도 offsetWidth, clientHeight, scrollHeight 등의 속성을 읽는 것도 같은 효과를 낸다.
    이러한 기법을 "강제 리플로우(forced reflow)" 또는 "레이아웃 스래싱(layout thrashing)"이라고 부릅니다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글

관련 채용 정보