
브라우저의 핵심 기능은 필요한 리소스를 서버에 요청하고 서버로부터 응답받아 브라우저에 시각적으로 렌더링하는 것이다. 브라우저의 주소창에 URL을 입력하고 접속하면 DNS를 통해 IP 주소로 변환되고 이 IP 주소를 갖는 서버에게 요청을 전송한다. 개발자 도구의 Network 패널을 확인하면 어떤 파일을 응답 받았는지 알 수 있다. 이 때 html 파일만 요청했음에도 CSS, 자바스크립트, 이미지, 폰트 파일들도 응답 받은 것을 확인 할 수 있다. html의 link 태그, img 태그, script 태그 등을 만나면 HTML의 파싱을 일시 중단하고 해당 리소스 파일을 서버로 요청하기 때문이다.
순수 텍스트인 HTML을 브라우저에 시각적인 픽셀로 렌더링하려면 HTML 문서를 브라우저가 이해할 수 있는 자료구조(DOM, Document Object Model)로 변환하여 메모리에 저장해야 한다. 브라우저의 렌더링 엔진은 HTML 문서를 파싱하여 DOM을 생성한다.
인코딩 방식을 기준으로 문자열로 변환한다.트리 자료구조로 구성하며, 이를 DOM이라 한다.렌더링 엔진은 HTML을 처음부터 한 줄씩 순차적으로 파싱하여 DOM을 생성해 나가다가 CSS를 로드하는 link 또는 style 태그를 만나면 DOM 생성을 일시 중단한다. 그리고 해당 CSS 파일을 서버에 요청하여 로드한 CSS 파일 또는 style 태그 내의 CSS를 HTML과 동일한 파싱 과정(바이트 -> 문자 -> 토큰 -> 노드 -> CSSOM)을 거치며 CSSOM을 생성한다. 파싱을 완료하면 HTML 파싱이 중단된 지점부터 다시 HTML을 파싱하기 시작하여 DOM 생성을 재개한다. CSSOM은 CSS 상속을 반영한다.
렌더링을 위해 DOM과 CSSOM을 결합한 트리 자료구조다. 브라우저 화면에 렌더링되는 노드만 포함하며, 브라우저 화면에 렌더링되지 않는 노드(meta 태그, script 태그 등)와 CSS에 의해 표시되지 않는 노드(display:none)들은 포함하지 않는다. 완성된 렌더 트리는 각 HTML 요소의 레이아웃을 계산하는 데 사용되며, 브라우저 화면에 픽셀을 렌더링하는 페인팅 처리에 입력된다.
레이아웃, 페인팅을 다시 실행하는 리렌더링은 비용이 많이 드는 작업이다. 리렌더링이 빈번하게 발생하지 않도록 주의해야 한다.
- 자바스크립트에 의한 노드 추가 또는 삭제
- 브라우저 창의 리사이징에 의한 뷰포트 크기 변경
- HTML 요소의 레이아웃(위치,크기)에 변경을 발생시키는 width/height, margin, padding, border, display, position, top/right/bottom/left 등의 스타일 변경
CSS 파싱 과정과 마찬가지로 DOM 생성 중 script 태그를 만나면 DOM 생성을 일시 중단하고, src 어트리뷰트에 정의된 자바스크립트 파일을 서버에 요청하여 로드한 자바스크립트 파일이나 script 태그 내의 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에 제어권을 넘긴다. 자바스크립트 엔진은 자바스크립트를 해석하여 AST(추상적 구문 트리, Abstract Syntax Tree)를 생성하고, 이를 기반으로 인터프리터가 실행할 수 있는 중간 코드(Intermediate Code)인 바이트코드를 생성하여 실행한다. 이렇게 자바스크립트 파싱과 실행이 완료되면 렌더링 엔진으로 다시 제어권을 넘겨 HTML 파싱을 중단된 지점부터 다시 시작하여 DOM 생성을 재개한다.
자바스크립트 코드에 DOM API가 사용된 경우 DOM이나 CSSOM이 변경되고 다시 렌더 트리로 결합된 후 레이아웃과 페인트 과정을 거쳐 브라우저의 화면에 다시 렌더링된다. 리플로우는 레이아웃 계산을 다시 하는 것을 말하고, 리페인트는 재결합된 렌더 트리를 기반으로 다시 페인트하는 것을 말한다. 레이아웃에 영향이 없는 변경은 리플로우 없이 리페인트만 실행된다.