브라우저의 렌더링 과정

eonisal·2024년 3월 16일
post-thumbnail

브라우저에 URL 주소를 입력하면 브라우저는 DNS 서버로부터 URL에 해당하는 IP 주소를 얻어내고 그 IP 주소의 웹서버로 HTTP 요청을 보내 웹 페이지 응답을 받아 브라우저상에 출력하게 된다.

웹 브라우저의 동작 과정을 간단히 요약하자면 이렇게 나타낼 수 있는데, 이렇게 받아온 웹 페이지 응답을 화면에 나타내주는 "렌더링"은 어떤 과정으로 이루어지는 것일까?

🏛️ DOM 생성

우선 서버로부터 HTML 파일을 받아와서 HTML 코드를 토대로 DOM을 생성하는데, DOM(Document Object Model)이란 "문서 객체 모델"로, HTML 코드를 브라우저가 본인이 해석하기 편한 방식으로 변환해놓은 객체 모델(트리 구조)을 의미한다. 즉 HTML 문서를 브라우저가 이해하고 조작할 수 있는 객체 형태의 트리 구조로 변환한 것이다.

HTML 파일을 받고 이 DOM을 생성하는 과정이 바로 되는것이 아니라 디코딩 -> 토큰화 -> 렉싱 -> DOM 트리 생성 의 과정을 거친다.

디코딩(Decoding)

서버로부터 받은 HTML 응답은 우리가 알고있는 HTML 코드의 모습이 아니라 0과 1로 이루어진 바이트 스트림(Byte Stream)의 형태이다.

<head>
  <meta charset="UTF-8" />
</head>

보통 HTML 코드를 작성할때 head 태그 내의 meta 태그에 이렇게 인코딩 방식을 지정한다. 여기에 지정한 인코딩 방식대로 인코딩된 바이트 스트림을 응답으로 받는 것이다.

브라우저는 이 바이트 스트림을 다시 디코딩하여 Character 화 시킨다. meta 태그에 지정한 인코딩 방식과 동일한 방식으로 디코딩해 바이트 스트림을 문자로 변환하여 HTML 코드의 내용을 얻어낸다.

토큰화(Tokenization)

바이트 스트림을 디코딩해 얻은 문자열은 곧 HTML 문서의 내용이지만 컴퓨터는 이 코드를 바로 이해하지 못한다. 브라우저가 HTML 코드를 이해하기 위해서 최종적으로 DOM Tree를 그리는데, 이 DOM Tree를 생성하기 위해서 우선 HTML 코드를 구조화하는 토큰화(Tokenization) 과정을 거친다.

디코딩 과정을 거쳐 얻은 HTML 코드 문자열이 다음과 같다고 하자.

브라우저 엔진이 이 문자열을 하나하나 읽으면서 여는 태그와 문자, 닫는 태그를 인식한다. 여는 태그로 시작해 어떠한 문자가 이어지고 닫는 태그가 나오면 그것을 하나의 HTML 태그로 인식하고 토큰(Token)이라는 단위로 표현하여 다음과 같이 나타낸다.

어떤 태그인지를 의미하는 이런 토큰을 만든다. 이 과정을 반복해서

이렇게 StartTag와 EndTag 등 여러 토큰들로 문자열을 표현한다. 이 과정을 토큰화(Tokenization) 라고 한다.

렉싱(Lexing)

토큰화된 결과를 바탕으로 어떤 HTML 요소가 존재하는지를 파악하는 단계로, 토큰을 속성 및 규칙을 정의한 객체로 변환한다.


StartTag 토큰으로 시작해 EndTag 토큰으로 끝나기까지의 구간들을 파악하여 이것은 어떤 태그이고 어떤 컨텐츠가 있는지, 자식 태그가 무엇인지 등의 정보를 담은 객체로 변환한다. 이 객체를 노드(Node)라고 표현한다.

이렇게 토큰을 노드화 시키는 과정을 통해 HTML 태그들을 객체화해 태그들을 구조화 시킨다. 이 노드들은 DOM을 구성하는 기본 단위가 된다.

DOM Tree

렉싱 과정을 거쳐 생성된 노드의 정보를 토대로 노드들 사이의 관계를 파악한다. 파악한 관계를 토대로 노드 간에 관계를 부여하여 다음과 같이 트리 구조로 표현한다.

노드 간에 관계를 부여하여 구조화 시키는것을 Model이라고 한다.

맨 처음에 디코딩 과정을 통해서 HTML 문서(Document) 내용을 얻었고, 그 문서를 토대로 태그들을 객체(Object)화 시켜 노드를 얻었으며, 그 노드 간에 관계를 부여하여 구조화 시킨 Model. 이것이 그 이름도 유명한 DOM(Document Object Model)이다.

이런 과정을 거쳐서 DOM을 생성하여 브라우저는 HTML 코드의 구조를 파악한다. 이 DOM 생성 과정을 한번에 나타낸 이미지가 아래의 이미지이다.

🎨 CSSOM 생성

DOM 생성 과정에서 살펴보았듯, 브라우저는 맨 처음 HTML 파일을 바이트 스트림의 형태로 응답을 받고 이를 디코딩해 캐릭터화 시켜 HTML 코드 문자열로 해석한다. 그 후 한글자씩 읽어나가는 토큰화 과정을 거친다.

<link rel="stylesheet" href="style.css" />

그러다가 이런 CSS 파일을 가져오는 스타일시트 링크 태그를 접하면 다시 웹서버로 요청을 보내 CSS 파일을 응답받는다.

그래서 보통 웹사이트에 들어왔을 때 네트워크 탭을 보면 다음과 같이 HTML 파일을 요청하고 그 뒤에 css 파일을 한번 더 요청하는 모습을 볼 수 있다.

이렇게 CSS 파일을 받아오면, HTML을 DOM 트리로 만든 것처럼 CSS도 브라우저가 이해하고 처리할 수 있도록 변환해줘야 한다.
그래서 CSS 파일도 HTML 파일과 똑같이 디코딩 -> 토큰화 -> 렉싱 -> Model 생성 과정을 거친다.

DOM 생성 과정과 동일한 과정을 거쳐서 다음과 같은 CSSOM 트리를 생성한다.

🖼️ Render Tree 생성

웹 페이지는 HTML 태그에 CSS로 정의한 스타일이 적용된 모습으로 출력된다. 즉 HTML 태그 구조에 CSS 스타일이 합쳐지게 되는 것이다.

이를 위해 DOM과 CSSOM을 생성하고나면 이 둘을 합치는 과정이 수행된다. DOM과 CSSOM을 합쳐 생성한 트리를 Render 트리라고 한다. 말 그대로 렌더링하기 위한 트리! 웹 페이지의 청사진이라고 보면 된다.

생성한 DOM과 CSSOM을 합쳐 Render 트리를 만드는데, 노드의 스타일 정보를 보고 렌더링에 필요한 노드만 포함하여 Render 트리를 생성한다. 이 Render 트리는 웹 페이지를 그리기 위한 최종 설계도인 셈으로, 쓸데없는 애들은 다 제외한다.

예를 들어 head 노드와 같은 애들이나 스타일이 display: none 인 노드들은 어차피 화면에 보이지 않을 요소니까 Render 트리에 반영하지 않음

🧩 Layout

DOM과 CSSOM을 합쳐 Render 트리까지 생성했으면 이제 Render 트리를 기반으로 페이지를 그리면 되는데, 그 전에 페이지를 그리기 위한 사전 계산 작업에 들어간다. 이 과정을 Layout 단계라고 한다.

최종적인 설계도는 갖고 있지만, 그 설계도 상의 모습을 실제 화면에서 어느 위치에 어느 크기로 그릴건지를 따로 확인해야 하는 경우가 있다.

예를 들어 다음과 같이 width가 50%로 지정된 div 요소가 있다고 하자.

이 50%는 우리가 쓰는 화면에 따라서 달라지는 값이다. 이런 값이 현재 화면에서는 정확히 몇 px 이 될지를 계산해야 정확한 길이로 요소를 그려낼 수 있다.

이와 같이 현재 뷰포트 내에서 Render 트리의 요소들의 정확한 위치와 크기 등을 계산하는 단계라고 보면 된다.

🖌️ Paint

Layout 단계를 거쳐 계산을 완료하고 난 후에야 비로소 Render 트리의 요소들을 실제로 화면에 그리게 된다. 이 단계를 Paint 단계라고 한다.

Render 트리의 노드들을 화면의 실제 픽셀로 변환하여 그리는데, 한 페이지에 모든 요소를 그리는게 아니라 여러개의 Layor에 특정 부분씩 나눠서 그리고 그 Layor들을 합쳐서 하나의 완전한 페이지를 생성하게 된다.

이 Layor들을 합치는 과정을 Composite 라고 한다.

만약 한 페이지에 모든 요소를 다 그려놓았는데 특정 부분의 모습이 변해야 한다면 그 페이지의 뷰 전체를 다시 그려야한다. 하지만 요소들을 여러 Layor에 조금씩 나눠서 그리면, 어떤 요소가 변해야 한다면 그 요소가 그려진 Layor만 수정하고 다시 합치면 된다.

따라서 여러 Layor에 나눠서 그리고 그 Layor 들을 Composite 하는 방식으로 Paint 과정이 진행된다. 이렇게 Layor를 합쳐서 우리가 보는 완전한 웹 페이지가 완성되게 된다.

💡 요소를 페이지에 그리는 단계도 실제로는 Paint, Composite 단계 외에 여러 과정이 존재한다. Layor, Tilling, Raster 라는 과정이 있다고 하는데 자세히 알아보고 싶다면 아래의 포스팅을 참고하면 좋을 듯 하다.

브라우저가 그리는 법

🎞️ Critical Rendering Path

브라우저가 처음 HTML 파일과 CSS 파일을 서버로부터 받아오고 실제 화면에 그려지게 되는 이 과정을 Critical Rendering Path 라고 부른다.

🛠️ Reflow, Repaint

이 Critical Rendering Path 과정에서 Layout과 Paint 단계는 우리가 웹 사이트를 이용하면서 매번 반복되는 과정이다.

사용자가 웹 사이트에 처음 접속하면 Critical Rendering Path 과정이 수행되어 웹 페이지가 완성되고 이후 사용자와의 여러 인터랙션으로 인해 새로운 요소가 추가되거나, 기존 요소의 모습이 바뀌거나 하는 변화가 일어난다.

이 변화로 인해 바뀌는 요소들을 반영해 새로 Render 트리를 생성하게 되고 Layout 과정이 수행된다. 이렇게 Layout 과정이 반복되는 것을 Reflow 라고 하고, 반복된 Layout 결과대로 다시 Paint 하는 과정을 Repaint 라고 한다.

Layout과 Paint 단계는 많은 연산을 필요로하는 좀 비싼 작업이다. 따라서 Reflow와 Repaint가 자주 일어나는건 사이트의 성능에 큰 악영향을 주기 때문에 Reflow와 Repaint가 발생하는 DOM 수정이 최대한 적게 발생하도록 코드를 짜는것이 사이트 성능을 위한 중요한 항목이다.

요소에 변경사항이 있다 해서 무조건 Reflow-Repaint 과정이 진행되는것은 아니고 단순 색상 변경과 같은 레이아웃에 영향을 미치지 않는 변화들은 Reflow 과정 없이 Repaint만 수행된다. 또한 Reflow가 발생한다면 Repaint는 무조건 발생한다.

💡 Reflow가 발생하는 속성과 Repaint만 발생하는 대표적인 속성들은 다음과 같다.

Reflow가 발생하는 속성
position, width, height, margin, padding, border, border-width, font-size, font-weight, line-height, text-align, overflow

Repaint만 발생하는 속성
background, color, text-decoration, border-style, border-radius




참고자료

코딩알려주는누나 - 웹개발자면서 이것도 모름? | DOM과 CSSOM, 렌더링 과정
브라우저 렌더링 동작 원리
웹 브라우저에 대해서 (2)
[Web¦Browser] DOM, CSSOM, Render Tree
브라우저의 렌더링 과정
[CSS] 브라우저의 Layer Model과 하드웨어 가속을 이용한 렌더링 최적화에 대해 알아보자!
브라우저가 그리는 법

profile
언제까지_이렇게_살아야돼_

0개의 댓글