프린세스 다이어리

브라우저 렌더링 엔진의 역할과, 렌더링 트리를 만들어서 그리는 과정 본문

FE

브라우저 렌더링 엔진의 역할과, 렌더링 트리를 만들어서 그리는 과정

개발공주 2021. 10. 11. 12:00
728x90

 

렌더링 엔진은 브라우저 엔진으로부터 사용자가 입력한 URI를 받아서, 해당하는 데이터를 렌더링 하는 역할을 한다. 브라우저마다 렌더링 엔진의 상세한 동작 과정이나 용어는 조금씩 차이가 있지만, 전반적인 원리는 기본적으로 동일하다. 크롬과 iOS의 경우, webkit이라는 렌더링 엔진을 사용한다. 렌더링 하는 과정은 다음과 같다.

 

객체 모델 생성 -> 렌더링 트리 구축 -> 렌더링 트리는 배치 -> 렌더링 트리 페인팅

 

1. 객체 모델(Object Model) 생성

 

브라우저가 페이지를 렌더링하려면, 먼저 HTML 문서를 파싱 하여 DOM트리를 생성하고, CSS 문서를 파싱 하여 CSSOM 트리를 생성해야 한다. DOM과 CSSOM은 서로 독립적인 데이터 객체이며, 나중에 이 두 가지가 병합하여 렌더링 된다.

 

(1) DOM 객체를 구성하는 과정

 

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="style.css" rel="stylesheet">
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
  </body>
</html>

DOM 객체를 구성하는 과정

 

- 변환: 만약 위와 같은 단순한 HTML 코드가 있다고 가정한다면, 렌더링 엔진은 HTML의 원시 바이트를 디스크나 네트워크에서 읽어와서, 해당 파일에 대해 지정된 인코딩(UTF-8 등)에 따라 개별 문자로 변환한다.

- 토큰화: 개별 문자로 변환된 것을 HTML5 표준으로 지정된 고유 토큰으로 변환한다. 각 토큰은 고유한 의미와 규칙을 가진다.

- 변환: 각 토큰은 해당 속성 및 규칙을 정의하는 객체로 변환된다.

- DOM 생성: 마지막으로 HTML 마크업이 여러 태그 간의 관계를 정의하기 때문에, 생성된 객체는 트리 데이터 구조 내에 연결된다. 이 트리 데이터 구조에는 마크업에 정의된 상위-하위 관계를 포함한다. 예를 들어 HTML 객체는 body 객체의 상위라는 관계다.

 

이렇게 구성된 DOM 트리는 HTML 문서 마크업의 속성과 각 노드의 관계에 대한 정보를 가지고 있지만, 아직 이 요소들이 렌더링 될 때 어떻게 표시할지에 대해서는 알 수가 없다. 이는 CSSOM의 역할이다.

 

(2) CSSOM 객체를 구성하는 과정

 

body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }

CSSOM 객체를 구성하는 과정

 

렌더링 엔진이 HTML DOM을 생성하면서 외부 CSS stylesheet 파일을 참조하는 <head> 섹션에서 링크 태그를 접하면, 이 리소스에 대한 요청을 네트워크 레이어에 즉시 발송하고 요청의 결과로 css파일을 응답받는다. HTML과 마찬가지로 수신된 CSS규칙을 렌더링 엔진이 이해하고 처리할 수 있는 형식으로 변환해야 한다. HTML처럼 CSS도 바이트가 문자로 변환되고 -> 토큰으로 변환 -> 노드로 변환 -> 마지막으로 CSSOM이라는 트리 구조에 링크가 된다.

 

CSSOM이 트리 구조를 가지는 이유는, 최상의 노드에서 하위로 내려갈수록 더욱 구체적인 규칙을 적용하는 방식이기 때문이다. 즉 스타일을 하향식으로 구체화한다. 또 여기서 구성된 CSSOM 트리는 개발자가 스타일시트에서 정의하도록 직접 작성한 스타일만 표시가 된다. 브라우저 자체적으로 내장된 User Agent Stylesheet은 개발자가 정의하지 않은 부분이 있을 때 적용된다.

 

2. Rendering Tree 구축, 배치, 그리기

 

DOM 트리와 CSSOM 트리는 문서의 각기 다른 측면을 나타내는 독립적인 객체다. 즉 하나는 콘텐츠의 구성을 설명하고, 다른 하나는 문서에 적용할 스타일 규칙을 설명한다. 이 두 가지를 결합하여 렌더링 트리를 형성해야 브라우저가 화면에 픽셀을 렌더링 할 수 있다. 

 

(1) 렌더링 트리 구축하기(construction)

 

DOM 객체와 CSSOM 객체의 정보를 합쳐 렌더링 트리를 구축하는 과정

 

- DOM 트리의 루트에서부터 시작하여 페이지를 렌더링 하는 데 필요한 노드만 남긴다. 스크립트 태그나 메타 태그 같은 요소는 렌더링에 반영되지 않으며, 일부는 CSS의 display: none 속성으로 인해 렌더링 트리에서 누락된다. 

- 표시된 각 DOM 노드에 대해 일치하는 CSSOM 규칙을 찾아 적용한다.

- 표시된 노드를 콘텐츠 및 계산된 스타일과 함께 내보낸다. 

 

그렇게 해서 최종적으로 렌더링 트리가 구축된다. 이 렌더링 트리는 화면에 표시되는 모든 노드의 콘텐츠 및 스타일 정보를 포함하는 구조다. 이 단계가 완성되었으므로, 이제 렌더링 트리 배치(레이아웃) 단계로 진행할 수 있다. 

 

(2) 렌더링 트리 배치하기(layout)

 

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Critial Path: Hello world!</title>
  </head>
  <body>
    <div style="width: 50%">
      <div style="width: 50%">Hello world!</div>
    </div>
  </body>
</html>

뷰포트 기준으로 스타일의 절대적 px 값을 계산한다.

 

사용자의 PC 브라우저나 휴대폰 단말기의 뷰포트 내에서 렌더링 트리가 그려질 정확한 위치와 크기를 계산하는 것은 이 배치 단계다. 페이지에서 각 객체의 정확한 크기와 위치를 파악하기 위해, 렌더링 엔진은 다시 렌더링 트리의 루트에서부터 계산에 들어간다.

 

위의 HTML 예시를 보면 두 개의 중첩된 div 엘리먼트가 본문에 있다. 상위 div는 가로길이가 뷰포트의 50%이고, 하위 div는 상위 div의 가로길이의 50%를 차지한다. 이것을 뷰포트의 가로길이를 이용하여 절대적인 픽셀로 변환이 된다. 각 요소의 정확한 위치와 크기를 계산해서 캡처한 것을 '상자 모델'이라고 한다. 레이아웃이 완료되면, 렌더링 엔진은 Paint Setup 및 Paint 이벤트를 발생시킨다. 

 

(3) 렌더링 트리 그리기(paint)

 

앞서 렌더링 트리를 계산하는 과정에서, 화면에 표시될 노드와 해당 노드의 계산된 픽셀을 파악했으므로, 이제 각 노드를 화면의 실제 픽셀로 변환하는 마지막 단계로 넘어갈 수 있다. 이 과정에서 스타일이 복잡할수록 페인팅에 걸리는 시간이 늘어난다. 단색은 페인트 하는 데 시간과 작업이 적게 필요한 반면, 그림자 효과나 그라데이션 효과는 계산하고 렌더링 하는 데 리소스가 더 소요된다. 

 


 

객체 모델을 생성하는 1번과, 렌더링 트리를 생성하고 계산하고 그리는 2번은 병렬적으로 진행한다는 특성이 있다. DOM 트리는 노드라는 자식 요소를 갖는 방식으로 구성되어 있고, 렌더링 트리도 렌더 오브젝트라는 자식 요소로 구성되어 있다. DOM 트리가 다 그려진 다음에 렌더 트리가 그려지는 게 아니라, 각각의 노드가 생성이 되자마자 바로 렌더링 트리의 노드로 바로바로 전환이 된다. 그러면 사용자에게는 돔트리가 완전히 완성될 때까지 기다리는 게 아니라, 돔트리가 생성되는 구성 요소들이 바로 렌더링 트리의 요소가 되기 때문에 브라우저가 조금씩 그려지는 것을 확인할 수 있다. 옛날에는 브라우저로 웹사이트를 들어가면 위에서 아래로 순차적으로 그려졌던 것이 그 이유에 해당한다.

 

728x90
Comments