본문 바로가기
개발서적/모던 자바스크립트 Deep Dive

브라우저의 렌더링 과정 (모던 자바스크립트 Deep Dive)

by 사과넹 2024. 4. 17.
반응형

  • 파싱(parsing)
    • 다음과 같은 일련의 과정을 일컫는다.
      • 프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽는다.
      • 프로그램을 실행하기 위해 텍스트 문서의 문자열을 토큰으로 분해한다.
      • 토큰에 문법적 의미와 구조를 반영한다.
      • 트리 구조의 자료구조인 파스 트리를 생성한다.
    • 파싱이 완료되면 파스 트리를 기반으로 중간 언어인 byte code를 생성하고 실행한다.
  • 렌더링(rendering)
    • HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것
    • 렌더링 과정
      • 브라우저는 렌더링에 필요한 리소스를 서버에게 요청하고 응답받는다.
      • 응답 온 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성하고 결합하여 렌더 트리를 생성한다.
      • 브라우저의 자바스크립트 엔진은 응답 온 자바스크립트를 파싱하여 AST(Abstract Syntax Tree)를 생성하고 바이트코드로 변환하여 실행한다.
        • 자바스크립트는 DOM API를 통해 DOM이나 CSSOM을 변경할 수 있고, 변경이 된다면 다시 렌더 트리로 결합된다.
      • 렌더 트리를 기반으로 HTML 요소의 레이아웃을 계산하고 브라우저 화면에 HTML 요소를 출력한다.

 

38.1 요청과 응답

  • 서버에 요청을 전송하기 위해 브라우저는 주소창을 제공한다.
    • 주소창에 URL을 입력하고 enter 키를 누르면 다음과 같은 일이 발생한다.
      • URL의 호스트 이름이 DNS(Domain Name System)을 통해 IP 주소로 변환된다.
      • 이 IP 주소를 갖는 서버에서 요청을 전송한다.
      • 일반적으로 서버는 루트 요청에 대해 암묵적으로 index.html을 응답하도록 설정되어 있다.
        • 다른 파일을 원하면 정적 파일 경로를 path 에 기술하여 서버에 요청해야 한다.

 

38.2 HTTP 1.1과 HTTP 2.0

  • HTTP는 브라우저와 서버가 통신하기 위한 프로토콜이다.

HTTP 1.1

  • connection당 하나의 요청과 응답만 처리한다.
  • html 문서 내 포함된 여러 개의 리소스 요청들(CSS의 link, javascript의 script)이 개별적으로 전송된다.
  • 동시 전송이 불가능한 구조이기 때문에 리소스 개수와 응답 시간이 비례하다.

HTTP 2.0

  • connection당 다중 요청과 응답이 가능하다.
  • HTTP 1.1에 비해 페이지 로드 속도가 약 50% 정도 빠르다고 알려져 있다.

 

38.3 HTML 파싱과 DOM 생성

  • HTML은 순수한 텍스트이기 때문에 브라우저에 시각적인 픽셀로 렌더링하기 위해서는 브라우저가 이해할 수 있는 자료구조(객체)로 변환하여 메모리에 저장해야 한다.
  • 렌더링 엔진은 응답받은 HTML 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM(Document Object Model)을 생성한다.

  • HTML 파싱 과정, DOM 생성 과정
    1. 서버는 브라우저가 요청한 HTML 파일을 메모리에 저장하고, 메모리에 저장된 바이트(2진수 형태)를 인터넷에 경유하여 응답한다.
    2. 브라우저는 바이트 형태로 응답받는다. 응답된 HTML 문서는 meta 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식을 기준으로 문자열로 변환된다.
    3. 문자열로 변환된 HTML 문서를 읽어 들여 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해한다.
    4. 각 토큰들을 객체로 변환하여 node를 생성한다. 토큰의 내용에 따라 문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드가 생성되고, 노드는 DOM을 구성하는 기본 요소가 된다.
    5. HTML 문서는 요소들의 집합으로 이루어지며 HTML 요소는 중첩 관계를 갖는다. 요소 간의 부자 관계를 반영하여 모든 노드들은 트리 자료구조를 구성하고 이를 DOM이라고 부른다.
  • DOM은 HTML 문서를 파싱한 결과물 이다.

 

38.4 CSS 파싱과 CSSOM 생성

  • HTML 파싱 도중 CSS를 로드하는 link나 style 태그를 만나면 DOM 생성을 일시 중지한다.
  • DOM 생성과 동일한 파싱 과정을 거친다.
    • byte → 문자 → token → node → CSSOM
    • 결과물은 CSSOM(CSS Object Model)이다.

38.5 렌더 트리 생성

  • DOM과 CSSOM은 렌더링을 위해 렌더 트리로 결합된다.
  • 화면에 렌더링되지 않는 노드들은 포함하지 않는다.
    • display:none; 같은 경우
  • 완성된 렌더 트리는 HTML 요소의 레이아웃을 계산하는 데 사용되며 픽셀을 렌더링하는 painting 처리에 입력된다.
  • 다음과 같을 때, 반복해서 레이아웃 계산과 페인팅이 재 실행된다.
    • 자바스크립트에 의한 노드 추가 또는 삭제
    • 브라우저 창의 리사이징에 의한 뷰포트 변경
    • HTML 요소의 레이아웃에 변경을 발생시키는 스타일 변경
  • 이런 레이아웃 계산과 페인팅 재실행은 성능을 저하시키는 원인이다.

 

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

  • DOM 생성 중, script 태그를 만나면 브라우저의 렌더링 엔진에서 자바스크립트 엔진 으로 제어권이 넘어 간다.
  • 자바스크립트 엔진은 자바스크립트 코드를 파싱하여 CPU가 이해할 수 있는 저수준 언어로 변환하고 실행하는 역할을 한다.
  • HTML과 CSS는 DOM과 CSSOM을 생성하고, 자바스크립트는 AST(Abstract Syntax Tree, 추상적 구문 트리) 를 생성한다.
    • AST를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트코드를 생성하여 실행한다.

토크나이징
문자열인 자바스크립트 코드를 문법적 의미를 갖는 코드의 최소 단위인 토큰으로 분해한다. lexing(렉싱)이라고 부르기도 하지만 차이는 있다.

파싱
AST를 생성한다. 토큰에 문법적 의미와 구조를 반영한 트리 구조이다. 인터프리터나 컴파일러만 사용할 수 있는 것이 아닌 Typescript, Babel, Prettier 같은 트랜스파일러를 구현할 수도 있다.

 

바이트 코드 생성과 실행

  • 파싱의 결과물로 생성된 AST는 인터프리터가 실행할 수 있는 중간 코드인 바이트코드로 변환되고 인터프리터에 의해 실행된다.

 

38.7 리플로우와 리페인트

  • 자바스크립트에 의해 DOM이나 CSSOM이 변경되면 렌더 트리로 다시 결합하고, 그 렌더 트리 기반으로 레이아웃과 페인트 과정을 거쳐 리렌더링 해야한다.
    • 이것을 reflow, repaint라고 부른다.
    • 경우에 따라 하나만 실행되기도 한다.

 

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

  • 렌더링 엔진과 자바스크립트 엔진은 직렬적으로 파싱한다.
  • 동기적으로 파싱되기 때문에 html에서 link, script tag의 위치는 중요하다.
  • 특히 script 태그는 DOM이나 CSSOM의 변경을 일으킬 수 있기 때문에 제일 뒤에 위치하는 것이 좋다.

 

38.9 script 태그의 async, defer 어트리뷰트

  • 자바스크립트 파싱에 의해 DOM 생성 중단되는 문제를 해결하기 위한 방법!
  • HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 진행된다.

async

  • 자바스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 직 후 진행되며 이때 HTML 파싱이 중단된다.
  • 순서와 상관없이 로드가 완려된 자바스크립트부터 실행된다.

defer

  • DOM 생성이 완료된 직후 자바스크립트 파싱과 실행이 진행된다.
728x90
반응형