[240429] 38장 브라우저 렌더링 과정
- 브라우저는 HTML, CSS, 자바스크립트, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받는다.
- 브라우저의 렌더링 엔진은 서버로부터 응답된 HTML과 CSS를 파싱하여 DOM과 CSSOM을 생성하고, 이들을 결합하여 렌더 트리를 생성한다.
- 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱하여 AST 를 생성하고 바이트코드로 변환하여 실행한다. 이때 자바스크립트는 DOM API를 통해 DOM 이나 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.
- 렌더 트리를 기반으로 HTML 요소의 레이아웃을 계산하고 브라우저 화면에 HTML 요소를 페인팅한다.
요청과 응답
- 서버에 요청을 전송하기 위해 브라우저는 주소창을 제공함
- URL을 입력하고 엔터키를 누르면 URL의 호스트 이름이 DNS를 통해 IP 주소로 변환되고 IP 주소로 변환되고 이 IP주소를 갖는 서버에서 요청을 전송한다.
HTTP 1.1과 HTTP 2.0
- HTTP는 웹에서 브라우저와 서버가 통신하기 위한 프로토콜(규약)이다.
- 1999년에 HTTP.1.1 , 2015년에 HTTP/2 가 발표됨
- 차이점
- HTTP/1.1 커넥션당 하나의 요청과 응답만 처리
- 여러개의 요청을 한번에 전송할 수 없고 응답 또한 마찬가지
- 응답 시간 증가
- HTTP/2 는 커넥션당 다중 요청.응답 가능
- HTTP/1.1 에 비해 페이지 로드 속도가 약 50% 정도 빠름
- HTTP/1.1 커넥션당 하나의 요청과 응답만 처리
- 차이점
HTML 파싱과 DOM 생성
- HTML은 순수한 텍스트인데, 시각적인 픽셀로 렌더링하려면 브라우저가 이해할 수 있는 자료구조로 변환하여 메모리에 저장해야 한다.
→ 자료구조 DOM 생성
- 토큰들을 객체로 변환하여 노드를 생성하는데, 토근의 내용에 따라 문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드가 생성
- HTML 요소는 중첩 관계를 갖는다. 시작 태그와 종료 태그 사이에 텍스트뿐만 아니라, HTML 요소도 포함될 수 있다. → 트리 자료구조
- 즉 DOM은 HTML 문서를 파싱한 결과물임
CSS 파싱과 CSSOM 생성
- 렌더링 엔진은 HTML을 처음부터 한 줄씩 순차적으로 파싱하여 DOM 생성
- CSS로드하는 link나 style 태그를 만나면 DOM 생성 일지 중지
- CSS를 HTML과 동일한 파싱 과정으로 해석하여 CSSOM 을 생성
- CSS 파싱 완료하면 HTML 파싱이 중단된 지점부터 다시 파싱 시작
- CSSOM은 CSS을 상속을 반영하여 생성됨
렌더 트리 생성
- DOM과 CSSOM은 렌더링을 위해 렌더 트리로 결합
- 브라우저 화면에 렌더링 되는 노드만으로 구성 ( meta 태그, script 태그 등은 포함 X )
-
완성된 렌더 트리는 각 HTML 요소의 레이아웃을 계산하는데 사용, 브라우저 화면에 픽셀을 렌더링하는 페인팅 처리에 입력된다.
- 아래와 같은 경우, 반복해서 레이아웃 게산과 페인팅이 재차 실행됨
- 자바스크립트에 의한 노드 추가 또 는 삭제
- 브라우저 창의 리사이징에 의한 뷰포트 크기 변경
- HTML 요소의 레이아웃에 변경을 발생 시키는 width/height , margin 등의 스타일 변경 - 레이아웃 계산과 페인팅을 다시 실행하는 리렌더링은 비용이 많이 드는 작업임
자바스크립트 파싱과 실행
- DOM은 HTML 문서의 구조와 정보뿐만 아니라 HTML 요소와 스타일 등을 변경할 수 있는 프로그래밍 인터페이스로서 DOM API 를 제공한다.
- CSS파싱 과정과 마찬가지로 HTML 을 한 줄씩 순차적으로 파싱하여 DOM 생성하다가 script 태그를 만나면 DOM 생성 일지 중단
- 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에 제어권을 넘긴다.
- AST (추상적 구문 트리) 생성
- AST 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트 코드 생성하여 실행
- 자바스크립트 파싱과 실행이 종료되면 렌더링 엔진으로 다시 제어권을 넘겨 HTML 파싱이 중단된 지점부터 HTML 파싱 시작하여 DOM 생성 재개
- 자바스크립트의 파싱과 실행은 브라우저의 렌더링 엔진이 아닌 자바스크립트 엔진이 처리
- 자스엔진은 CPU가 이해할 수 있는 저수준 언어로 변환하고 실행하는 역할을 함
- 구글 크롬과 Node.js는 V8, 모두 ECMAScript 사양을 준수함
토크나이징
- 코드의 최소 단위인 코큰들로 분해
파싱
- 토큰들의 집합을 구문 분석하여 AST를 생성
- AST를 사용하면 TypeScript, Babel, Prettier 과 같은 트랜스파일러 구현 가능
바이트코드 생성과 실행
- 파싱의 결과물
- 인터프리터에 의해 실행
- V8 엔진의 경우 자주 사용되는 코드는 터포팬이라 불리는 컴파일러에 의해 최적화된 머신 코드로 컴파일되어 성능을 최적화한다. 코드 사용 빈도가 적어지면 다시 디옵티마이징하기도함
리플로우와 리페인트
- 변경하는 DOM API 가 사용된 경우DOM과 CSSOM은 다시 렌더 트리로 결합되고 레이아웃과 페인트 과정을 거쳐 브라우저 화면에 다시 렌더링함
- 리플로우와 리페인트는 순차적인건 아니고, 레이아웃에 영향이 없는 변경은 리페인트만 실행
자바스크립트 파싱에 의한 HTML 파싱 중단
- 브라우저는 동기적 (위→아래) 로 순차적으로 파싱하고 실행함
- script 태그의 위치에 따라 HTML 파싱이 블로킹되어 DOM 생성이 지연될 수 있어서 sciprt 태그 위치는 중요한 의미 가짐
- 자바스크립트 위치를 가장 아래에 두는것도 좋은 아이디어다.
- 완성되지 않은 상태에서 자바스크립트가 DOM을 조작하면 에러 발생할 수 있음
- 자바스크립트 로딩/파싱/실행으로 인해 HTML요소들의 렌더링에 지장받는 일이 발생하지 않아 페이지 로딩 시간 단축
script 태그의 async/defer 어트리뷰트
- HTML5부터는 DOM 생성 중단의 문제를 해결하기 위해 async와 defer 어트리뷰트가 추가되었다.
- asyne와 defer 어트리뷰트는 src 어트리뷰트를 통해 외부 자바스크립트 파일을 로드하는 경우에만 사용 가능
- 즉, 인라인에서는 불가능
<script async src="extern.js"></script>
<script defer src="extern.js"></script>
async 어트리뷰트
- 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행
-
단, 자바스크립트의 파싱과 실행은 로드가 완료된 후 진행되며, 이때 HTML 파싱은 중단
- 로드가 완료된 자바스크립트부터 실행되기때문에 순서 보장이 필요한 script 태그에는 지정X
defer 어트리뷰트
- 로드는 비동기적으로 진행, 실행은 HTML 파싱이 완료된 직후 실행
- DOM 생성이 완료된 이후 실행되어야 할 자바스크립트에 유용
Leave a comment