티스토리 뷰

브라우저 렌더링 과정 🤔

자바스크립트는 현재 Node.js의 등장으로 백엔드에서도 사용되고 있지만, 그래도 웹 어플리케이션을 만들 때 주로 사용되고 있습니다. 그래서 이번에는 브라우저에서 HTML, CSS, 그리고 자바스크립트로 작성한 문서가 렌더링되는 과정을 알아 보려 합니다. 빠르고 신뢰할 수 있는 웹사이트를 구축하려면, 브라우저가 웹페이지를 렌더링하기 위해 거치는 단계들의 메커니즘을 이해하는 것이 필요하다 생각합니다.

 

아래에서 소개할 렌더링 과정을 요약하면 다음과 같습니다.

  1. HTML 파싱
  2. 외부 리소스 가져오기
  3. CSS 파싱 및 CSSOM 생성
  4. 자바스크립트 실행
  5. DOM과 CSSOM 병합 후 렌더 트리 생성
  6. 레이아웃 계산 및 페인트

 

렌더링(Rendering): HTML, CSS, JavaScript로 작성된 문서를 파싱해 브라우저에 출력하는 것을 말합니다.

 

1. HTML 파싱

클라이언트는 웹사이트에 접속하면 서버에 HTML 문서를 요청합니다. 서버는 요청에 따라 HTML 파일을 메모리에 적재한 후 2진수의 바이트 값을 응답합니다. 브라우저는 수신을 시작하면서, HTML을 문서 객체 모델(DOM)로 변환하기 위해 파서(Parser)를 설정하여 파싱을 수행합니다.

 

이 과정에서 HTML 문서는 문법적으로 최소한의 의미를 갖는 토큰으로 분해되어 DOM을 구성합니다.

 

문서 객체 모델(DOM)은 웹에서 문서의 구조와 내용을 구성하는 데이터 표현입니다.

 

 

2. 외부 리소스 가져오기

브라우저 렌더링 엔진은 HTML 문서를 위에서 아래로 읽기 시작하며, 외부 리소스를 읽는 태그(script, link)를 만나게 되면 잠시 HTML 파싱을 멈추고 외부 리소스에 대한 로드와 파싱을 먼저 수행합니다. 

 

<script type="text/javascript" src="script.js" defer>
<script type="text/javascript" src="script.js" async>

 

defer와 async는 자바스크립트 파싱을 HTML 파싱과 비동기로 할 수 있도록 하는 키워드입니다. 둘의 차이가 있다면 defer는 자바스크립트 파싱이 끝났더라도 HTML 파싱이 완료되지 않았다면 실행하지 않고, async는 파싱이 끝나는 즉시 실행된다는 점에 있습니다.

 

 

3. CSS 파싱 및 CSSOM 생성

HTML을 파싱해서 DOM을 생성하는 것과 비슷하게, CSS 역시 파싱을 통해 렌더링에 필요한 CSSOM을 생성합니다. 둘 모두 웹 사이트를 올바르게 렌더링하기 위해 필요한 구조이며, CSSOM은 웹 페이지의 레이아웃을 결정하고 페인트하는 데 사용됩니다.


CSSOM이 DOM과 다른 점은 CSS 규칙이 특수성으로 인해 서로 다른 다양한 지점에서 서로 덮어쓸 수 있기 때문에 점진적으로 빌드될 수 없다는 것입니다. 이것이 CSS가 렌더링을 차단하는 이유이며, 모든 CSS가 구문 분석되고 CSSOM이 만들어지기 전까지는 브라우저가 화면의 각 요소를 어디에 어떻게 배치해야 하는지 알 수 없습니다.

 

 

4. 자바스크립트 실행

브라우저 렌더링 엔진 script 태그를 만나게 되면 자바스크립트 문서의 로드를 위해 자바스크립트 엔진에게 제어권을 넘깁니다. 브라우저마다 자바스크립트 엔진을 탑재하고 있으며, 대표적으로 크롬의 V8, 파이어폭스의 SpiderMonkey 등이 있습니다. 자바스크립트 엔진은 자바스크립트로 작성된 코드를 CPU가 이해할 수 있는 저수준 언어(Low-level Language)로 변환하고 실행하는 역할을 합니다.

 

브라우저 렌더링 엔진이 DOM과 CSSOM을 만들던 것처럼, 자바스크립트 엔진도 AST(Abstract Syntax Tree)라는 트리를 만들어 인터프리터가 이해할 수 있는 바이트코드를 생성하여 실행합니다. 바이트코드까지 생성을 마치게 되면, 자바스크립트 엔진의 인터프리터에 의해 실행이 되고 제어권이 다시 브라우저 렌더링 엔진에게로 넘어갑니다.

 

 

5. DOM과 CSSOM 병합 후 렌더 트리 생성

렌더 트리는 DOM과 CSSOM을 병합한 트리 구조이며, 웹 페이지에 렌더링될 모든 내용을 나타냅니다. 이는 렌더 트리의 모든 노드가 시각적으로 존재함을 의미하는 것은 아닙니다. 예를 들어 CSS의 opacity가 0 또는 display: none으로 스타일이 설정된 노드는 화면에 보여지지 않을 것이므로 렌더 트리에 포함되지 않습니다.

 

그리고 시각적 정보를 포함하지 않는 <head>와 같은 태그는 항상 생략됩니다.

 

 

6. 레이아웃 계산 및 페인트

최종적으로 만들어진 렌더 트리를 통해 브라우저에 출력할 요소에 대한 레이아웃을 결정하고, 페인트라는 그리기 작업을 수행합니다. 여기까지의 작업을 렌더링이라 부르며, 레이아웃이 변경되거나 요소가 추가/제거됨으로써 리렌더링이 언제든 발생할 수 있습니다.

 

다만 리렌더링은 비용이 많이 드는 작업이므로, 항상 최소화할 수 있도록 해야 좋은 성능을 기대할 수 있습니다.

 

 

참고 📖

렌더링 트리 생성, 레이아웃 및 페인트

자바스크립트 엔진 톺아보기

자바스크립트 개발자를 위한 AST(번역)

How the browser renders a web page

댓글