ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JS ] 브라우저의 렌더링 과정
    Javascript 2022. 1. 13. 13:06

    출처 :https://developers.google.com/web/fundamentals/performance/critical-rendering-path

     

     


    아래의 내용은 '모던 자바스크립트 Deep Dive - 38장 브라우저의 렌더링 과정' 부분을 제가 공부한 것과 함께 정리한 내용입니다. 제가 기억하기 위해 정리한 것이라 자세한 내용을 알고 싶으신 분은 책에 자세히 정리되어 있으니
    읽어보시길 추천합니다. 그림은 구글의 'Order Loading Thoughtfully'을 참고하였습니다.
     

     

     

    요청과 응답


    브라우저의 핵심 기능은 필요한 리소스(HTML, CSS, 자바스크립트, 이미지, 폰트 등의 정적 파일 또는 서버가 동적으로 생성한 데이터)를 서버에 요청하고 서버로부터 응답받아 브라우저에 시각적으로 렌더링하는 것이다.

    즉, 렌더링이 필요한 리소스는 모두 서버에 존재하므로 필요한 리소스를 서버에 요청하고 서버가 응답한 리소스를 파싱하여 렌더링 하는 것이다.

     

     

    HTTP 1.1과 HTTP 2.0


    HTTP는 1991년 최초로 문서화되었고 HTTP/1.0 (1991년), HTTP/1.1 (1999년), HTTP/2.0 (2015년)에 발표되었다. 

    이 중 HTTP/1.1과 HTTP/2.0의 차이점을 간략히 살펴보면 HTTP/1.1은 기본적으로 커넥션당 하나의 요청과 응답만 처리한다. HTTP/1.1은 리소스의 동시 전송이 불가능한 구조이므로 요청할 리소스 개수에 비례하여 응답시간도 증가하는 단점이 있다.

    HTTP/2.0은 커넥션당 여러 개의 요청과 응답, 즉 다중 요청/응답이 가능합니다. 따라서 HTTP/1.1보다 페이지 로드 속도가 50% 정도 빠르다고 알려져 있습니다. 

     

     

    HTML 파싱과 DOM 생성


    브라우저의 요청에 의해 서버가 응답한  HTML 문서는 문자열로 이루어진 순수한 텍스트이다.

    다음과 같은 index.html이 서버로부터 응답되었다고 가정해보자.

     <!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>

     

    브라우저 렌더링 엔진은 다음 그림과 같은 과정을 통해 응답받은 HTML 문서를 파싱하여 브라우저가 이해 할 수 있는 구조인 DOM(Document Object Model)을 생성한다.

    출처:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model

     

    1. 서버에 존재하던 HTML 파일이 브라우저의 요청에 의해 응답된다. 이때 서버는 브라우저가 요청한 HTML 파일을 읽어 들여 메모리에 저장한 다음 메모리에 저장된 바이트(2진수)를 인터넷을 경유하여 응답한다.

    2. 브라우저는 서버가 응답한 HTML 문서를 바이트 형태로 응답받는다. 브라우저는 이를 확인하고 문자열로 변환한다.
    참고 : HTML meta 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식(예: UTF-8)은 응답헤더에 담겨 응답된다. 

    3. 문자열로 변환된 HTML 문서를 읽어들여 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해한다.

    4. 각 토큰들을 객체로 변홤하여 노드들을 생성한다. 토큰 내용에 따라 문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드가 생성된다. 노드는 이후 DOM을 구성하는 기본 요소가 된다.

    5. HTML 문서는 HTML 요소들의 집합으로 이루어지며 HTML 요소는 중첩 관계를 갖는다. 이 중첩관계로 부자관계가 형성되며 이를 반영하여 모든 노드들을 트리 자료구조로 구성한다. 이 노드들로 구성된 트리 자료구조를 DOM(Document Object Model)이라고 부른다.

     

     

    CSS파싱과 CSSOM 생성


    렌더링 엔진은 HTML을 처음부터 한 줄씩 순차적으로 파싱하여 DOM을 생성해 나간다. 생성해 나가다 CSS를 로드하는 link 태그나 style 태그를 만나면 DOM 생성을 일시중단한다.

    그리고 link 태그의 href 어트리뷰트에 지정된 CSS파일을 서버에 요청하여 로드한 CSS파일이나 style 태그 내의 CSS를 HTML과 동일한 파싱 과정(바이트 -> 문자 -> 토큰 -> 노드 -> CSSOM)을 거치며 해석하여 CSSOM(CSS Object Dom)을 생성한다. 이후 CSS파싱을 완료하면 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱하기 시작하여 DOM 생성을 재개한다.

     

    위에서 살펴본 index.html에는 CSS파일을 로드하는 link 태그가 있습니다.

    렌더링 엔진은 meta 태그까지 HTML을 순차적으로 해석한 다음, link 태그를 만나면 DOM 생성을 일시 중단하고 link 태그의 href 어트리뷰트에 지정된 CSS파일을 서버에 요청합니다.

    <!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>
    /* style.css */
    
    body { font-size: 16px }
    p { font-weight: bold }
    span { color: red }
    p span { display: none }
    img { float: right }

     

    HTML과 동일한 파싱과정을 거치고 CSSOM을 생성합니다.

     

    CSSOM은 아래와 같이 CSS의 상속을 반영하여 생성됩니다. 

     

     

     

    렌더 트리 생성


    렌더링 엔진은 DOM과 CSSOM을 생성한 후, 이 둘을 렌더 트리(render tree)로 결합합니다. 

    렌더트리는 렌더링을 위한 트리 구조의 자료구조입니다. 따라서 브라우저 화면에 렌더링되지 않는 노드와 CSS에 의해 비표시되는 노드들은 포함되지 않습니다. 

     

    출처 :https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction

     

    이후 완성된 렌더트리는 각 HTML 요소의 레이아웃(위치와 크기)을 계산하는데 사용되며 브라우저 화면에 픽셀을 렌더링하는 페인팅 처리에 입렵됩니다.

    <!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>

    출처 :https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction

    레이아웃 프로세스에서는 뷰포트 내에서 각 요소의 정확한 위치와 크기를 정확하게 캡처하는 상자 모델이 출력됩니다. 모든 상대적인 측정값은 화면에서 절대적인 픽셀로 변환됩니다. 

    layout 이벤트 타임라인

    Layout 이벤트 타임라인에서 렌더링 트리 생성, 위치 및 크기 계산을 캡쳐합니다.
    레이아웃이 완료될 때 브라우저가 Paint Setup 및 Paint 이벤트를 발생시킵니다. 이러한 작업은 렌더링 트리를 화면의 픽셀로 변환합니다. 

     

     

    뷰포트에 표시


    출처:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction

     

    이제 페이지가 뷰포트에 표시됩니다.

    브라우저 단계를 간단히 요약해 보면 다음과 같습니다.

    1. HTML 마크업을 처리하고 DOM 트리를 빌드합니다.
    2. CSS 마크업을 처리하고 CSSOM 트리를 빌드합니다.
    3. DOM 및 CSSOM을 결합하여 렌더링 트리를 형성합니다.
    4. 렌더링 트리에서 레이아웃을 실행하여 각 노드의 기하학적 형태를 계산합니다.
    5. 개별 노드를 화면에 페인트합니다.

     

     

    자바스크립트의 파싱과 실행


    CSS 파싱과 마찬가지로 렌더링 엔진은 HTML을 한 줄씩 순차적으로 파싱하며 DOM을 생성해 나가다가 자바스크립트 파일을 로드하는 script 태그나 자바스크립트 코드를 콘텐츠로 담은 script 태그를 만나면 DOM 생성을 일시 중단한다.

    그리고 script 태그의 src 어트리뷰트에 정의된 자바스크립트 파일을 서버에 요청하여 로드한 자바스크립트 파일이나 script 태그 내의 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에 제어권을 넘긴다.

     

    자바스크립트 파싱과 실행이 종료되면 렝더링 엔진으로 다시 제어권을 넘겨 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱을 시작하여 DOM 생성을 재개한다.

     

    자바스크립트 엔진은 자바스크립트를 해석해서 AST(Abstract Syntax Tree)를 생성한다. 이 AST를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트코드를 생성하여 실행합니다.  

    출처 : advanced javascript from udemy
    모던자바스크립트 Deep Dive

     

     

    리플로우와 리페인트


    만약 자바스크립트 코드에 DOM이나 CSSOM을 변경하는 DOM API가 사용된 경우 DOM이나 CSSOM이 변경된다.

    이때 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합되고 변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정을 거쳐 브라우저의 화면에 다시 렌더링 한다. 이를 리블로우, 리페인트라고 한다.

    레이아웃에 영향이 있으면, 레이아웃 계산을 다시 진행하고 리플로우와 리페인트가 일어난다.

    레이아웃에 영향이 없으면 리플로이 없이 리페인트만 실행된다.

     

     

     

    댓글

Designed by Tistory and darae.