Reflow and repaint 성능 비용

Preview:

Citation preview

웹 프론트엔드 개발에 숨겨진 성능 비용

- Reflow & Repaint

발표자. 엄 두성

브라우저 렌더링 프로세스의 이해

• Rendering Engine Basic Flow :

브라우저가네트워크계층에서 요청된데이터를 받아오면

렌더링 엔진이 움직이기시작한다.

HTML Code

DOM Tree

documentElement(html)

head body

meta title style p div

CSS Code

Styles Structure

StylingInformation

cascades

Parse Parse

: 랜더링엔진에서코드를파싱하여 DOM Tree를생성

Render Tree

root(render view)

body

DOM TreeStyles

Structure

p

: DOM을화면에그리기위한정보들을 Rendering Tree로생성

Render Tree

root(render view)

body

p

: 생성된 Rendering Tree로 Element의위치나크기정보를생성

http://www.youtube.com/watch?v=nJtBUHyNBxs

http://www.youtube.com/watch?v=AKZ2fj8155I

: 생성된정보를바탕으로실제화면을그린다.

브라우저 렌더링 프로세스의 이해

Reflow Repaint

그렇다면..

화면구성이완료된 후 동적인 변화발생시엔?

• 특정엘리먼트의 Color 값에변화 발생

→ 해당엘리먼트의 Repaint 발생

• 엘리먼트의포지션에변화가발생

→ 해당엘리먼트의 Repaint + 레이아웃의 Reflow 발생

즉, 엘리먼트의폰트 사이즈를키우는단순한작업만추가 되더라도

전체 Render Tree의 Repaint와 Reflow를 유발

Reflow? Repaint?

• Repaint (or Redraw) :

1. 엘리먼트의 스킨에 변화가 발생하지만,

레이아웃에는 영향을 미치지 않을 때 유발

• Reflow :

1. 문서 내 노드들의레이아웃, 포지션을 재계산 후 다시 뿌림

2. Repaint 보다도 더 심각한 퍼포먼스 저하를 유발시키는 프로세스

무엇이 Reflow를 유발시키는가?

- 브라우저창 크기 수정

- DOM 트리 수정

- Style sheet 추가

- Style Property 수정

- 편집 ( 입력, ContentEditable )

- 등등..

Reflow 발생 example

Reflow 발생 그래프 :

단계별설명1.Click 이벤트2.Recalculate ( 변경된스타일수치 계산수행)3.Layout (Reflow 과정 수행)4.Paint (Repaint 과정 수행)

function reflow() {document.getElementById(‘container’).style.width=600px;

}

Reflow를 피하거나 그 영향을 최소화하는 방법

1. 애니메이션이들어간 노드는 position:fixed 또는

position:absolute로지정하여전체 노드에서분리

2. cssText 를 활용해 Reflow or Repaint 최소화

3. DOM 사용을 최소화하여 Reflow 비용 줄이기

4. 등등..

특정 노드의 Position 속성 변경 (1)

- position 속성을 "fixed" 또는 "absoute"로 값을 주면

해당 노드는 전체 노드에서 분리 됨.

즉, 전체 노드에걸쳐 Reflow 비용이들지 않으며,

해당 노드의 Repaint 비용만 들어가게됨.

특정 노드의 Position 속성 변경 (1)

테스트 코드:

<div id="container_animation“

style="background:blue;

position:absolute;

top:0px;left:0px;width:100px;height:100px;

border:red 1px solid;">

</div>

function animation() {document.getElementById('container_animation').style.left = '100px';document.getElementById('container_animation').style.top = '100px';return false;

}

특정 노드의 Position 속성 변경 (2)

테스트 결과:

cssText 를 활용해 Reflow 최소화 (1)

- DOM과 스타일 변경을하나로 묶어 Reflow 수행을

최소화 한다.

cssText 를 활용해 Reflow 최소화 (2)

case 1 : (Bad Case) 해당노드의 style 객체를여러번호출해적용

function collect() {var elem = document.getElementById('container');

elem.style.backgroundColor = 'red';elem.style.width = '200px';elem.style.height = '200px';

return false;}

cssText 를 활용해 Reflow 최소화 (3)

case 2 : style 객체 속성인 cssText를통해한번에적용.

function collect() {var elem = document.getElementById('container');

elem.style.cssText = 'background:red;width:200px;height:200px;';

return false;}

cssText 를 활용해 Reflow 최소화 (4)

테스트결과 :

상황별 Reflow 비용에드는시간.

Case 1 : 112ms

Case 2 : 104ms

DOM 사용을 최소화하여 Reflow 비용 줄이기(1)

- 노드 조각(document.createDocumentFragment),

노드 사본(elem.cloneNode) 을 활용하여 DOM 접근을

최소화 하여 비용을줄일 수 있다.

DOM 사용을 최소화하여 Reflow 비용 줄이기(2)

Case 1 : (Bad Case)

function notReflow() {

var elem = document.getElementById('container');

for (var i = 0; i < 10; i++) {var a = document.createElement('a');a.href = '#';a.appendChild(document.createTextNode('test' + i));elem.appendChild(a);

}

return false;}

DOM 사용을 최소화하여 Reflow 비용 줄이기(3)

Case 2 : 노드 조각을 활용한 엘리먼트 추가 방법

function notReflow() {

var frag = document.createDocumentFragment();

for (var i = 0; i < 10; i++) {var a = document.createElement('a');a.href = '#';a.appendChild(document.createTextNode('test' + i));frag.appendChild(a);

}

document.getElementById('container').appendChild(frag);

return false;}

DOM 사용을 최소화하여 Reflow 비용 줄이기(4)

Case 3 : 노드 사본을 활용한 엘리먼트 추가 방법

function notReflow() {

var elem = document.getElementById('container');var clone = elem.cloneNode(true);

for (var i = 0; i < 10; i++) {var a = document.createElement('a');a.href = '#';a.appendChild(document.createTextNode('test' + i));clone.appendChild(a);

}

elem.appendChild(clone);

return false;}

DOM 사용을 최소화하여 Reflow 비용 줄이기(5)

상황별 테스트 결과:

Case 1 : 153ms

Case 2 : 136ms

Case 3 : 129ms

Thank you

Recommended