38. 브라우저의 렌더링 과정

Sooo·2023년 8월 3일
1

요약

  • 브라우저의 렌더링엔진은 html을 순서대로 파싱하다가, css를 로드하는 link나 style태그를 만나면 html 파싱을 통한 dom생성을 멈추고 css를 파싱해 cssom을 만든다. 마찬가지로 js를 로드하는 script 태그를 만나면 자바스크립트엔진에 제어권을 넘겨 파싱을 완료한 후 다시 html을 파싱한다.
    • DOM이나 CSSOM을 변경하는 자바스크립트코드가 포함되었을 경우, js를 파싱하기 전에 DOM이나 CSSOM이 이미 생성되어 있어야한다. DOM api가 실행되는 시점에 생성이 완료되지 않았다면 문제가 발생할 수 있다.

    • 자바스크립트 로딩/파싱/실행에 의해 html이 블로킹되면 그만큼 UI가 늦게 보여지므로, 페이지 로딩 시간이 길어질 수 있다.

      js script를 html의 body가장 아래에 위치시키는 게 좋다.

  • 렌더트리(DOM + CSSOM 결합)는 브라우저 화면에 렌더링되지 않는 노드 (meta, script 태그)와 css에 의해 비표시되는 노드들은 포함하지 않는다
  • 자바스크립트로 DOM api를 사용하여 조작하면 이미 생성된 DOM, CSSOM을 동적으로 조작할 수 있다
    • 조작되면 변경사항이 다시 렌더트리에 반영되고, 반영된 렌더트리를 기반으로 레이아웃과 페인트과정이 다시 일어난다. (⇒ 리플로우, 리페인트)
    • 자주 일어나면 성능에 안좋다.
  • 자바스크립트는 자바스크립트 엔진에 의해 파싱되어(v8) 어휘분석(lexical analysis)되어 문법적 의미를 가진 토큰으로 분해되고, 다시 토큰들의 집합이 구문 분석(syntax anaysis)되어 AST(추상적 구문 트리)가 생성된다. AST를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트코드를 생성하여 실행한다.
  • async / defer 는 파싱에 의해 dom 생성이 블로킹 되는 이슈를 근본적으로 해결하기 위해 html5부터 script태그에 추가된 속성이다.
    • async: script 태그 순서와 상관없이 html파싱과 js 파일 로드가 비동기적으로 진행된다. 단 로드가 끝난 뒤 js 파싱/실행이 바로 실행되고, 이 때 html 파싱이 중단된다. 태그 순서와 상관없이 로드가 끝난 js 파일부터 실행되므로 js끼리 순서 보장이 필요한 경우 이 속성을 쓰면 안된다. ⇒ ❓이건 언제 쓰는거지?
    • defer: async와 비슷한데, html파싱이 완료되고 DOM생성이 완료되어 DOMContentLoaded 이벤트가 발생하는 시점에 js의 파싱과 실행이 진행된다.

궁금한 점 | 느낀 점

  • js를 로드하는 script 태그의 위치에 따라 js가 dom요소를 찾지 못해 발생하는 이슈가 있을 수 있겠다
  • css는 html 파싱을 멈추고 먼저 하더라도 이후 css와 html의 모든 파싱이 끝난 뒤에 렌더트리를 만들어 브라우저에 레이아웃을 그리므로, 태그의 위치가 상관 없을 것 같다.
    • ❓css 태그 위치가 중요한 케이스가 있을까?
    • ✅ html과 css의 파싱이 모두 끝나야 레이아웃을 그리므로, css 태그 위치는 중요하지 않음
    • ✅ CSS의 내용안에서 선언간 순서는 중요
  • ❓자바스크립트 언어야 싱글스레드 언어이지만, 실행하는 주체인 브라우저는 멀티스레딩이 가능하다고 들었는데, 왜 파싱 도중 제어권을 넘겨야할까? 한 번에 하나의 작업만 실행가능한 것처럼 보인다.
    • ✅ “브라우저는 동기적으로, 위에서 아래로 순차적으로 파싱하고 실행된다.” (673p)

테스트 프로젝트 아이디어

  • index.html에 css와 js를 로드하는 태그를 넣고 순서에 따른 실행 비교하기
  • 오픈소스 자바스크립트 파서를 사용해 AST 생성해보기

1개의 댓글

comment-user-thumbnail
2023년 8월 4일

개발자로서 배울 점이 많은 글이었습니다. 감사합니다.

답글 달기