브라우저 렌더링(작동) 원리

📅 TIL #127




🎯 Achievement Goals

  1. 브라우저의 렌더링(작동)원리에 대해서 이해한다.
  2. Reflow가 발생하는 이유와 방지 방법에 대해서 이해한다.
  3. 렌더링 최적화에 대해서 고민해본다.







브라우저의 렌더링(작동) 원리


브라우저의 구조


브라우저의 작동 원리에 대해서 알아보기 전에 먼저 웹 브라우저의 구조를 살펴보았다. 이 중에서도 HTML과 CSS를 파싱하여 요청한 웹 페이지를 표시하는 렌더링 엔진에 대해서 더 알아볼 예정이다.


렌더링 엔진은 다음과 같은 목표를 가진다.

  1. HTML, CSS, 이미지 등 웹 페이지에 포함된 모든 요소들을 화면에 보여준다.
  2. 업데이트가 필요할 때, 효율적으로 렌더링할 수 있도록 자료 구조를 생성한다.


나는 보통 웹 페이지에 들어가기 위해 주소 url에 웹 페이지 주소를 입력하고 엔터를 누른다. 그러면 어떤 일이 발생할까?

먼저 웹 페이지 해당 서버에 요청(request)를 보내게 된다.

그러면 서버는 요청을 받고 응답(response)으로 HTML 데이터를 내려주게 되고 이 HTML 데이터가 브라우저 하나의 화면을 그려내는 과정을 중요 렌더링 경로(Critical Rendering Path)라고 부른다. 그러면 나는 그려내는 과정을 한 번 살펴보자.




중요 렌더링 경로(Critical Rendering Path)


렌더링경로1


  1. 서버에서 응답으로 받은 HTML 데이터를 파싱한다.
  2. HTML을 파싱한 결과로 DOM Tree를 생성한다.
  3. 파싱하는 중 CSS 링크를 만나면 CSS 파일을 요청해서 받아온다.
  4. CSS 파일을 읽어서 CSSOM(CSS Object Model)을 만든다.
  5. DOM Tree와 CSSOM이 모두 만들어지면 이 둘을 결합해서 Render Tree를 만든다.
  6. Render Tree가 생성되면 브라우저의 view port를 계산해서 Layout 과정을 거친다.
  7. Layout 과정이 완료되면 계산이 완료된 Render Tree를 사용해서 실제 화면을 그리게 된다.


그러면 각 단계마다 더 구체적으로 알아보자.




DOM Tree와 CSSOM Tree 생성

렌더링경로2


서버에 요청을 하고 응답으로 HTML 데이터를 받아온다고 설명했었다. 그러면 이 HTML을 파싱하게 되는데, 파싱이란 브라우저가 코드를 이해하고 사용할 수 있는 구조로 변환하는 것을 의미한다.


<!DOCTYPE html>
<html>
 <head>
  <link rel="stylesheet" href="styled.css">
 </head>

 <body>
  <h1>안녕하세요 이우성입니다!</h1>
 </body>
</html>


파싱을 하게 되면 이제 HTML표준에 따라 문자열을 토큰(Token)화 한다. 토큰화는 위에 예시 코드안에서 <html>은 StartTag를 뜻하고, </html>는 EndTag를 뜻하는 것과 같이 고유 토큰으로 변환되는 것을 말한다. 그리고 이 모든 과정이 끝나면 DOM Tree가 생성이 된다.


HTML을 파싱하다가 CSS 링크를 만나면 CSS파일을 요청해서 CSSOM(CSS Object Model) Tree를 생성한다. CSSOM은 DOM이 화면에 어떻게 표시되는지 알려주는 역할을 한다.


CSSOM을 구성하는 것 까지 끝나야 Rendering 과정을 시작할 수 있다. 즉 Render Tree를 생성할 수 있다는 뜻이다. 그렇기 때문에 CSS는 Rendering의 blocking 요소라고도 부른다.




Render Tree 생성


렌더링경로3


CSSOM을 만들었으니 이제 DOM과 CSSOM을 결합하여 Render Tree를 생성하게 된다. Render Tree는 화면에 표시되어야 할 모든 노드의 컨텐츠, 스타일 정보를 포함하는 트리이다.


렌더와 관련된 모든 것을 Render Tree에 포함시키는데, 이때 display: none같이 영향이 가지 않는 것은 Render Tree에 추가되지 않는다. 마찬가지로 화면에 보이지 않는 meta 태그 등도 추가되지 않는다.


renderTree




Render Tree 배치 (Layout or Reflow)


렌더링경로4


Render Tree가 생성되면 이제 Render Tree 배치 과정을 거친다. 이 과정은 view port 내에서 요소들의 정확한 위치와 크기를 계산하는 과정을 일컫는다.

(CSS Box model에 따라 여백이나 높이, 너비 등을 계산할 때를 말한다.)


%, vh, vw와 같이 상대적인 속성들은 실제 화면에 그려지는 px단위로 변환되며 이 과정을 Layout 또는 Reflow라고 한다.




Render Tree Paint(RePaint)


렌더링경로5


위치나 크기의 계산이 끝났으면 이제 Render Tree의 각 노드들을 사용해서 화면을 그리게 되는데 이 과정을 RePaint라고 하며, 이 때 Render Tree에 포함된 모든 요소들이 실제 픽셀로 그려지게 된다.


지금까지 HTML과 CSS만으로 렌더링 과정이 어떻게 진행되는지 살펴보았다.


그러면 여기서 자바스크립트가 실행되면서 CSS가 변경되거나 애니메이션이 재생되었을 때는 어떻게 될까?

  • 다시 Layout이 발생하는 경우: 요소의 크기나 브라우저 창이 변경되었을 때


  • Paint부터 다시 발생되는 경우: 주로 배경 이미지나 텍스트 색상, 그림자 등 Layout의 수치를 변화시키지 않는 스타일의 변경이 일어났을 때 발생


  • 레이어의 Composite(합성)만 다시 발생하는 경우: Layout과 Paint를 수행하지 않고 레이어의 합성만 발생하기 때문에 성능상으로 가장 큰 이점을 가진다.




렌더링 최적화


그러면 나는 자연스럽게 최적화에 대해서도 생각해볼 수 있었다. 보통 css 작업을 할 때 margin이나 padding을 남발하는 것은 좋지 않다는 이야기를 많이 들었지만 구체적으로 왜 남발하지 말라는 이야기는 못들었었다. 오늘 공부를 하고 나서야 이유를 알게 되었다.


아까 배운 Reflow(또는 Layout)가 발생하는 이유는 요소의 크기나 위치등이 변경되었을 때 Reflow 발생이 일어난다고 하였다.


그렇다면 대표적으로 어떤 속성들이 Reflow를 발생시킬까? 그리고 다음과 같은 속성들을 최소화로 사용하면 최적화에 영향을 준다.

Reflow 대표적인 속성

position, margin, padding, border, float….



그러면 RePaint 과정에서도 최적화를 할 수 있다. RePaint는 색상이나 그림자가 변경될 때 RePaint가 일어난다고 했었다. 그렇다면 대표적인 속성으로는 어떤 것들이 있을까?

RePaint 대표적인 속성

background, background-color, background-repeat, background-position…


자바스크립트와 CSS를 조합해서 애니메이션이나 레이아웃 변화가 많은 요소에 position을 absolute 또는 fixed를 사용하면 영향을 받는 노드들을 줄일 수 있다고 한다. 그 이유는 Reflow과정은 전혀 없고 RePaint과정만 있기 때문이라고 한다.


마지막으로 프레임을 줄여서 성능을 개선할 수 있다고 한다. 0.1초마다 1px씩 이동하는 것 보다는 0.3초마다 3px씩 이동하는 요소가 Reflow 연산비용이 3배나 줄어든다고 한다. 이 부분은 처음 들었던 내용이라 정말 신선했다.





참고 자료

브라우저는 웹페이지를 어떻게 그리나요?
브라우저 렌더링과 최적화