렌더링 엔진이란?
역할
HTML, CSS, JS, 이미지 등 웹페이지에 포함된 모든 요소를 화면에 보여줍니다.
업데이트가 필요할 때 효율적으로 렌더링 할 수 있도록 자료구조를 생성합니다.
*업데이트가 일어나는 환경: 입력, 스크롤, 애니메이션, 데이터 로딩
동작과정
웹 페이지에 접속하게 되면, 네트워크를 통해 해당 웹페이지의 HTML 문서를 얻어옵니다.
이 때 렌더링 엔진은 아래의 다이어그램과 같은 과정을 거쳐 읽어들인 HTML 문서를 해석합니다.

- 위의 4단계(Critical Rendering Path)는 다음 과정의 각 단계에 순서대로 대응됩니다.
- 파싱(Parsing)
- 렌더트리(Render Tree) 구축
- 레이아웃(Layout)(또는 리플로우(Reflow))
- 페인트(Paint)
+. 합성(Composite)
❗️각 단계에서 리소스를 로드하는 순서나, 작성한 스크립트 내용에 따라 웹페이지의 반응속도가 달라질 수 있습니다.
프론트엔드 개발자가 브라우저 렌더링을 알아야 하는 이유중 하나가 아닐까...
렌더링 엔진의 동작 과정
1. 파싱(Parsing)
(HTML, CSS)코드를 토큰화(Tokenize)하고 구조화 하는 과정입니다.
*자바스크립트는 JS엔진에서 별도로 해석됨
- 어휘분석기(Lexical scanner 또는 Lexer)를 통해 코드가 토큰화 됩니다.
*<div></div>를 토큰화 하면 ['<','div','>','</','div','>'] 와 같이 나타냅니다. - 파서는 토큰화된 코드를 해석, 구문 규칙과 일치하면 파싱 트리에 추가, 또 다른 토큰을 요청합니다.
- 위 과정을 코드를 모두 해석할 때 까지 반복합니다.
포괄적인 파싱 과정은 위와 같고, HTML과 CSS의 상세한 파싱 과정에 대해서도 알아보겠습니다.

HTML 파싱 과정
- HTML 문서의 코드들이 토큰화됩니다.
- 토큰은 각각의 속성과 규칙을 정의하는 노드 객체로 변환됩니다.
- 태그: element node
- 태그의 요소: attribute node
- 텍스트: text node
- 주석: comment node
- 각 노드가 서로 연관성을 가질 수 있도록 DOM 트리를 생성합니다.
HTML 파서의 특징
- 오류에 너그러운 특성을 가지고 있습니다.
*예를 들면, 태그를 열고 태그를 닫지 않아도, 브라우저에서 실행시키면 완성된 코드로 수정되어 나옵니다.
<!-- 브라우저 실행 후 -->
<div>hi
<!-- 브라우저 실행 후 -->
<div>hi</div>
- 파싱 과정이 도중에 중단될 수 있습니다.
- 파싱 도중 <script>(Javascript), <link>(CSS) 같은 외부 태그를 만날 경우 해당 태그의 해석을 실행합니다.
*<script>의 경우 DOM을 직접 수정하는 내용이 있을 수도 있기 때문이기도 합니다.
- 파싱 도중 <script>(Javascript), <link>(CSS) 같은 외부 태그를 만날 경우 해당 태그의 해석을 실행합니다.
- 파싱 과정의 재시작(Reentrant)이 있을 수 있습니다.
- 파싱 도중 외부 요인으로 DOM이 추가, 변경, 삭제될 경우 HTML은 처음부터 다시 파싱을 진행합니다.
*파싱과정: 바이트를 문자로 변환 > 토큰 실별 후 노드로 변환 > DOM 트리 빌드
*처리해야 할 HTML이 많을 경우 파싱 시간이 오래 걸릴 수 있습니다.
- 파싱 도중 외부 요인으로 DOM이 추가, 변경, 삭제될 경우 HTML은 처음부터 다시 파싱을 진행합니다.
CSS 파싱
일반적으로 CSS를 링크하는 코드는 HTML 코드 내에 삽입 되어 있기 때문에, HTML 파싱 도중에 CSS 파싱이 시작됩니다.
<!-- HTML 파싱 중... -->
<head>
<!-- HTML 파싱 중단, CSS 파싱 시작 -->
<link rel="stylesheet" href="styles.css">
</head>
CSS 파싱과정은 위에서 말한 공통 파싱 과정 대로(1. 파싱 항목 참조)
: CSS 파일 다운로드 → 토큰화 → 구문 해석 → (CSSOM)트리 생성 과정으로 이루어집니다.

2. 렌더트리(Render Tree) 구축

DOM 트리와 CSSOM 트리가 합쳐져 Render 트리가 만들어집니다.
렌더 트리는 화면에 나타나는 요소들을 결정하는 트리입니다.
*어떤 요소들이, 어떤 스타일로, 어떤 순서로 나타날 것인지를 결정합니다.
이 때, 화면에 그려지지 않는 요소들은 트리에 나타나지 않습니다. 시각적으로 나타낼 것이 없기 때문입니다.
*예를 들면 HTML의 <head>, <script>과 같은 태그나, CSS의 display:none 스타일이 적용된 엘리먼트 입니다.
즉 렌더트리는 DOM트리는 정확하게 1:1로 매칭되지는 않습니다.(DOM 트리는 나타나지 않는 요소도 모두 포함합니다.)
구축 과정
- Document 객체의 각 노드를 순회합니다.
- 각 노드에 해당하는 CSSOM 규칙을 찾아 적용합니다.
- 렌더와 관련된(시각적으로 보여질) 요소들만 렌더트리에 포함시킵니다.
3. 레이아웃(또는 리플로우)
렌더 트리를 화면에 배치하기 위해 노드들의 크기와 위치를 계산을 합니다.
크기가 %나 em같은 상대적 단위를 사용했을 경우 기기의 뷰포트에 맞춰서 픽셀 단위로 변환됩니다.
따라서 뷰포트를 변경하면 레이아웃부터 렌더링 과정이 다시 일어납니다.
*뷰포트: 브라우저의 순수 화면 영역
이 과정은 HTML 루트에서부터 재귀적으로 실행됩니다.
*부모노드 → 자녀노드 순서라고 보면 됩니다.
4. 페인트
레이아웃 단계를 통해 계산된 엘리먼트들을 실제 픽셀로 그려주는 단계입니다.
이 과정 역시 루트에서부터 재귀적으로 실행됩니다.
+. 합성
마지막으로 이 단계에서 Paint 단계에서 생성된 레이어를 합성하여 실제 화면에 나타냅니다.
*페인트는 트리 형태의 여러 레이어로 나뉘어져 진행되고, 합성단계에서 하나로 합쳐집니다.
UI가 업데이트되는 3가지 상황
1. 레이아웃부터 다시 발생하는 경우(리플로우)
- 뷰포트 리사이징
- 노드 추가 / 제거
- 노드의 크기 / 위치 변경
2. 페인트부터 다시 발생하는 경우
- 레이아웃의 수치(위치, 크기 등)를 변화시키지 않는 스타일의 변경(background, font color, shadow 등)이 일어났을때 발생
3. 레이어의 합성만 다시 발생하는 경우(리페인트)
- transform, opacity 변경 시 발생

불필요한 UI 업데이트를 줄여 페이지의 최적화 하기 위해 개발 시 충분히 고려해야 할 사항입니다.
언제, 어떻게 UI 업데이트가 되는지 CSS 속성별로 상세하게 알고싶다면 아래 링크를 참고하시면 좋습니다.
- 3편에서는 DOM에 대해서 알아보겠습니다.
https://ure93.tistory.com/4
[참고자료]
https://d2.naver.com/helloworld/59361
https://yozm.wishket.com/magazine/detail/1338/
https://www.youtube.com/watch?v=sJ14cWjrNis&t=610s