브라우저 렌더링 과정 & 렌더링 최적화

지은·2022년 11월 22일
1

Web / Browser

목록 보기
5/7
post-custom-banner

브라우저 렌더링

: HTML, CSS, JavaScript 등 개발자가 작성한 문서를 브라우저가 그래픽 형태로 화면에 출력하는 과정
브라우저마다 가지고 있는 렌더링 엔진이 요청 받은 데이터를 화면에 렌더링하는 역할을 담당한다.

  • 파이어폭스 - Gecko
  • 사파리 - Webkit
  • 크롬, 오페라 - Blink
  • 아웃룩 익스프레스, 마이크로소프트 아웃룩 - Trident

렌더링 엔진 동작 과정

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

  1. 렌더링 엔진은 전달받은 HTML 문서를 파싱문서 객체 모델(DOM) 트리를 만든다.
  2. 그러고나서 CSS 파일을 파싱CSS 객체 모델(CSSOM) 트리를 만든다.
  3. DOM 트리와 CSSOM 트리를 결합해 Render 트리를 만든다.
  4. 레이아웃 과정을 통해 각 요소를 어디에 배치할지 결정한다.
  5. 레이아웃 과정이 끝나면, UI 백엔드에서 Render 트리를 화면에 그린다(paint).

1. 📄 파싱(Parsing)

: 프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(syntax analysis)하는 단계
일종의 인터프리터, 컴파일러 구성요소 중 하나인 파서(parser)가 파싱을 진행한다.

HTML 파싱

  • 파서는 HTML 파일의 코드를 토큰(token)으로 한 번 분해한다.

    토큰(token) : 문법적 의미를 갖는 최소 단위로, 토큰에는 시작 태그마침 태그, 속성 이름 등이 포함된다.

  • 이 토큰들을 문법적 의미와 구조에 따라 노드(node)라는 요소로 바꾼다.
  • 노드들은 상하 관계에 따라 하나의 트리를 형성한다. ➡️ 🌳 DOM 트리

CSS 파싱

브라우저가 HTML 문서를 파싱하다가 CSS 스타일을 만나면, HTML 파싱을 중단하고, CSS 파일을 파싱한다.

  • 파서는 CSS 파일 안의 코드를 CSS 스타일링 레이아웃과 페인팅에 사용하는 데이터 구조인 🌲 CSSOM 트리 로 파싱한다.

2. 🌳 DOM Tree

DOM (Document Object Model)

: HTML 문서의 요소들의 중첩 관계를 기반으로 노드들을 트리 구조로 구성한 것

  • 브라우저는 JavaScript 언어만 알아듣기 때문에 HTML의 태그나 속성을 이해하지 못한다.
  • 따라서 HTML 문서를 브라우저가 이해할 수 있는 형태인 객체로 바꾸어준 것이 바로 DOM 트리다.
<html>
  <head>
    <meta ... />
    <link ... />
  </head>
  <body>
    <p>Hello,
      <span>web performance</span>
      students
    </p>
    <div>
      <img ... />
    </div>
  </body>
</html>


3. 🌲 CSSOM Tree

  • HTML 파일을 파싱하던 브라우저는 <link><style> 태그를 만나면, 잠시 파싱을 멈추고 CSS 파일을 서버로 요청한다. 그러고 CSS 파일을 파싱하여 CSSOM 트리를 만든다.
  • CSSOM 트리를 다 만들고 나면, 브라우저는 다시 HTML 파일로 돌아가 마저 DOM 트리를 구축한다.
body {
  font-size: 16px;
}

p {
  font-weight: bold;
}

p span {
  display: none;
}

span {
  color: red;
}

img {
  float: right;
}

  • CSS는 부모의 속성을 자식이 상속받는다.

4. 🎄 Render Tree

: DOM 트리와 CSSOM 트리를 이용해 생성하는, 렌더링을 목적으로 만들어지는 트리

렌더링은 브라우저가 사용자에게 보여줄 화면을 그리는 과정이므로, 보이지 않는 요소들은 이 트리에서 제외된다.
(<head>, <link>, <meta>, display: none 등)


5. 📏 Layout

: 렌더 트리를 기반으로 HTML 요소의 위치, 크기를 계산하여 브라우저 화면의 어디에 배치할 것인지 결정하는 과정

  • 렌더 트리는 요소의 크기, 위치 등의 정보를 담고 있지만, 텍스트로 구성된 객체에 불과하다.
  • 렌더링 엔진이 렌더 트리를 위에서 아래로 읽어내려가며, 이러한 정보들을 계산하여 각 요소들이 전체 화면에서 어디에, 어떤 크기로, 어떻게 배치되어야 하는지 결정한다.
  • 이때 모든 값은 절대 단위인 px로 변환된다.


6. 🎨 Painting

: 레이아웃에서 계산한 대로 브라우저 화면의 픽셀을 채워나가는 과정

  • 이때 처리해야 할 스타일이 복잡한 경우, 더 많은 시간이 소요된다.

이렇게 페인팅 과정이 끝나면, 텍스트에 불과했던 HTML 파일의 내용들이 이미지화된 모습으로 브라우저 화면에 띄워진다.


렌더링 최적화

위의 렌더링 과정을 거쳐 최종적으로 페이지가 그려진 후,
사용자가 브라우저 화면의 크기를 조절하거나 화면에 요소가 추가/삭제 되는 경우, 화면에 있던 요소들의 크기가 바뀌게 된다.

➡️ 이때 화면에 나타나는 모습이 바뀌기 위해서는, 모든 요소의 위치와 크기를 다시 계산하고 다시 그려 보여주어야 한다.

리플로우(Reflow)

: 웹 인터랙션으로 인해 렌더링 과정의 레이아웃 단계를 반복 수행하는 것

리페인트(Repaint)

: 웹 인터랙션으로 인해 렌더링 과정의 페인트 단계를 반복 수행하는 것

리플로우와 리페인트가 일어나는 예시

const newDiv = document.createElement('div');
document.body.append(newDiv);
div.textContent = "I'm newly added!";

JavaScript를 이용해 DOM을 조작하는 경우, 브라우저는 DOM 트리를 다시 구성하고, CSSOM 트리와 합쳐 새로운 렌더 트리를 구축한다.
그러고나서 레이아웃페인트 과정을 또 다시 거쳐 화면에 보여준다.


리플로우와 리페인트 최적화하는 법

리플로우 과정은 배치를 위한 연산을 해야 해서 CPU를 많이 차지하고,
리페인트 과정은 픽셀을 다시 화면에 찍어 그려야 하기 때문에 GPU를 많이 차지한다.
따라서 리플로우와 리페인트가 많이 발생하면 프레임 드랍(Frame Drop) 현상이 일어날 수 있다.

1. 불필요한 레이아웃을 줄인다.

CSS 속성 중 레이아웃을 발생시키는 속성들이 있다. 이 속성들을 사용하게 되면 매번 렌더 트리를 만들고, 레이아웃이 발생하고, 이어서 페인팅을 발생시킨다.
따라서 레이아웃을 발생시키는 속성을 피하면 위의 과정이 발생하는 횟수를 줄일 수 있다.

레이아웃, 페인트를 발생시키는 CSS 속성

리플로우 시 리페인트는 필연적으로 일어나므로, 가능하다면 리플로우가 발생하는 속성보다는 리페인트만 발생하는 속성을 사용하는 것이 좋다.

리플로우를 발생시키는 속성

  • 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

리페인트를 발생시키는 속성

  • background, background-image, background-pisition, 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 속성은 리페인트가 일어나지 않으므로, visibilty, display 속성을 사용하는 것보다 성능 개선에 도움이 된다.


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

position:absolute/fixed

  • JavaScript와 CSS를 조합한 애니메이션이 많거나, 레이아웃 변화가 많은 요소인 경우,
    position 속성을 absolute 또는 fixed로 사용해주면 영향을 받는 주변 노드를 줄일 수 있다.
  • fixed는 영향을 받는 노드가 전혀 없는 경우, 리플로우 과정이 필요 없기 때문에 리페인트 연산 비용만 들일 수 있다.
profile
블로그 이전 -> https://janechun.tistory.com
post-custom-banner

0개의 댓글