38.0 브라우저의 렌더링 과정
- 브라우저가 HTML, CSS, JS로 작성된 텍스트 문서를 어떻게 parsing(해석)하여 브라우저에 rendering?
- parsing(구문 분석); 텍스트 문서의 문자열을 토큰으로 분해 (어휘 분석) 이후 구문 트리를 생성하는 과정
- rendering; HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것
- 브라우저의 렌더링 과정 (Critical Rendering Path)
- 브라우저는 HTML, CSS, JS, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 서버로 요청하고, 응답 받음
- 렌더링 엔진은 서버로부터 응답된 HTML, CSS 파싱하여 DOM과 CSSOM 생성, 결합 -> 렌더 트리 생성
- JS 엔진은 서버로부터 응답된 JS를 파싱하여 Abstract Syntax Tree를 생성하고 바이트코드로 변환 후 실행,
JS는 DOM API를 통해 DOM이나 CSSOM 변경 가능, 변경된 DOM과 CSSOM이 다시 렌더 트리로 결합됨
- 렌더 트리 기반으로 HTML 요소의 레이아웃(위치와 크기)을 계산하고 브라우저 화면에 HTML 요소 페인팅
38.1 요청과 응답
- 브라우저의 렌더링 엔진이 HTML 파싱 도중 외부 리소스를 로드하는 태그를 만나면,
HTML 파싱을 일시 중단하고 해당 리소스 파일을 서버로 요청함
38.2 HTTP 1.1과 HTTP 2.0
- HTTP: 웹에서 브라우저와 서버가 통신하기 위한 프로토콜(규약)
- HTTP 1.1 vs. HTTP 2.0
- HTTP 1.1 (1999)
- connection당 하나의 요청과 응답만 처리 (다중 요청/응답 불가능)
- 리소스의 동시 전송이 불가능한 구조, 요청할 리소스 개수에 비례하여 응답 시간 증가하는 단점
- HTTP 2.0 (2015)
- connection당 여러 개의 요청과 응답 (다중 요청/응답 가능)
- 여러 리소스 동시 전송 가능한 구조, HTTP/1.1 보다 페이지 로드 속도 약 50% 빠름
38.3 HTML 파싱과 DOM 생성
- 브라우저의 렌더링 엔진은 서버로부터 응답받은 HTML 문서를 파싱하여,
브라우저가 이해할 수 있는 자료구조인 DOM 생성
- HTML 파싱, DOM 생성 과정
- 브라우저 -> 서버에 HTML 파일 요청
- 서버는 브라우저가 요청한 HTML 파일을 읽어들여 메모리에 저장, 메모리에 저장된 바이트(2진수)를 응답
- 브라우저는 응답 받은 바이트(2진수)를 meta 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식으로
문자열로 변환 (응답 헤더 - content-type: text/html; charset=utf-8)
- 문자열로 변환된 HTML 문서를 토큰들로 분해
- 각 토큰들을 객체로 변환하여 노드 생성
- 모든 노드들을 트리 자료구조로 구성 => DOM (HTML 문서 파싱한 결과물)
38.4 CSS 파싱과 CSSOM 생성
- 렌더링 엔진은 DOM 생성하다가 CSS 로드하는 link 태그나 style 태그 만나면 DOM 생성 일시 중단
- 서버에게 요청하여 로드한 CSS를 HTML과 동일한 파싱 과정 거침 (바이트 -> 문자 -> 토큰 -> 노드 -> CSSOM)
- CSSOM은 CSS의 상속을 반영하여 생성됨
38.5 렌더 트리 생성
- DOM과 CSSOM은 렌더링을 위해 렌더 트리로 결합됨
- 렌더 트리
- 렌더링을 위한 트리 구조의 자료구조
- 브라우저 화면에 렌더링되는 노드만으로 구성
- 각 HTML 요소의 레이아웃(위치와 크기)을 계산하는데 사용되며,
브라우저 화면에 픽섹을 렌더링하는 페인팅 처리에 입력됨
- 리렌더링은 성능에 영향 많이 주므로 주의 필요!
38.6 자바스크립트 파싱과 실행
- JS 코드에서 DOM API 사용하면 이미 생성된 DOM을 동적으로 조작 가능
- JS 파싱과 실행은 렌더링 엔진이 아니라 JS 엔진이 처리함
- JS 엔진은 JS를 해석하여 AST(Abstract Syntax Tree) 생성
- AST 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트 코드 생성하여 실행
- JS 파싱과 실행 과정
- 어휘 분석 (Lexical Analysis)
- 토크나이징
- JS 소스코드 -> 토큰 (토크나이저)
- 구문 분석 (Syntax Analysis)
- 파싱
- 토큰 -> AST (파서)
- 바이트 코드 생성과 실행
- 바이트 코드 생성: AST -> 바이트 코드 (바이트 코드 생성기)
- 바이트 코드 실행: 인터프리터
38.7 리플로우와 리페인트
- DOM API에 의해 DOM이나 CSSOM이 변경될 수 있음
- DOM과 CSSOM은 다시 렌더 트리로 결합되고,
변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정 거쳐 다시 화면에 리렌더링
- 리플로우; 레이아웃 다시 계산 (레이아웃 영향 주는 변경 발생한 경우에 한하여 실행됨)
- 리페인트; 재결합된 렌더 트리를 기반으로 다시 페인트
38.8 자바스크립트 파싱에 의한 HTML 파싱 중단
- 렌더링 엔진과 JS 엔진은 직렬적으로/동기적으로 파싱 수행
- script 태그의 위치에 따라 HTML 파싱 블로킹 되어 DOM 생성 지연 가능성 문제
- script 태그 위치 중요!
- body 요소의 가장 아래에 JS 위치시키는 것은 좋은 아이디어!
- JS 실행될 시점에는 이미 렌더링 엔진이 HTML 요소 모두 파싱하여 DOM 생성 완료한 이후임
- JS 실행 전에 DOM 생성이 완료되어 렌더링되서 페이지 로딩 시간 단축되는 이점
38.9 script 태그의 async/defer 어트리뷰트
- async 어트리뷰트
- 외부 JS 파일 로드하는 경우에만 사용 가능
- HTML 파싱와 외부 JS 파일 로드가 비동기적으로 동시에 진행됨
- JS 파싱과 실행은 JS 파일 로드 완료된 직후에 진행되고, HTML 파싱 중단됨
- 순서 보장 X
- defer 어트리뷰트
- 외부 JS 파일 로드하는 경우에만 사용 가능
- HTML 파싱와 외부 JS 파일 로드가 비동기적으로 동시에 진행됨
- JS 파싱과 실행은 HTML 파싱 완료된 직후 (DOM 생성 완료 직후)에 진행됨
- DOM 생성 완료 이후 실행될 JS에 유용
'Books > 모던 JS Deep Dive ✔️' 카테고리의 다른 글
[모던 JS Deep Dive] 40장 - 이벤트 (0) | 2022.01.25 |
---|---|
[모던 JS Deep Dive] 39장 - DOM (0) | 2022.01.25 |
[모던 JS Deep Dive] 37장 - Set과 Map (0) | 2022.01.20 |
[모던 JS Deep Dive] 36장 - 디스트럭처링 할당 (0) | 2022.01.20 |
[모던 JS Deep Dive] 35장 - 스프레드 문법 (0) | 2022.01.20 |
댓글