브라우저 렌더링 과정을 알아보기 전에 먼저 DOM에 대해 알 필요가 있다.
HTML, XML과 같은 마크업 언어를 로봇에 비유한다면, 이런 로봇의 팔, 다리를 리모컨(자바스크립트와 같은 프로그래밍 언어)으로 조작할 수 있게끔 하는 인터페이스를 DOM(Document Object Model)이라 할 수 있다.
내가 좋아하는 개발자 유투버인 얄코님께서 DOM을 로봇을 조종하는 리모컨에 비유했다. 이 말을 듣고 DOM을 이해해버렸다. 확실히 누군가 이해하기 쉽게 알려주는 것도 재능의 영역인 듯 하다ㅎ. MDN이 소개하는 DOM을 살펴보자.
문서 객체 모델(The Document Object Model)은 HTML, XML 문서의 프로그래밍 인터페이스로서 문서의 구조화된 표현(structured representation)과 자바스크립트와 같은 프로그래밍 언어가 문서에 접근할 수 있는 방법을 제공하여 그들이 문서 구조, 스타일, 내용 등을 변경할 수 있게 돕는다. DOM은 계층적 구조를 가진 노드 트리로 구성된다.
Global Object(브라우저에서 현재 열려있는 창을 의미)로서 DOM, BOM, JavaScript의 모든 오브젝트들을 포함하는 가장 기본적인 오브젝트로 아래 두 가지 역할을 수행한다.
호스트 환경이 웹 브라우저인 경우
호스트와 호스트 환경
자바스크립트가 돌아가는 플랫폼을 호스트(host)라고 부르며, 브라우저, 웹서버 등 다양한 것들이 호스트가 될 수 있다. 각 플랫폼은 해당 플랫폼에 특정되는 기능을 제공하는데, 자바스크립트 명세서에서는 이를 호스트 환경이라고 부른다.
호스트 환경은 랭귀지 코어(ECMAScript)에 더해 플랫폼 종속적인 객체 및 함수를 제공한다. 예를 들어, 웹브라우저는 웹페이지를 제어하기 위한 수단을 제공하고, Node.js는 서버 사이드 기능을 제공한다.
Document Object(문서 객체)란 html, head, body와 같은 태그들을 javascript가 이용할 수 있는 (메모리에 보관할 수 있는) 객체를 의미하며, 페이지의 기본 진입점 역할을 한다. 웹 페이지 내의 모든 콘텐츠를 객체로 나타내며, 이 객체를 이용해 페이지 내 모든 요소를 변경, 특정 요소를 생성할 수 있다.
프로그래머가 작성한 html 파일을 브라우저가 읽게 되며, html 내 태그들을 각각의 노드(브라우저가 이해할 수 있는 오브젝트)로 변환하는 과정을 수행한다.
HTML을 지탱하는 것은 태그(tag)이다. DOM에 따르면 모든 html 태그는 객체이며, 태그 내의 문자 역시 객체이다. 이런 모든 객체는 자바스크립트를 통해 접근할 수 있고, 페이지를 조작할 때 이 객체를 사용한다. html 태그는 그에 상응하는 DOM tree 요소를 지닌다.
브라우저에서 DOM과 프로그래머가 정의한 CSS를 병합하여 만든 Object Model
DOM + CSSOM 후, 브라우저에서 사용자에게 직접 보여지는 태그들만 선별하여 렌더링한 것이다. (head태그, display: none인 태그 등의 요소들은 제외된다.)
opacity: 0, visibility: hidden
VSdisplay: none
앞의 두 가지의 경우 렌더 트리에 포함되지만, 마지막의 경우는 포함되지 않는다. 따라서 상황에 맞는 속성을 적용해야 렌더링 과정에서 불필요한 성능 저하가 일어나지 않는다. (이 부분은 프론트엔드 단골 면접 질문이니 잘 알고 넘어가자. 실제로 받은적 있다..ㅎ)
브라우저 객체 모델(Browser Object Model, BOM)은 문서 이외의 모든 것을 제어하기 위해 브라우저(호스트 환경)가 제공하는 추가 객체를 나타낸다.
navigator.userAgent
현재 사용 중인 브라우저 정보 제공navigator.platform
브라우저가 실행 중인 운영체제 정보 제공CPR이란 브라우저가 HTML, CSS, Javascipt를 화면에 픽셀로 변화하는 일련의 단계로, 픽셀 파이프라인(Pixel Pipeline)이라고도 한다. 한마디로 '브라우저가 웹 애플리케이션을 사용자에게 보여주기까지의 과정'라 할 수 있다.
HTML 파일을 브라우저가 이해할 수 있는 파일로 변환하는 단계
requests/response: 브라우저가 서버에 HTML 파일을 요청 후 응답을 받는다.
loading: HTML 파일(데이터)을 받아온다.
scripting: HTML 파일을 한 줄씩 바이트(byte) 단위로 읽는 과정이며(파싱), HTML 중간에 스크립트나 css, 이미지가 존재하는 경우에는 HTML 파싱이 중단된다.
HTML→DOM: 바이트 → 문자(html의 meta의 charset을 참조) → HTML 토큰(태그와 텍스트 및 속성) → 노드 → DOM 트리
CSS→CSSOM: 바이트 -> 문자 -> CSS 규칙, 즉 선택자(selector)와 선언(declaration) -> CSSOM 트리
Javascript→AST(Abstract Syntax Tree)
rendering: DOM과 CSSOM을 결합하여 render tree(렌더 트리)를 생성한다. render tree의 각 노드는 DOM 트리의 요소와 연결되며, CSSOM 트리에서 해당 요소에 적용된 스타일 정보를 포함한다. 즉, render tree는 HTML 문서의 구조와 각 요소의 스타일 정보를 모두 포함한 트리이다. render tree는 화면에 표시되는 각 요소의 레이아웃을 계산하는 데 사용된다.
reflow는 브라우저 주요 렌더링 경로의 모든 단계를 모두 재실행하고, repaint의 경우도 레이아웃을 제외하고 재실행하므로 모두 렌더링 성능에 영향을 줄 수 있다. 따라서 reflow와 repaint를 잘 관리하는 것이 성능 최적화에 도움이 되며, 아래와 같은 최적화 방법이 있다.
위에서 살펴본 것과 같이, reflow를 유발하는 CSS 속성 사용을 최소화해야 한다. 가능한 한 CSS 스타일을 미리 설정해 초기 페이지 로드 시에만 계산이 이루어지도록 하고, 이후에는 변경하지 않는 것이 좋다.
CSS 에니메이션 최적화: 하드웨어 가속이란 CPU에서 처리해야 할 작업을 GPU에 위임하여 더욱 효율적으로 처리하는 방법이다. transform
, opacity
와 같은 css 속성을 사용하면, 요소를 별도의 레이어로 분리하고 작업을 GPU에 위임하여 처리함으로써 레이아웃 단계와 페인트 단계를 건너뛸 수 있다. 단, 레이어가 많아지면 그만큼 메모리 소모가 많아진다는 점을 유의해야 한다.
will-change
속성 사용: 브라우저에 특정 요소가 변경될 것이라고 미리 알려줄 수 있다. 예를 들어, will-change: transform
으로 미리 GPU에서 요소를 준비하게 하여 reflow와 repaint에 미치는 영향을 줄일 수 있다. 하지만 will-chagne
속성을 너무 자주 사용하면 메모리 낭비가 발생하므로 필요한 요소에만 적용할 필요가 있다.
참고자료
매일메일 (기술면접 메일 서비스) - 'reflow와 repaint의 차이점에 대해서 설명해주세요.', '브라우저 렌더링 파이프라인에 대해서 설명해주세요.'
DOM 소개 - Web API | MDN
The HTML DOM API - Web API | MDN
[10분 테코톡] 러기의 브라우저의 동작
Render-tree Construction, Layout, and Paint | Web Fundamentals