Blog

Read

How Browsers Work

Nov 8, 2020

사용자가 브라우저 주소창에 주소를 입력(url)했을 때, 화면에 보여지게 되는 일련의 과정들이 있습니다.

브라우저는 주소를 통해 서버에 request를 보내고 응답으로 resource를 내려받고, HTML데이터를 받아 로딩과정을 거쳐 화면을 보여줍니다.

브라우저 로딩과정 : 웹 페이지에 필요한 리소스를 내려받고, 해석후 계산 화면에 보여주는 과정

Parsing


  • 브라우저 에서 웹페이지를 로드하면 HTML 파일을 다운로드 합니다.

  • HTML을 해석(파싱) DOM 트리를 구성합니다

  • 파싱 중 <script /> <link /> <img /> 를 만나면 리소스를 요청하고 다운로드 합니다.
  • JS파일을 만나면 해당 파일을 받아와서 실행할때 까지 파싱이 멈춥니다.
  • 위 같은 문제를 막기위해, body 최하단에 script 를 위치하게 합니다.
  • HTML 또는 리소스에 CSS가 포함될 경우, CSSOM트리 작업도 함께 진행합니다.
  • CSSOM을 구성하는 것이 끝나야, 비로소 이후의 Rendering 과정을 시작할 수 있습니다.
  • HTML 및 CSS는 둘다 렌더링 차단 리소스 입니다

Render Tree


DOM 노드를 어떻게 표시할 지 나타낸 것입니다.

파싱 단계에서 생성된 DOM, CSSOM 트리를 가지고 스타일을 매칭시켜주는 과정을 거쳐 렌더 트리를 구성합니다. 렌더 트리는 화면에 실제로 '보이는' 친구들만으로 이루어집니다.

display : none 과 같은 설정은 Render Tree에 추가되지 않습니다.

요소의 테두리 두께를 바꾸거나 문단에 텍스트를 추가해서 줄이 늘어나는 등 요소의 기하학적 구조(너비와 높이)에 영향을 미치도록 DOM이 변경되면 브라우저는 변경된 요소의 기하학적 구조를 다시 계산해야 하고, 이에 영향을 받는 다른 요소의 기하학적 구조와 위치도 다시 계산해야 합니다.


브라우저는 렌더 트리 중에서 변경에 영향을 받은 부분을 유효하지 않은 것으로 간주하고 렌더트리를 다시 만듭니다. 이러한 과정을 리플로우라고 합니다. 리플로우 가 끝나면 브라우저는 영향을 받은 부분을 다시 그리는데 이를 리페인트 라고 합니다.


background color를 바꾸는 등의 변경은 기하학적 요소에 영향을 주지 않습니다. 즉, 요소의 레이아웃이 변하지 않으므로, 리플로우는 일어나지 않고 리페인트 만 일어나게 됩니다.

리플로우와 리페인트는 많은 비용이 드는 작업이며 웹 어플리케이션에 UI 반응이 떨어질 수 있습니다. 따라서 이러한 일이 적게 일어나도록 하는것이 최선입니다.


Reflow


리플로우가 일어날 때

  • 보이는 DOM 요소를 추가 / 제거 했을 때
  • 요소의 위치가 바뀌었을 때
  • 요소의 크기(마진, 패딩, 테두리 두께, 너비, 높이 등) 가 바뀌었을 때
  • 텍스트 내용이 바뀌거나 이미지가 다른 크기의 이미지로 대체되는 등 내용이 바뀌었을 때
  • 페이지를 처음 표시할 때
  • 브라우저 창의 크기를 바꿨을 때

Optimization Reflow


리플로우마다 다시 계산을 하게 되면 많은 비용이 들기 때문에, 대부분 브라우저 자체적으로 렌더 트리 변경을 큐에 모았다가 한번에 처리하는 식으로 처리하여 최적화 합니다. 하지만, 이 큐를 비우고 예약된 모든 변경을 강제 반영하는 메서드들이 있습니다.

  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop, scrollLeft, scrollWidth, scrollHeight
  • clinetTop, clinetLeft, clinetWidth, clinetHeight
  • getComputedStyle()

이 속성들은 렌더링 큐에서 변경을 바로 실행하여 리플로우를 실행합니다. 따라서 스타일을 바꾸는 도중에는 위 속성을 쓰지 않는것이 최선입니다.


React, it batches the changes and call applies them on real-dom in one go. Thus, minimizing the re-flow and re-paint.

Layout


레이아웃 단계에서는 노드의 정확한 위치와 크기를 계산합니다.

노드의 정확한 크기와 위치를 파악하기 위해 루트부터 노드를 순회하면서 계산하고, 레이아웃 결과로 각 노드의 정확한 위치와 크기를 픽셀값으로 렌더트리에 반영합니다. 만약 CSS에서 크기 값을 %로 지정하였다면, 레이아웃 단계를 거친 후 % 값은 계산되고 측정 가능한 픽셀 단위로 변환됩니다.

뷰포트를 기준으로 실제로 놓으려면 얘가 어디에 가야하는 지는 계산

Paint


이전 레이아웃 단계에서 계산된 값을 이용해 렌더트리의 각 노드를 화면상의 실제 픽셀로 변환합니다. 이때 위치와 관계없는 CSS 속성(색상, 투명도 등)을 적용합니다. 그리고 픽셀로 변환된 결과는 포토샵의 레이어처럼 생성되어 개별 레이어로 관리됩니다. 단, 각각의 엘리먼트가 모두 레이어가 되는 것은 아닙니다. transform 속성 등을 사용하면 엘리먼트가 레이어화 되는데, 이 과정을 페인트라고 합니다.


Composite & Render


페인트 단계에서 생성된 레이어를 합성하여 스크린을 업데이트 합니다. 합성과 렌더 단계가 끝나면 화면에서 웹 페이지를 볼 수 있습니다.