Skip to content
On this page

브라우저의 렌더링 과정

수정하기
문서 생성 2021-10-02 19:43:00 최근 수정 2022-12-14 23:38:40

브라우저가 HTML, CSS, JavaScript로 작성된 문서를 어떻게 파싱해서 렌더링하는지 알아보도록 하겠다.

우선 브라우저의 주소창에 접속하고 싶은 URL을 입력하거나 서버로부터 정적/동적 데이터를 Ajax 또는 REST-API를 통해 요청할 것이다.
일반적으로 서버는 스킴과 호스트만으로 구성된 URI에 의한 요청(루트 요청)에 암묵적으로 index.html을 응답하도록 되어있다. 따라서 루트 요청이 들어오면 루트 폴더의 정적 파일 index.html을 브라우저에 응답한다.
(https://google.com이 요청되면 https://google.com/index.html)

개발자도구 네트워크.png

주소창에 URL을 입력해 접속을 하면 브라우저 개발자 도구의 Network 패널에 다양한 리소스들이 응답되는 것을 확인할 수 있다.

다음은 브라우저에 응답된 이 HTML 문서(여기서는 index.html)를 렌더링 하는 과정을 살펴보자.

HTML 파싱 그리고 DOM 생성

HTML 문서는 문자열로 이루어진 텍스트이기 때문에 브라우저에 시각적으로 렌더링 하기 위해서 HTML 문서를 브라우저가 이해할 수 있는 구조로 변환해야 한다. 여기서 말하는 브라우저가 이해할 수 있는 구조란 DOM을 의미한다. DOM을 생성하는 과정은 다음과 같다.

  1. 서버에 있는 HTML 파일을 브라우저가 요청해서 응답을 해야 한다. 이때 서버는 브라우저가 요청한 HTML을 읽어서 바이트를 응답한다.
  2. 브라우저는 서버가 응답한 바이트 형태 데이터(HTML 문서가 변환된)를 받는다. 해당 데이터는 <meta> 태그의 charset 어트리뷰트에 의해 지정된 인코딩 방식을 기준으로 문자열로 변환된다.
  3. 문자열로 변환된 HTML 문서를 읽어서 문법적 의미를 갖는 최소 단위인 토큰으로 분해한다.
  4. 각 토큰들을 객체로 변환해서 **노드(node)들을 생성한다. 토큰의 내용에 따라 문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드가 생성된다.
  5. HTML 문서의 요소들은 중첩 관계를 갖는다. 이 부모-자식 관계를 반영해서 모든 노드들을 트리 자료구조로 구성한다. 이렇게 구성된 트리 자료구조를 DOM이라고 한다.

CSS 파싱 그리고 CSSDOM 생성

브라우저 렌더링 엔진이 HTML 문서를 파싱해서 DOM을 생성하다가 CSS를 불러오는 <link> 태그나 <style> 태그를 만나면 파싱을 일시 중단한다. 그다음에 <link> 태그의 href 에 지정된 CSS 파일을 서버에 요청해 불러온 CSS 파일 또는 <style> 태그 내의 CSS를 HTML 문서를 통해 DOM 을 만든 것처럼 CSSDOM을 만든다.
CSS 파싱이 완료되면 기존 HTML 파싱을 일시 중단했던 지점부터 다시 HTML 파싱을 시작한다.
CSSDOM도 DOM 처럼, CSS의 상속 관계를 반영해서 생성한다.

렌더 트리 생성

지금까지 만들어진 DOM과 CSSDOM은 렌더링을 위해 렌더 트리로 결합된다.
렌더 트리는 말 그대로 렌더링을 위한 트리이기 때문에 브라우저 화면에 렌더링 되지 않는 노드(<meta> 태그, <script> 태그, display: none; 등)들은 포함되지 않는다.

완성된 렌더 트리는 HTML 요소들의 레이아웃(위치/크기)을 계산하는 데 사용되고 브라우저 화면에 픽셀을 렌더링하는 페인팅 처리에 입력이 된다.

DOM과 CSSDOM, 렌더 트리의 생성 과정은 계속 반복될 수 있다. 다음과 같은 경우에 레이아웃 계산, 페인팅이 재실행된다. (리플로우, 리페인팅)

  • 자바스크립트에 의한 노드 추가/삭제
  • 브라우저 창의 리사이징에 의한 뷰포트 크기 변경
  • HTML 요소의 레이아웃 변경을 발생시키는 style 변경 (width, height, margin, padding, border, display, position, top, right, bottom, left 등...)

레이아웃 계산, 그리고 페이팅을 다시 실행하는 리렌더링은 성능에 악영향을 주는 작업이다. 가급적 빈번하게 발생하지 않도록 주의할 필요가 있다.

자바스크립트 파싱과 실행

CSS 파싱과 마찬가지로 브라우저 렌더링 엔진이 HTML을 파싱하면서 DOM을 생성하다가 <script> 태그를 만나면 DOM 생성을 일시 중단한다.
그 후에 자바스크립트 엔진이 자바스크립트 파싱과 실행을 진행한다. 그리고 자바스크립트 파싱이 종료되면 다시 브라우저 렌더링 엔진이 DOM 생성을 재개한다.

자바스크립트 엔진은 자바스크립트 코드를 파싱해서 CPU가 이해할 수 있는 저수준 언어로 변환하고 실행하는 역할을 한다.
브라우저 렌더링 엔진이 HTML, CSS를 파싱해서 DOM과 CSSDOM을 생성하는 것처럼 자바스크립트 엔진은 자바스크립트를 해석해 AST(추상적 구문 트리)를 생성한다. 그리고 이 AST를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 바이트코드를 생성해 실행한다.

자바스크립트 소스코드를 토크나이저가 토크나이징을 해서 토큰으로 만들고 파서가 파싱을 해서 AST를 만든다. 그리고 AST를 바이트코드로 바꾸어 인터프리터가 실행을 한다.

자바스크립트 소스코드 → 토크나이저(토크나이징) → 토큰 -> 파서(파싱) → AST → 바이트코드 생성기(바이트코드 생성) → 바이트코드 → 인터프리터(실행)

토크나이징/렉싱

토크나이징은 자바스크립트 소스코드를 '토큰'이라 부르는 (해당 언어에) 의미 있는 조각으로 만드는 과정이다. 렉싱은 토큰의 의미를 분석한다.

파싱

토큰 배열을 프로그램의 문법 구조를 반영해 트리 형태로 바꾸는 과정이다. 이 파싱의 결과로 만들어진 트리를 AST(Abstract Syntax Tree, 추상 구문 트리) 라고 부른다. 이 AST가 실행 코드로 변경된다.

리플로우, 리페인트

만약에 자바스크립트 코드 내에 DOM이나 CSSDOM을 변경하는 DOM API가 사용된 경우, 변경된 DOM가 CSSDOM은 다시 렌더 트리로 결합되어 변경된 렌더 트리를 기반으로 레이아웃과 페인팅 과정을 거쳐서 화면이 리렌더링 된다. 이를 리플로우, 리페인트라고 한다.

script 태그의 async, defer 어트리뷰트

reference

같이 보기

Tags