렌더링 최적화(Reflow, Repaint)

Daehyeon Yun·2024년 8월 2일

프론트엔드

목록 보기
5/14

📖 Reference
📎https://boxfoxs.tistory.com/408
📎https://velog.io/@bumsu0211/브라우저-렌더링-과정과-최적화


🎨 렌더링 최적화?

우선, 렌더링 엔진 동작 과정을 살펴보자.

만약, 사용자가 브라우저를 통해 웹 사이트에 접속하면 브라우저는 서버로부터 HTML, CSS, JavaScript 등 웹 사이트에 필요한 리소스를 다운받는다.

필요한 리소스를 전달받은 렌더링 엔진 은 다음과 같이 진행된다.

  1. 렌더링 엔진은 전달받은 HTML 문서파싱(Parsing) 하여 문서 객체 모델(DOM) 트리를 만든다.

  2. DOM 트리 를 만든 뒤 렌더링 엔진은 CSS 파일 을 파싱하여 CSS 객체 모델(CCSOM) 트리 를 만든다.

  3. 렌더링 엔진은 제작한 DOM 트리CSSOM 트리 를 결합하여 Render 트리 를 만든다.

    Render Tree 는 DOM 트리와 CSSOM 트리를 이용해 생성하는 렌더링을 목적으로 한 트리이며, 렌더링은 브라우저가 사용자에게 보여줄 화면을 그리는 과정이다.

    • 이때, 화면에 보이지 않는 요소드는 Render Tree 에서 제외된다.
      • ex) <head> <link> <meta> display: none 등등..
  4. 레이아웃(Layout) 과정을 통해 각 요소를 어디에 배치할지 결정한다.

    레이아웃(Layout) 과정은 Render Tree 를 기반으로 HTML 요소의 위치, 크기를 계산하여 브라우저 화면 중 어디에 배치할 것인지 결정하는 과정이다.

  5. 레이아웃(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)를 발생시키는 속성

  • position
  • width height
  • top bottom left right
  • margin padding border border-width
  • clear display float overflow
  • font-family fontsize font-weight
  • line-height min-height
  • text-align vertical-align

🎨 리페인트(Repaint)를 발생시키는 속성

  • background background-image background-position background-repeat background-size
  • border-radius border-style box-shadow
  • color outline-color
  • line-style outline
  • clear display float visibility
  • font-family fontsize font-weight

💡 opacity 속성은 리페인트가 일어나지 않는다. 따라서, visibiltydisplay 속성을 사용하는 것 보다 성능 개선에 도움이 된다.

2. 주변 노드에 영향을 주는 노드를 줄인다.

position: absolute/fixed

  • JavaScript와 CSS를 조합한 애니메이션이 많거나, 레이아웃 변화가 많은 요소인 경우 position 속성을 absolute 또는 fixed 로 사용하면 해당 요소 주변에 영향을 주는 노드를 감소시킬 수 있다.
  • fixed주변에 영향을 받는 노드가 전혀 없는 경우, 리플로우(Reflow) 과정이 필요 없어 리페인트(Repaint) 연산 비용만 들일 수 있다.

profile
열심히 살아야지

0개의 댓글