FrontEnd

[프론트엔드 면접 대비] 브라우저의 렌더링 과정 알아보기

DevInvestor 2021. 8. 24. 00:52
반응형

모던 자바스크립트 Deep Dive - YES24

 

모던 자바스크립트 Deep Dive - YES24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com

 

모던자바스크립트 Deep Dive 책의 38장을 정리한 내용임

브라우저의 렌더링 과정 개요

  • 파싱
    • parse tree/ syntax tree를 생성하는 일련의 과정
    • 파싱이 완료되면 파스 트리 기반으로 바이트 코드를 생성함
      • 바이트 코드는 특정 하드웨어가 아니라 가상 머신에서 실행하도록 만든 바이너리 코드
  • 렌더링
    • html, css, js 문서를 파싱하여 브라우저에 시각적으로 출력하는 것
    • CSSOM +DOM > Render Tree 생성 후 레이아웃, 페인팅을 통해 브라우저에 출력됨

브라우저의 렌더링 과정

브라우저는 다음 과정을 거쳐 렌더링을 수행함

  1. HTML, JS, CSS, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버에서 응답받는다.
  2. CSS와 HTML로 각각 CSSOM과 DOM을 생성 후 결합하여 렌더 트리를 만든다 (렌더링 엔진)
    1. HTML 해석하다 CSS(스타일, 링크 태그)를 만나면 CSS를 파싱한다. 그 후 중단된 HTML 파싱 과정으로 돌아옴
  3. HTML을 파싱하다 JS를 만나면(script 태그) 자바스크립트 엔진이 자바스크립트를 파싱하여 AST > 바이트코드로 변환하여 실행
    1. 이때 실행되는 JS는 DOM과 CSSOM을 조작할 수 있음 > script 실행 시점이 중요
  4. 렌더 트리를 기반으로 레이아웃(위치와 크기) 계산 후 HTML 요소를 페인팅
  • 브라우저의 기능은 필요한 리소스를 서버에 요청 및 응답받아 시각적 렌더링 및 인터랙션 제공
    • 리소스 다운로드, 파싱, 렌더링, JS해석 & 실행
  • 브라우저의 렌더링 엔진은 HTML을 파싱하는 도중 외부 리소스를 로드하는 태그를 만나면 HTML의 파싱을 일시 중단하고 해당 리소스 파일을 서버로 요청함
    • script 태그
    • img 태그
    • link 태그 ...
  • HTTP/1.1 vs HTTP/2
    • HTTP/2는 다중응답/다중요청 가능
    • HTTP/1.1은 응답 와야 다음 요청 보냄

HTML 파싱과 DOM 생성

  • DOM은 HTML 문서를 파싱한 결과물인 트리 자료구조다
  • 다운로드 한 리소스는 바이너리에 불과
    • 파일 포맷에 맞게 파싱 > 자료구조로 변환 > 메모리 저장 필요
  • 브라우저의 렌더링 엔진은 HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM 생성
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script src="app.js"></script>
  </body>
</html>

HTML 파싱과 DOM 생성

  1. 서버에서 응답받은 HTML 프일은 바이너리에 불과 (바이트 - 2진수)
  2. 응답 헤더의 charset 에 따라 디코딩 (ex: utf-8)
    • content-type: text/html; charset=utf-8
  3. 문자열로 변환된 HTML 문서를 문법적 의미를 갖는 코드의 최소 단위인 토큰화
  4. 토큰을 객체로 변환하여 노드 생성
    1. 노드는 document, attribute, text 노드 등이 있음
    2. DOM의 기본 구성 요소임
  5. HTML 노드의 부자 관계를 반영하여 트리 자료구조 만듬
    1. 이 트리 자료구조가 DOM
  • CSS도 동일하게 바이트 > 문자 >토큰 > 노드 > CSSOM을 거쳐 해석함
    • link 태그나 style 태그 만나면...

CSSOM 생성

렌더 트리 생성

  • 렌더링 엔진은 DOM과 CSSOM을 결합하여 render tree를 생성함
    • 렌더 트리는 렌더링을 위한 트리의 자료구조임
      • 화면에 렌더링되지 않는 노드들은 포함되지 않음
        • 브라우저 화면에 렌더링되는 노드만으로 구성
      • ex) (display : none)인 css에 의해 비표시되는 태그, script태그, meta태그 등

  • 렌더 트리는 레이아웃(위치와 크기) 계산과 페인팅(브라우저 화면에 렌더링)에 사용됨

  • 레이아웃 계산과 페인팅은 반복 실행될 수 있음 (가급적 줄여야 함)
    • 자바스크립트에 의한 노드 추가 / 삭제
    • 브라우저 창의 리사이징에 의한 뷰포트 크기 변경
    • HTML 요소의 레이아웃(위치,크기)을 변경시키는 스타일 변경

자바스크립트 파싱과 실행

  • DOM은 HTML 문서의 구조와 정보, 스타일을 변경할 수 있는 DOM API 제공
  • 자바스크립트 파싱은 자바스크립트 엔진이 실행함
    • script 태그를 만나면 src 어트리뷰트에 정의된 파일을 서버에 요청 후 로드
    • 렌더링 엔진이 자바스크립트 엔진에 제어권을 넘겨줌
    • 자바스크립트 파싱 및 실행 종료 후 렌더링 엔진에 다시 제어권을 넘김
    • AST > 바이트코드

자바스크립트 파싱과 실행

  • 토크나이징
    • 소스코드를 문법적 의미 코드 최소 단위인 토큰으로 분해
  • 파싱
    • 토큰에 문법적 의미와 구조 반영한 AST(추상 구문 트리)를 생성
  • 바이트코드 생성과 실행
    • AST는 인터프리터(v8-ignition)가 실행할 수 있는 중간 코드인 바이트코드로 변환 후 실행됨
    • JIT (v8-turbofan)에 의해 머신 코드로 컴파일 되기도 함

리플로우와 리페인트

  • 자바스크립트 코드에 DOM이나 CSSOM을 변경하는 DOM API가 사용된 경우
    • 렌더 트리로 다시 DOM과 CSSOM을 결합 후 레아이웃 > 페인트 과정 거쳐 다시 렌더링
    • 리플로우, 리페인트

DOM API에 의한 리플로우, 리페인트

  • 리플로우는 레이아웃을 다시 계산
    • 노드 추가 삭제
    • 요소 크기 위치 변경
    • 윈도우 리사이징
  • 리페인트
    • 재결합된 렌더 트리 기반 다시 페인트
  • 레이아웃에 영향이 없는 변경은 리플로우 없이 리페인트만 실행

자바스크립트 파싱에 의한 HTML 파싱 중단

  • 렌더링 엔진과 자바스크립트 엔진은 파싱을 직렬적으로 실행
    • 동기적, 순차적 HTML, JS, CSS 파싱 및 실행
      • JS의 경우 DOM, CSSOM이 미완성된 경우 오류 가능

  • app.js에서 파싱이 다 끝나기 전에
  • 요소를 조작하면?
    • TypeError
  • script 태그를 닫는 body 바로 위에 위치시키는 이유
    • 로딩 전 DOM 조작 오류 방지
    • 자바스크립트 실행 전에 DOM 생성이 완료되었으므로 페이지 로딩 시간 단축
      • 다시 HTML을 파싱할 필요 없음
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <ul>
      <li id="apple">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
    <script>
      /*
      DOM API인 document.getElementById는 DOM에서 id가 'apple'인 HTML 요소를
      취득한다. 아래 코드가 실행되는 시점에는 id가 'apple'인 HTML 요소의 파싱이 완료되어
      DOM에 포함되어 있기 때문에 정상적으로 동작한다.
      */
      const $apple = document.getElementById('apple');

      // apple 요소의 css color 프로퍼티 값을 변경한다.
      $apple.style.color = 'red';
    </script>
  </body>
</html>

script 태그의 async/defer 어트리뷰트

  • 자바스크립트 파싱에 의해 DOM 생성이 중단되는 문제 해결 위한 어트리뷰트
  • src 어트리뷰트가 없는 inline 자바스크립트에는 사용 불가
    • 외부 파일 로딩에만 사용 가능
<script async src="extern.js"></script>
<script defer src="extern.js"></script>
  • async
    • 자바스크립트 로드만 비동기로 실행
    • 다운 왼료되면 JS 실행하며 HTML 파싱 중단
      • 여려개 있으면 다운 먼저된놈부터 실행됨
      • 순서보장이 안됨

  • defer
    • 로드 비동기로 하고 마지막에 실행해줌

  • DOMContentLoaded 이벤트
    • HTML 파싱이 완료된 직후 발생
    • 즉, DOM 생성이 완료된 직후 발생
  • 좀 더 공부해보면 좋은 내용
    • AST
    • 바이트코드
      • 기계어의 추상화

이 내용들은 면접에 무조건 나오는거 같다. 매번 복기하자.

반응형