브라우저 렌더링 과정 요약했던걸 좀 더 과정 그 자체를 파악하는 것에 중점을 둬 한번 더 요약해보았다.
브라우저의 렌더링이 시작되는 것은 위 아키텍쳐의 11번으로부터 시작된다.
주소창에 직접 주소를 입력하던가 클릭을 통해 웹 페이지로 사용자가 접근하면 클라이언트에서 해당되는 파일을 서버에 요청해 받아오게 된다.
사용자가 요청한 URI를 DNS를 통해 적절한 IP주소를 찾아 해당 IP를 가진 서버에 GET요청을 보내는 것이다.
브라우저가 서버에 있는 HTML파일을 얻어 Byte Stream(2진수) 형태로 응답받는다.
응답된 바이트 형태의 HTML문서를 응답 헤더의 charset
에 명시된 대로 디코딩하여 문자열로 변환하고
content-type
에 명시된 text/html
MIMTYPE을 보고 HTML 파일로 인식하고 파싱한다.
문자열로 변환 된 이후의 상세한 파싱 과정
(1) 토큰: 변환된 문자열을 토큰화해 HTML에 사용되는 최소 단위인 `Element`, `Attribute` 등의 구성요소로 분해한다.
(2) 노드: 변환된 토큰을 DOM에서 사용될 객체인 Node로 변환한다.
변환된 노드들은 트리 자료구조인 DOM을 형성하게 된다.
HTML 마크업에 정의된 여러 태그 간의 계층 관계를 해석해서 트리 구조로 연결이 된다.
HTML파싱 중 css링크를 만나면 CSS파일을 가져오고 파싱한다.
HTML처럼 CSS도 서버로부터 바이트 데이터로 얻어와 파싱하고 CSS Object Model을 형성한다.
결국 HTML을 파싱하던 도중 외부 CSS 파일을 다운로드하고 파싱하는 형태일텐데 이들은 브라우저에서 병렬처리된다.
렌더링 엔진이 문서의 처음부터 끝까지 모두 해석하고 DOM
과 CSSOM
이 완성되면 이 둘을 결합해 render tree
를 생성한다.
render tree
를 사용해 브라우저에 보이는 레이아웃(Layout Operation)을 계산하고 페인팅(Painting Operation)한다.
render tree
에는 최종적으로 화면에 보여질 항목에 대한 것들로만 형성된다.
render tree
를 기반으로 HTML 요소들의 위치와 크기를 계산해 적절한 위치에 구성한다.
계산된 HTML요소들의 레이아웃을 바탕으로 브라우저 화면에 픽셀을 채워넣는 작업이다.
페인팅 작업까지 모두 완료되면 실제로 브라우저 화면에 렌더링이 된다!
렌더링 엔진이 HTML 노드를 통해 DOM을 형성하던 도중 script
태그를 만나면 DOM 생성을 중지한다.
script 태그에 정의된 자바스크립트 파일을 서버에 요청하여 로드하고
해당 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에게 제어권이 넘어가며
모두 파싱해 실행이 끝나면 렌더링 엔진으로 다시 제어권이 넘어간다.
Blocking되는 이유
병렬적으로 처리하다가 렌더링 작업을 방해할 수 있다.
자바스크립트에서 DOM을 변경하거나 스타일을 변경할 수 있고 이는 DOM, CSSDOM을 업데이트하는데 동시에 이 작업들이 수행된다면 뭘 먼저 읽어서 처리해야되는지 모르는 상황이 발생한다.
async
HTML파싱과 외부 자바스크립트 파일 로드가 비동기적으로 동시에 진행된다.
자바스크립트 파일 로드가 끝나면 자바스크립트 파싱이 진행되며 이 때 HTML 파싱이 중단된다.
여러 태그에 async
를 지정하면 스크립트 태그 지정 순서와 상관없이 먼저 로드된 자바스크립트 파일부터 실행하기 때문에 주의해야 한다.
defer
HTML파싱과 외부 자바스크립트 파일 로드가 비동기적으로 동시에 진행되고
자바스크립트의 파싱과 실행은 DOM이 형성된 직후 진행된다.