렌더링 최적화(Reflow, Repaint)
- JavaScript
📖 Reference 📎https://boxfoxs.tistory.com/408 📎https://velog.io/@bumsu0211/브라우저-렌더링-과정과-최적화
🎨 렌더링 최적화?
우선, 렌더링 엔진 동작 과정을 살펴보자.

만약, 사용자가 브라우저를 통해 웹 사이트에 접속하면 브라우저는 서버로부터 HTML, CSS, JavaScript 등 웹 사이트에 필요한 리소스를 다운받는다.
필요한 리소스를 전달받은 렌더링 엔진 은 다음과 같이 진행된다.
- 렌더링 엔진은 전달받은
HTML 문서를파싱(Parsing)하여문서 객체 모델(DOM)트리를 만든다. DOM 트리를 만든 뒤 렌더링 엔진은CSS 파일을 파싱하여CSS 객체 모델(CCSOM) 트리를 만든다.- 렌더링 엔진은 제작한
DOM 트리와CSSOM 트리를 결합하여Render 트리를 만든다.
→ Render Tree 는 DOM 트리와 CSSOM 트리를 이용해 생성하는 렌더링을 목적으로 한 트리이며, 렌더링은 브라우저가 사용자에게 보여줄 화면을 그리는 과정이다.
- 이때, 화면에 보이지 않는 요소드는
Render Tree에서 제외된다. - ex)
<head><link><meta>display: none등등..
레이아웃(Layout)과정을 통해 각 요소를 어디에 배치할지 결정한다.
→ 레이아웃(Layout) 과정은 Render Tree 를 기반으로 HTML 요소의 위치, 크기를 계산하여 브라우저 화면 중 어디에 배치할 것인지 결정하는 과정이다.
레이아웃(Layout)과정이 끝나면UI 백엔드에서Render 트리를 화면에 그린다.
→ 해당 과정은 Painting 과정으로, 위 레이아웃(Layout) 과정에서 계산된 값을 바탕으로 실제 화면의 픽셀을 채워나가는 과정이다.
- 이때, 처리해야할 스타일(Style)이 복잡한 경우,
Paint되는 시간 소요가 많아진다.
Painting 과정이 끝나면 텍스트에 불과한 HTML 파일의 내용들이 이미지화된 모습으로 브라우저 화면에 출력된다.
🤔 리플로우(Reflow)와 리페인트(Repaint)란?
위 렌더링 과정을 거쳐 최종적으로 페이지가 그려졌다.
만약, 사용자가 브라우저 화면의 크기를 조절하거나 화면에 요소가 추가/삭제되는 경우 화면에 있던 요수들의 크기는 어떻게 될까?
화면에 나타나는 모습이 바뀌기 위해서는, 모든 요소의 위치와 크기를 다시 계산하고 다시 그려야한다.
그렇다면 리플로우(Reflow) 와 리페인트(Repaint) 의 역할은 무엇일까?
💡리플로우(Reflow)
: 웹 인터랙션으로 인해 렌더링 과정 중 레이아웃(Layout) 단계를 반복 수행하는 것.
인터렉션(Interaction)혹은인터랙티브(interactive)는 사용자가 브라우저 안에서 상호작용, 데이터 교류 등 동적인 활동을 뜻한다.
💡리페인트(Repaint)
: 웹 인터랙션으로 인해 렌더링 과정 중 페인트(Paint) 단계를 반복 수행하는 것.
💻 리플로우(Reflow)와 리페인트(Repaint)가 일어나는 예시
const newDiv = document.createElement('div');
document.body.append(newDiv);
div.textContent = "새로운 요소 추가";
위와 같이 JavaScript 를 통해 DOM 을 조작하는 경우, 브라우저는 DOM 트리 다시 구성하여 CSSOM 트리 와 합쳐 새로운 Render Tree 를 구축한다.
그 후, 레이아웃(Layout) 과 페인트(Paint) 과정을 다시 한 번 거쳐 화면에 출력한다.
🤔왜 렌더링 최적화를 해야하지?
- 리플로우(Reflow) 과정은
레이아웃(Layout)과정을 다시한다.
→ 레이아웃(Layout) 과정은 Render Tree 를 기반으로 HTML 요소의 위치, 크기 등을 계산하여 배치할 공간을 선정하는 과정이다.
→ 💡 즉, 배치를 위한 연산 이 진행되기에 CPU를 많이 차지한다.
- 리페인팅(Repaint) 과정은
페인팅(Paint)과정을 다시한다.
→ 페인팅(Paint) 과정은 레이아웃(Layout) 과정에서 결정된 요소들을 그리는 작업을 수행한다.
→ 💡즉, 요소들을 화면에 다시 그려야 하기에 GPU를 많이 차지한다.
❗따라서, 리플로우와 리페인트가 많이 발생하면 프레임 드랍(Frame Drop) 과 같은 현상이 발생할 수 있다.

😮 그렇다면 리플로우와 리페인팅을 최적화할 수 있는 방법은?
1. 불필요한 레이아웃을 줄인다.
: CSS 속성 중 레이아웃(Layout) 과정을 발생시키는 속성들이 존재한다.
- 해당 속성을 사용하면 매번 렌더 트리를 만들고, 레이아웃 과정을 거쳐, 페인팅 과정을 발생시킨다.
따라서, 레이아웃을 발생시키는 속성을 피하면 위와 같이 렌더링 과정이 발생하는 횟수를 줄일 수 있다.
1-1. 레이아웃 과정과 페인트 과정을 발생시키는 CSS 속성들
: 리플로우 시 리페인트는 필연적으로 발생한다.
- 따라서, 가능하다면 리플로우가 발생하는 속성보다는 리페인트만 발생시키는 속성을 사용하는 것이 좋다
🎨 리플로우(Reflow)를 발생시키는 속성
positionwidthheighttopbottomleftrightmarginpaddingborderborder-widthcleardisplayfloatoverflowfont-familyfontsizefont-weightline-heightmin-heighttext-alignvertical-align
🎨 리페인트(Repaint)를 발생시키는 속성
backgroundbackground-imagebackground-positionbackground-repeatbackground-sizeborder-radiusborder-stylebox-shadowcoloroutline-colorline-styleoutlinecleardisplayfloatvisibilityfont-familyfontsizefont-weight
💡
opacity속성은 리페인트가 일어나지 않는다. 따라서,visibilty와display속성을 사용하는 것 보다 성능 개선에 도움이 된다.
2. 주변 노드에 영향을 주는 노드를 줄인다.
position: absolute/fixed
- JavaScript와 CSS를 조합한 애니메이션이 많거나, 레이아웃 변화가 많은 요소인 경우
position속성을absolute또는fixed로 사용하면 해당 요소 주변에 영향을 주는 노드를 감소시킬 수 있다. fixed는 주변에 영향을 받는 노드가 전혀 없는 경우,리플로우(Reflow)과정이 필요 없어리페인트(Repaint)연산 비용만 들일 수 있다.