브라우저가 작동될때에는 렌더링 과정에서 Repaint, Reflow의 과정을 거치게 된다. 말 그대로 해당 element를 다시 칠하고 다시 flow(?) 하는것이다. react를 이용하는 입장에서 렌더링 최적화를 수행할때 반드시 고려해야하는 항목이기도 하다. 이 포스팅에서는 애매하게 알고있는 두가지의 개념을 정확히 짚고 넘어가도록 하겠다.
The rendering process of a web page
그에 앞서 브라우저가 요소를 렌더링할때 어떤 과정을 거치게 되는지 알아보자.
간단히 요약하면,
HTML을parsing해서DOM Tree를 만들고,CSS를parsing해서 스타일 구조체를 만들어내는데 이를CSSOM Tree라고 한다DOM Tree와CSSOM Tree이 둘을 이용하여Render Tree를 생성한다 (실제 화면에 표현되는Node들로 구성)viewport내에서 각node들의 정확하 위치와 크기를 계산한다 (Layout)layout계산이 완료되면 이제 요소들을 화면에 그린다 (Paint)
Reflow(Layout change)
위에서 짚어보았던 렌더링 과정을 거친 뒤에 최종적으로 web page가 그려진다. 하지만 이것은 끝난것이 아니다. 이후 어떠한 이벤트에 따라 element의 크기, 위치 등 layout을 변경하면 그 영향을 받는 child node, parent node들을 포함하여 다시 layout과정을 수행한다. 이때 render tree와 각 element의 크기와 위치를 다시 연산하게 되는데 이를 Reflow라고 한다.
Reflow의 경우 다음의 대표적인 경우에 발생한다
node의 추가 또는 제거element의 위치, 크기(margin,padding,width,height...)변경font변경,image크기 변경page initial renderingwindow resizingJS를 이용한DOM의 동적 변화
Repaint(Redraw)
reflow처럼 style을 변경하는 모든것이 layout 수치에 영향을 받지는 않는다. background-color, visibility, outline 등의 style 변경시에는 layout은 변하지 않고 reflow가 생략된 repaint 과정만 발생한다.
reflow와 repaint를 완전히 피할수는 없다. repaint의 경우 dom api를 통해 visibility를 변경하였을때, child node들까지 다 검색하기 때문에 성능이 저하될 수 있다. reflow의 경우 해당 요소의 child, parent 모두 layout을 새로 연산하기 때문에 더 심각한 성능저하를 일으키기도 한다.
Reflow를 피하거나 그 영향을 줄일 수 있는 몇가지 방법은 다음과 같다.
inline style을 최대한 없앤다inline상에style이 주어진 경우, 페이지 전체에 걸쳐서reflow가 수차례 발생하게 된다. 만일 없을경우에는 외부스타일 class 조합으로 한번만 reflow를 발생시킨다animation이 들어간element의 경우position: fix;또는position: absolute;로 지정한다.animation의 경우 초단위로 상당한reflow를 불러일으킨다. 이 경우에 위 두가지 속성을 사용하여 다른 요소들에 영향을 끼치지 않도록 하면, 해당 요소만의 repaint만을 유발하므로 효율적이다JS를 통해style변화를 줄 경우 가급적 한번에 처리한다
// (X)
var newElement = document.getElementById('elem');
newElement.style.background = 'blue';
newElement.style.color = '#fff';
newElement.style.border = '1px solid #ccc';
// 아래처럼 바꾼다
// (O)
/* CSS */
// #elem1 { border:1px solid #000; color:#000; background:#ddd; }
// .coloring { border-color:#00f; color:#fff; background:blue; }
/* js */
document.getElementById('elem1').className = 'coloring';table레이아웃을 줄인다table로 구성된 요소의 경우 점진적 페이지 렌더링이 적용되지 않으며, 모두 load 되고연산된후에 화면에 보여진다. 또한 아주 작은 변화마저도table전체 모든node에 대한reflow를 유발한다고 한다
reflow와 repaint를 고려해서 개발을 진행하는 것도 중요하지만, 너무 성능/효율성에 치우칠 경우 퀄리티에 문제가 생길 수 있다. 적절히 trade-off를 생각하면서 개발을 진행하면 보기에도 훌륭하고 성능적으로도 우수한 멋진 웹페이지가 탄생할 것이다.
- https://medium.com/@gneutzling/the-rendering-process-of-a-web-page-78e05a6749dc