WEB

Reflow, Repaint 와 7가지 렌더링 최적화방법

ㅇㄱ9 2022. 4. 25. 14:00
728x90

브라우저 렌더링 과정을 알아보았으니 최적화시키는 방법을 알아보자. 

 

[출처]https://dev.to/gopal1996/understanding-reflow-and-repaint-in-the-browser-1jbg

위와 같은 렌더링 과정에서 Reflow와 Repaint는 둘다 비용이 많이 드는 작업이다.

먼저 이 두 과정에 대해 알아보자. 

 

Reflow(Layout)이란?

화면구조(Layout)이 변경되었을 때 뷰 포트 내에서 렌더 트리상 노드의 정확한 위치과 크기를 계산하는 과정이다. element의 reflow는 DOM에 있는 모든 하위, 상위 요소의 후속 리플로우를 유발한다. 

 

- 모든 엘리먼트의 위치나 길이, 크기 등등을 다시 계산하는 과정

- 상위 엘리먼트를 변경시키면 하위 엘리먼트에도 영향을 끼침

- render tree를 재생성하므로 부하가 크고 레이아웃에 영향을 줌

- DOM노드를 추가, 제거 , 업데이트하는 경우 발생 

Repaint(Redraw)란?

화면에 가시성이 변하지만 레이아웃에 영향을 미치지 않는 요소의 외관을 변경할 때 발생한다. 

 

- 레이아웃에 영향을 주지않지만 눈에 보이는 요소들(background-color, color, visibility,..)이 변경됨

- reflow 보다는 부하가 크지는 않음

 

[출처]https://dev.to/gopal1996/understanding-reflow-and-repaint-in-the-browser-1jbg

Reflow와 Repaint가 모두 일어나는 경우 

- DOM 노드를 추가, 제거 업데이트하는 경우 

- DOM 요소의 위치 변경, 크기 변경 (margin, padding, border, width, height, 등..) 

- display : none으로 DOM 요소를 숨기는 경우

- DOM 노드를 이동하거나 애니메이션을 생성하는 경우

- 창 크기를 조정하는 경우 (Resizing)- 글꼴 스타일을 변경하는 경우 (요소의 geometry가 변경되고 이는 페이지에 있는 다른 요소의 위치나 크기에 영향을 미칠 수 있고 두 요소 모두 브라우저에서 reflow를 수행하고 repaint 과정을 거침)- 스타일 시트를 추가하거나 제거하는 경우- DOM을 조작하는 스크립트를 수정하는 경우

- offset, scrollTop, scrollLeft와 같은 계산된 스타일 정보 요청

- 이미지  크기 변경

Repaint만 일어나는 경우 

- visibility :  hidden 으로 DOM 요소를 숨기는 경우 (레이아웃이나 위치 변경이 없어 repaint만 발생)

- background-color, visibillty, outline 등의 스타일 변경

 

Reapint와 Reflow 최소화하는 방법

1) 개별 스타일을 바꾸기보다 클래스 이름을 변경. 동적인 스타일인 경우 cssText속성을 편집한다.

[출처]https://webclub.tistory.com/346

2) DOM 변경사항을 일괄처리

  - documentFragment를 사용하여 DOM사용을 최소화한다. ( documentFragment는 DOM에 적용되기 전까지는 메모리상에만 존재)

[출처]https://beomy.github.io/tech/browser/reflow-repaint/

  - display :none으로 요소를 숨기고 (1 reflow, 1 repaint) 변경사항 100개를 추가한 후 display를 복원한다. ( 총 2 reflow, 2 repaint)

3) 계산된 스타일을 반복적으로 묻지 않고 변수에 캐싱

:offset, scrollTop과 같은 계산된 스타일 정보를 요청할 때마다 정확한 정보를 제공하기 위해 큐를 비우고 모든 변경사항을 적용하기 때문에 스타일 정보를 변수에 저장하여 사용을 권장

[출처]https://beomy.github.io/tech/browser/reflow-repaint/

4) 영향받는 엘리먼트 제한하기 ( position fixed, absolute를 활용)

 

5) <table> 레이아웃을 피한다.

:<table>은 점진적으로 렌더링 되지 않고 모두 로드되고 테이블 너비가 계산된 후 화면에 그려진다. 콘텐츠의 값에 따라 테이블 너비가 계산되기 때문에, 테이블 콘텐츠의 작은 변경만 있어도 테이블 너비가 다시 계산되고 테이블의 모든 노드들이 Reflow가 발생. 데이터 표시용 도로 사용 시 table-layout:fixed를 사용하자.

 

6) IE의 CSS표현식을 사용하지 않는다.

: Reflow가 발생할 때마다 자바스크립트 표현식이 다시 계산되기 때문이다.

[출처]https://beomy.github.io/tech/browser/reflow-repaint/

6) 되도록 실행 사이클 안에서 실행하도록 처리

타이머에서 실행되게 하면 추가적인 실행 사이클이 발생하게 되는데, 첫 번째 요소에 대한 작업이 한 사이클 내에서 실행되고, 타이머의 실행은 먼저 실행된 사이클이 끝난 다음에 진행된다. 이로 인해 결과적으로 리플로와 리페인트가 두 번 일어나게 되므로 리플로우와 리페인트가 일어날 수 있는 작업은 가능하면 실행 사이클 안에서 실행하도록 처리하는 편이 효과적이다.

 

7) 노드복제 

: 변경하려는 요소의 노드를 복제한 후 복제된 노드에 필요한 작업을 실행하는 방법. 복제된 노드는 DOM 트리에 추가된 상태가 아니므로 렌더링 성능에 영향을 줄 수 있는 작업을 실행하더라도 리플로나 리페인트가 발생하지 않는다.

작업이 모두 완료된 이후 복제된 노드를 원래 노드와 치환해 DOM 트리에 변경된 사항이 적용되게하면 치환 시점에만 리플로와 리페인트가 발생한다.

var element = document.getElementById("box1");
var clone = element.cloneNode(true);     // 원본 노드를 복제한다.

for(var i=0; i < 100; i++) {
    clone.style.width = i + "px";
}

// 변경된 복제 노드를 DOM 트리에 반영하기 위해 기존 노드와 치환한다.
parentNode.replaceChild(clone, element);

Chorme Tool을 통한 성능 확인

-Bad Code

- Optimized Code

----

참고사이트

- <Reflow or Repaint(or ReDraw) 과정 설명 및 최적화 방법>

- <[Browser] Critical Rendering Path 최적화>

- <[Browser] Reflow와 Repaint>

- <브라우저 렌더링에 대한 이해와 최적화>

- <FrontEnd-성능 최적화-기본>

- <Understanding Reflow and Repaint in the browser>

- <[자바스크립트] 브라우저 렌더링>

 

 

728x90
반응형