https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=251552545
모던 자바스크립트 Deep Dive 교재에 나온 내용을 바탕으로 정리하였다.
1. 브라우저 랜더링 전체 과정
1. 브라우저가 HTML, CSS, JavaScript, 이미지 등의 리소스를 서버측에 요청하고 응답받는다.
2. 브라우저 랜더링 엔진에서 HTML과 CSS를 파싱하여 각각 DOM과 CSSOM을 생성한다.
3. 브라우저 자바스크립트 엔진은 Javascript를 파싱하여 AST(Abstract Syntax Tree)를 생성한다.
4. AST는 실행 후 DOM API를 통하여 DOM과 CSSOM을 변경한다.
5. 변경된 DOM과 CSSOM은 다시 Render Tree로 결합된다.
6. Render Tree를 기반으로 브라우저 화면에 페인팅한다.
※ 파싱?
프로그래밍 언어에 맞게 작성된 텍스트 문서를 읽어서 트리구조로 만드는 과정이다.
2. 랜더링 엔진이 HTML을 DOM으로 바꾸는 과정
1. 브라우저는 서버가 응답한 html 문서를 바이트 형태로 응답 받는다.
2. 응답된 바이트 형태의 html은 meta 태그에 선언된 인코딩 방식(UTF-8)에 따라 문자열로 변환된다.
3. 문자열로 변환된 html은 토큰들로 분해된다.
4. 각 토큰들을 객체로 변환하여 노드(node)를 생성한다.
5. 노드들은 각 요소간 관계를 반영하여 트리 자료구조로 구성된다. 이 트리 자료구조를 DOM이라 한다.
※토큰?
의미를 가지는 최소 단위
※DOM?
Document Object Model의 약자
3. CSS 파싱과 CSSOM 생성 과정
기본적으로 HTML 파싱과정과 동일하다.
- 랜더링 엔진이 HTML을 처음부터 한 줄씩 순서대로 파싱하다가 style 태그 또는 link 태그를 만나면 DOM 생성을 일시 중단하고 css 파일을 서버에 요청한다.
- 요청한 css파일은 바이트 -> 문자열 -> 토큰 -> 노드 -> CSSOM 의 과정을 거친다.
- css 파싱이 완료되면 html 파싱 중단 지점부터 다시 html 파싱을 시작한다.
4. 자바스크립트 파싱과 실행
- DOM은 html요소와 스타일을 변경할 수 있는 DOM API를 제공한다. 이 DOM API는 자바스크립트 실행 후 DOM과 CSSOM을 변경하도록 도와준다.
- css 파싱과정과 마찬가지로 랜더링 엔진은 html을 한 줄씩 파싱하다가 script 태그를 만나면 DOM 생성을 일시 중단하고 자바스크립트 엔진이 자바스크립트 코드를 파싱하기 시작한다.
1. 자바스크립트 코드를 토큰들로 분해한다. (토크나이징 tokenizing)
2. 토큰들을 구분 분석(파싱)하여 AST(추상적 구문 트리)를 생성한다.
3. AST는 바이트코드로 변환되고 인터프레터에 의해 실행된다.
5. 랜더트리 생성 및 리플로우, 리랜더링 과정
1. 랜더트리 생성
- 랜더링 엔진은 DOM과 CSSOM을 결합하여 랜더 트리를 생성한다.
- 브라우저 화면에 랜더링 되지 않는 노드는 제외된다. (meta 태그, script 태그, css display:none 등)
- 랜더 트리는 html 요소의 레이아웃(위치&크기) 계산에 사용되고 브라우저 화면에 페인트된다.
2. 리플로우 & 리페인트
- 자바스크립트 코드에 DOM API가 사용되면 DOM과 CSSOM이 변경된다.
- 변경된 DOM과 CSSOM은 다시 렌더 트리를 생성하고 레이아웃 계산을 다시 한다. (리플로우)
- 레이아웃 된 결과를 바탕으로 다시 페인트 한다. (리페인트)
- 레이아웃에 영향이 없는 변경은 리플로우 없이 리페인트만 실행된다.
6. Script 태그의 위치
: 브라우저는 위에서 아래방향으로 순차적으로(동기적으로) 파싱하고 실행한다. 따라서 script 태그의 위치는 body 요소의 가장 아래에 위치시키는 것이 좋다. DOM API 사용시 DOM과 CSSOM이 이미 생성되어 있어야 하기 때문이다.
- DOM이 완성되지 않은 상태에서 DOM API 사용시 작동이 안될 수 있다.
- body 요소 가장 아래에 자바스크립트를 위치시키면 html 요소들의 랜더링에 지장받는 일이 없기에 페이지 로딩 시간이 단축된다.
추가내용)
HTML5부터 script 태그에 async와 defer 어트리뷰트가 추가되었다. async와 defer 어트리뷰트를 사용하면 자바스크립트 파일의 파싱와 로드가 비동기적으로 진행된다.