브라우저 렌더링의 Reflow와 Repaint, 그리고 렌더링 최적화
렌더링 최적화 Reflow, Repaint 줄이기
브라우저 렌더링에서 웹 성능 최적화를 어떻게 할 수 있을까요?
이를 알려면 Reflow와 Repaint에 대해 먼저 짚고 넘어가야 합니다.
Reflow (Layout)
렌더링 과정을 거친 뒤에 최종적으로 페이지가 그려진다고 해서 렌더링 과정이 다 끝난것이 아닙니다. 어떠한 액션이나 이벤트에 따라 html 요소의 크기나 위치등 레이아웃 수치를 수정하면 그에 영향을 받는 자식 노드나 부모 노드들을 포함하여 Layout 과정을 다시 수행하게 됩니다. 이렇게 되면 Render Tree와 각 요소들의 크기와 위치를 다시 계산하게 됩니다. 이러한 과정을 Reflow라고 합니다.
// reflow 발생 예제
function reflow() {
document.getElementById('content').style.width = '600px';
}
Reflow가 일어나는 대표적인 경우는 아래와 같습니다.
- 페이지 초기 렌더링 시(최초 Layout 과정)
- 윈도우 리사이징 시 (Viewport 크기 변경시)
- 노드 추가 또는 제거
- 요소의 위치, 크기 변경 (left, top, margin, padding, border, width, height, 등..)
- 폰트 변경 과(텍스트 내용) 이미지 크기 변경(크기가 다른 이미지로 변경 시)
Repaint (Paint)
Reflow만 수행되면 실제 화면에 반영되지 않습니다. 렌더링 과정과 같이 Render Tree를 다시 화면에 그려주는 과정이 필요합니다. 결국은 Paint 단계가 다시 수행되는 것이며 이를 Repaint 라고 합니다.
하지만 무조건 Reflow가 일어나야 Repaint가 일어나는것은 아닙니다. background-color, visibility와 같이 레이아웃에는 영향을 주지 않는 스타일 속성이 변경되었을 때는 Reflow를 수행할 필요가 없기 때문에 Repaint만 수행하게 됩니다.
Reflow, Repaint 과정과 성능 개선 전략 - 출처 : http://bit.ly/2SQXLzY
Reflow, Repaint 줄이기
이번 포스팅에서 다룰 성능 최적화는 단순히 Reflow, Repaint 연산을 줄이는 방법에 대해 소개하고자 합니다. 아래 내용은 현재까지 조사된 부분만 소개하였습니다. 또한 실제 테스트해본 것이 아닌 이론적인 내용 및 발췌해 온 내용이므로 검증이 필요합니다. 하위 내용은 지속적으로 업데이트 하겠습니다.
1. 사용하지 않는 노드에는 visibilty: invisible 보다 display: none을 사용하기
visibility invisible은 레이아웃 공간을 차지하기 때문에 reflow의 대상이 됩니다. 하지만 display none은 Layout 공간을 차지하지 않아 Render Tree에서 아예 제외됩니다.
2. Reflow, Repaint 가 발생하는 속성 사용 피하기
아래는 각각 Reflow, Repaint가 일어나는 CSS 속성들 입니다. Reflow가 일어나면 Repaint는 필연적으로 일어나야 하기 때문에 가능하다면 Reflow가 발생하는 속성보다 Repaint 만 발생하는 속성을 사용하는것이 좋습니다.
Reflow가 일어나는 대표적인 속성
position | width | height | left | top |
right | bottom | margin | padding | border |
border-width | clear | display | float | font-family |
font-size | font-weight | line-height | min-height | overflow |
text-align | vertical-align | white-space | .... |
Repaint가 일어나는 대표적인 속성
background | background-image | background-position | background-repeat | background-size |
border-radius | border-style | box-shadow | color | line-style |
outline | outline-color | outline-style | outline-width | text-decoration |
visibility | .... |
또한 Reflow Repaint가 일어나지 않는 transform, opacitiy와 같은 속성도 있습니다. 따라서 left, right, width, height 보다 transform을, visibility/display 보다 opacitiy를 사용하는 것이 성능 개선에 도움이 됩니다.
(Repaint가 일어나지 않는 원리에 대해서는 차후 포스팅에서 다루도록 하겠습니다)
3. 영향을 주는 노드 줄이기
Javascript + Css를 조합하여 애니메이션이 많거나 레이아웃 변화가 많은 요소의 경우 position을 absolute 또는 fixed를 사용하여 영향을 받는 주변 노드들을 줄일 수 있습니다. fixed와 같이 영향을 받는 노드가 전혀 없는 경우 reflow과정이 전혀 필요가 없어지기 때문에 Repaint 연산비용만 들게 됩니다.
또다른 방법은 애니메이션 시작시 요소를 absolute, fixed로 변경 후 애니메이션이 종료되었을 때 원상복구 하는 방법도 Reflow, Repaint 연산을 줄이는대에 도움이 됩니다.
4. 프레임 줄이기
단순히 생각하면 0.1초에 1px씩 이동하는 요소보다 3px씩 이동하는 요소가 Reflow, Repaint 연산비용이 3배가 줄어든다고 볼 수 있습니다. 따라서 부드러운 효과를 조금 줄여 성능을 개선할 수 있습니다.