김우석 개발자

How to Rendering

개요 : 웹 렌더링의 과정을 정리한 글

웹 렌더링은 어떠한 과정으로 이루어질까?

CRP


브라우저가 서버에서 페이지에 대한 응답을 받으면 화면에 표시되기 까지 많은 단계를 거친다. 브라우저가 페이지의 초기 출력을 위해 실행해야하는 이 순서를 CRP(Critical Rendering Path)라고 한다. CRP를 최적화 하면 최초 페이지 렌더링에 걸리는 시간이 상당히 단축된다.

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/images/progressive-rendering.png?hl=ko

CRP는 6단계로 구성되어 있다.

  • DOM 트리 구축
  • CSSOM 트리 구축
  • JavaScript 실행
  • 렌더링 트리 구축
  • 레이아웃 생성
  • 페인팅

raw bytes of data


서버에 요청을 보내면 서버는 응답과 함께 데이터를 보내준다. 컴퓨터는 0과 1밖에 이해하지 못하기 때문에 브라우저는 바이트화 된 데이터를 받아온다. 바이트화 된 데이터는 8자리의 2진수이며 이를 2자리의 16진수로 나타낸 것이 밑에 보이는 hex-view이다.

../../../../../public/assets/2021-06-01-Web-CRP/hex_view.jpg

fiddler을 사용하여 구글에 접속할 때 보낸 request와 받은 response를 16진수로 나타낸 것이다.

바이트화 된 데이터를 인코딩하여 브라우저가 사용할 수 있도록 Characters로 변환된다. 인코딩 페이지에서 이어진다.

DOM


Document Object Model은 원본 HTML 문서의 객체 기반 표현 방식이다. 둘은 서로 비슷하지만, DOM이 갖고 있는 근본적인 차이는 단순 텍스트로 구성된 HTML 문서의 내용과 구조가 객체 모델로 변환되어 다양한 프로그램에서 사용된다는 점이다.

<!doctype html>
<html lang="en">
 <head>
   <title>My first web page</title>
  </head>
 <body>
    <h1>Hello, world!</h1>
    <p>How are you?</p>
  </body>
</html>

../../../../../public/assets/2021-06-01-Web-CRP/DOM.jpg

단순한 텍스트였던 HTML 문서는 위와 같은 노드 트리로 표현된다.

DOM tree


  • 브라우저가 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>

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/images/full-process.png?hl=ko

  1. Bytes → Characters 변환
    • 브라우저가 HTML의 원시 바이트를 네트워크에서 읽어와서, 해당 파일에 대해 지정된 인코딩(UTF-8)에 따라 개별 문자로 변환한다.
  2. Characters → Tokens 토큰화
    • 브라우저가 문자열을 W3C HTML5 표준에 지정된 고유 토큰으로 변환한다.
    • 파싱 알고리즘 (블로그 전문 인용) HTML 파서
  3. Tokens → Nodes 렉싱
    • 방출된 토큰은 해당 속성 및 규칙을 정의하는 ‘객체’로 변환된다.
  4. Tokens → DOM 생성
    • HTML 마크업이 여러 태그 간의 관계를 정의하기 때문에 생성된 객체는 트리 데이터 구조 내에 연결된다. 이 트리 데이터 구조에는 원래 마크업에 정의된 상위-하위 관계도 포함된다.

DOM의 특징


DOM이 HTML과 반드시 연결되어 있는 것은 아니다

  1. 작성된 HTML 문서가 유효하지 않을 때
    • 브라우저는 DOM을 생성하는 동안, 유효하지 않은 HTML 코드를 올바르게 교정한다.
      <!doctype html>
     <html>
     Hello, world!
     </html>
    

    ../../../../../public/assets/2021-06-01-Web-CRP/DOM2.jpg

    DOM 트리는 올바르게 교정되어 나타낸다.

  2. 자바스크립에 의해 DOM이 수정될 때
    • DOM은 HTML 문서의 내용을 볼 수 있는 인터페이스 역할을 하는 동시에 동적 자원으로써 변경이 가능하다.
    var newParagraph = document.createElement("p");
    var paragraphContent = document.createTextNode("I'm new!");
    newParagraph.appendChild(paragraphContent);
    document.body.appendChild(newParagraph);
    

우리가 브라우저에서 보는 것은 정확히는 DOM이 아니라 render 트리이다.

render 트리는 DOM 과 CSSOM 을 결합한 것으로, 오직 스크린에 그려지는 것으로 구성되어 있어 DOM과 다르다. 렌더 트리에는 렌더링 되는 요소만을 담기 때문에 시각적으로 보이지 않는 요소는 제외된다.

<!doctype html>
<html lang="en">
  <head></head>
  <body>
    <h1>Hello, world!</h1>
    <p style="display: none;">How are you?</p>
  </body>
</html>

개발자 도구에 있는 것은 DOM이 아니다.

개발자 도구의 Elements 탭은 DOM과 아주 비슷한 결과를 보여준다. 그러나 개발자 도구 에서는 DOM보다 추가적인 요소를 보여준다.

가장 좋은 예는 CSS 의사 요소(pseudo-elements)이다. ::before과 ::after 선택자를 사용하여 생성된 의사 요소는 CSSOM과 렌더 트리의 일부를 구성한다.

DOM은 오직 원본 HTML 문서로부터 빌드 되고, 요소에 적용되는 스타일을 포함하지 않는다.

의사 요소는 DOM에 포함되지 않음에도 불구하고, 개발자 도구의 Elements 탭에는 포함되어 나타난다

https://bitsofco.de/content/images/2018/11/Pseudo-element-in-devtools-inspector.png

::after 선택자는 DOM에 포함되지 않지만 개발자 도구에는 표시되어 있다.

CSSOM


CSS Object Model은 DOM과 유사한 스타일의 Object 표현이다. 브라우저는 단순한 페이지의 DOM을 생성하는 동안 외부 CSS 스타일 시트인 style.css를 참조하는 문서의 헤드 섹션에서 링크 태그를 접한다. 페이지를 렌더링 하는데 이 리소스가 필요할 것이라고 판단한 브라우저는 리소스에 대한 요청을 즉시 발송하고 요청의 결과로 다음 콘텐츠가 반환된다.

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

HTML과 마찬가지로 수신된 CSS 규칙을 브라우저가 이해하고 처리할 수 있는 형식으로 변환해야 한다. 따라서 CSS에 대해 HTML 프로세스를 반복한다.

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/images/cssom-construction.png?hl=ko

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/images/cssom-tree.png?hl=ko

CSSOM이 트리 구조를 가지는 이유는 무엇일까? 페이지에 있는 객체의 최종 스타일을 계산할 때 브라우저는 해당 노드에 적용 가능한 가장 일반적인 규칙으로 시작한 후 더욱 구체적인 규칙을 적용하는 방식, 즉 ‘하향식’으로 규칙을 적용하여 계산된 스타일을 재귀적으로 세분화한다. HTML과 달리 CSS는 계단식 상속 특성 때문에 부분적으로 실행될 수 없다. 문서의 뒷부분에 정의된 스타일은 이전에 정의된 스타일을 무시하고 변경할 수 있다. 따라서 스타일 시트 전체가 파싱되어야 다음 단계로 넘어갈 수 있다. (렌더링 차단 리소스)

위의 그림에서 body 요소 내에 있는 span 태그 안에 포함된 모든 텍스트의 크기는 16픽셀이고 색상은 빨간색이다. font-size 지시문은 body에서 span으로 하향식을 적용되기 때문이다. 하지만 span 태그가 단락<p> 태그의 하위인 경우 해당 콘텐츠는 표시되지 않는다(display: none).

또한, 위의 트리는 완전한 CSSOM 트리가 아니고 스타일시트에서 재정의하도록 결정한 스타일만 표시한다는 점에 유의해야한다. 모든 브라우저는 ‘사용자 에이전트 스타일’이라고 하는 기본 스타일 집합, 즉 개발자가 고유한 스타일을 제공하지 않을 경우 표시되는 스타일을 제공한다. 개발자가 작성하는 스타일은 이러한 기본 스타일을 간단하게 재정의한다.

JavaScript 실행


JavaScript는 파서 차단 리소스이다. 이 말은 HTML 문서의 파싱이 JavaScript에 의해 차단된다는 뜻이다.

파서가 script 태그에 도달(내부적으로도 외부적으로도) 하면 페치를 멈추고 실행한다. 따라서 문서 내의 요소를 참조하는 JavaScript 파일이 있는 경우 해당 문서가 표시된 후에 배치해야 한다.

참고자료


HTML

DOM은 정확히 무엇일까? WIT블로그

What, exactly, is the DOM?

객체 모델 생성 Web Fundamentals Google Developers

같은 카테고리의 글