
우리는 주로 html, css, js를 사용하여 웹페이지를 만들기 위한 코드를 작성한다.
웹 브라우저에서는 이 코드(Ex) 8비트 데이터 형태인 html 파일)를 가지고 웹페이지를 그려준다.
렌더링 과정에 대해서 알아보기 전에, 웹 브라우저의 구조에 대해서 알아보자.
여러 웹 브라우저가 존재하지만, 공통적인 구조는 아래와 같다.

웹 페이지를 제외하고, 사용자와 상호작용하는 사용자 인터페이스
HTML과 CSS를 파싱하여 요청한 웹 페이지를 표시하는 렌더링 엔진
+) 모든 브라우저에는 고유한 렌더링 엔진이 있다.
User Interface와 Rendering Engine을 연결하는 브라우저 엔진
사용자 인터페이스에서 수신한 입력에 따라 렌더링 엔진을 쿼리하고 처리한다.
각종 네트워크 요청을 수행하는 네트워킹 파트
HTTP 또는 FTP와 같은 표준 프로토콜을 사용하여 네트워크 호출을 관리한다.
체크박스나 버튼과 같은 기본적인 위젯을 그려주는 UI 백엔드 파트
기본 운영 체제의 사용자 인터페이스 방법을 사용한다.
자바스크립트 코드를 구문 분석하고 실행하는 인터프리터 (Ex) Chrome-V8)
해석된 결과가 생성되면 사용자 인터페이스에 표시하기 위해 렌더링 엔진으로 전달된다.
보조 기억장치에 데이터를 저장하는 파트(Ex) LocalStorage, Cookie)
브라우저는 WebSQL, IndexedDB, FileSystem 등과 같은 데이터 저장 메커니즘과 호환되어야 한다.
렌더링 엔진은 웹페이지에 포함된 모든 요소들을 화면에 보여준다. 또한, 업데이트가 필요할때(Ex) 체크박스 클릭) 효율적으로 렌더링을 할 수 있도록 자료구조를 생성한다.
+) 이 과정에서 가공되어지는 하나의 단위는 node(노드)인데, 이 노드는 바이트 형태의 html ➡️ 문자 ➡️ 토큰 ➡️ 노드를 거쳐서 만들어진다. 이 노드를 통해 아래에서 설명할 DOM or CSSOM을 생성하는 것이다.
Critical Rendering Path라고도 불리는 동작 과정은 크게 5가지로 나눌 수 있다.
HTML & CSS 파싱 후 각각의 Tree 생성
이 트리 구조 때문에 부모의 속성이 자식에게 전파되는 것이다!
<html>
<body>
<h1>안녕하세요</h1>
<p>이것은 예시입니다.</p>
</body>
</html> ⬇️html
└── body
├── h1
│ └── "안녕하세요"
└── p
└── "이것은 예시입니다."body { font-family: Arial; }
h1 { color: blue; }
p { margin: 10px; } ⬇️body
├── font-family: Arial
├── h1
│ └── color: blue
└── p
└── margin: 10pxRender Tree 생성
// 브라우저마다 다를 수 있음
body (font-family: Arial)
├── h1 (color: blue)
│ └── "안녕하세요"
└── p (margin: 10px)
└── "이것은 예시입니다."Render Tree 배치(Layout)
렌더 트리가 생성될 때 위치 또는 크기 값은 할당되지 않는다. 따라서, 이 단계에서 각 요소의 크기와 위치를 계산하고 모든 노드에 정확한 좌표가 할당되어 모든 노드가 화면에서 정확한 위치에 나타날 수 있게 된다.
이때, CSS에서 %나 em 같은 상대적인 단위를 사용했을 경우, 기기에 맞춰서 pixel 단위로 변환하게 된다.
Render Tree 그리기(Paint)
실제 화면에 픽셀을 그리는 과정이다. 렌더 트리를 탐색하고 렌더러의 paint() 메서드를 호출하여 UI 백엔드 계층을 사용하여 화면의 각 노드를 그린다.
모든 브라우저는 고유한 렌더링 엔진을 가지고 있다. 따라서 자연스럽게 모든 브라우저는 사용자 화면에서 웹 페이지를 해석하는 고유한 방식을 가지고 있으므로 웹사이트의 크로스 브라우저 호환성도 고려를 해야 한다는 것을 잊지말자. 🤓
레이어 합성(Composite)
레이어를 합성하여 실제 화면에 나타낸다.
어떤 상황인지에 따라서 특정 단계부터 다시 시작하게 된다.
document.getElementById('myDiv').style.width = '200px'; 이 경우, 브라우저는 Layout 단계부터 다시 시작하여 모든 요소의 위치와 크기를 재계산한 후 Paint 단계를 거치게 된다.document.getElementById('myDiv').style.backgroundColor = 'blue'; 이 경우, 브라우저는 Layout 단계를 건너뛰고 Paint 단계부터 다시 시작한다. 요소의 위치와 크기는 그대로지만, 새로운 스타일을 적용하여 다시 그리게 된다.document.getElementById('myDiv').style.transform = 'translateX(100px)'; 이 경우, 브라우저는 Layout과 Paint 단계를 건너뛰고 Composite 단계만 수행한다. 이미 그려진 레이어를 새로운 위치에 배치하는 것만 수행하여 화면을 업데이트하는 것이다.성능 최적화를 위해서는 가능한 한 3번째 경우(레이어 합성)를 활용하는 것이 좋다. 만약 3번이 불가능한 상황이라면, 가능한 한 적은 요소에만 영향을 주도록 코드를 작성하는 것도 방법이다.
Understanding Role of Rendering Engines in Browsers | BrowserStack