브라우저 렌더링

브라우저

브라우저의 구성 요소

img

이미지 출처 https://donkeyhotel.tistory.com/1040


  • User Interface : 주소표시줄, 뒤로/앞으로 가기 버튼, 북마크 메뉴 등
  • Browser Engine : 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어
  • Rendering Engine : HTML과 CSS를 파싱하여 화면에 표시
  • Networking : HTTP 요청과 같은 네트워크 호출 담당
  • JS Engine : 자바스크립트 코드를 해석하고 실행
  • UI Backend : 콤보 박스, 확인란, 창 같은 핵심 위젯을 그림.
  • Data Storage : 쿠키, 로컬스토리지 등의 자료가 저장되는 저장소

렌더링 엔진의 동작 원리

post-thumbnail

이미지 출처 - velog.io/@leedocs


1) DOM 트리 생성

  • 클라이언트가 요청(request)한 HTML 파일을 서버가 응답(response)하면, 브라우저 렌더링 엔진은 HTML파일을 파싱하여 Object Model로 만든다.
  • HTML 마크업은 여러 태그 간의 포함관계가 있기 때문에 생성된 객체는 트리 데이터 구조로 만들어진다.
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="style.css" rel="stylesheet">
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
  </body>
</html> 

DOM 트리

이미지 출처 - Google 개발자 문서


2) CSSOM 생성

  • HTML 파일을 읽다가 보면 head 태그 내에 링크된 외부 CSS 파일을 만나면, 이 리소스에 대한 요청을 발송하여 CSS 규칙을 수신한다.
  • DOM 트리를 생성하는 것과 동일한 과정으로 CSSOM 트리를 생성한다.

    DevTools에서 CSSOM 생성 추적

이미지 출처 - Google 개발자 문서


3) 렌더링 트리 (Rendering Tree) 생성

  • DOM 트리와 CSSOM 트리를 결합해서 렌더링 트리 생성
  • 렌더링 트리에는 페이지를 렌더링하는데 필요한 노드만 포함된다 = 우리 눈에 보이는 것만 그려진다

    • script 태그, meta 태그 등은 렌더링된 출력에 반영되지 않으므로 생략됨
    • css에서 ‘display: none’ 처리된 노드는 빠지게 됨
    • 반면 ‘visibility: invisible’ 처리된 노드는 공간은 차지하고 요소가 보이지만 않는 것이기 때문에 렌더트리에 포함됨

img

이미지 출처 - Google 개발자 문서


4) 레이아웃 (Layout) 단계

  • 기기의 viewport(그래픽이 표시되는 브라우저의 영역) 내에서의 노드의 정확한 위치와 크기를 계산한다.
  • %, vh, vw 등의 상대적인 위치/크기 속성이 실제 화면에 그려지는 절대적 픽셀값으로 변환된다.

레이아웃 정보 계산

이미지 출처 - Google 개발자 문서


5) 페인팅 (Painting) 단계

  • 렌더링 트리의 각 노드를 화면에 실제 픽셀로 변환해서 나타낸다.
  • 이 때 텍스트, 색, 이미지, 그림자 효과 등이 모두 처리된다.

6) Reflow / Repaint

  • 사용자가 다양한 액션을 수행하면서 발생되는 이벤트로 인해 새로운 HTML 요소가 추가되거나 스타일이 바뀌는 등의 변경이 일어날 수 있다.
  • Reflow가 일어나는 대표적인 경우는 다음과 같다.

    • 페이지 최초 렌더링
    • 윈도우 리사이징 (viewport 크기 변경)
    • 노드 추가 또는 제거
    • 요소의 위치, 크기 변경
    • 폰트 변경, 이미지 크기 변경 등
  • 이러한 변경을 통해 영향을 받게 되는 모든 노드에 대해서 렌더링 트리 생성레이아웃 과정을 다시 수행하게 되는데, 이를 Reflow라고 한다.

    Reflow 가 일어나는 대표적 속성들

    position, width, height, margin, padding, border, border-width, font-size, font-weight, line-height, text-align, overflow

  • Reflow의 결과를 다시 화면에 그리는 것을 Repaint 라고 한다.

    • 레이아웃의 변경 없이 단순한 색상 변경 같은 경우는 Reflow 없이 바로 Repaint만 수행된다.

    Repaint 가 일어나는 대표적 속성들

    background, color, text-decoration, border-style, border-radius


렌더링 최적화

1) Critical Rendering Path 최적화

CRP(중요 렌더링 경로)란, 브라우저가 페이지의 초기 출력을 위해 실행해야 하는 순서 (HTML, CSS, JavaScript를 화면에 픽셀로 변환하는 일련의 단계)를 말한다.

브라우저가 HTML을 DOM 트리로 변환하기 위해 파싱을 시작할 때, stylesheet / script 등의 외부 자원에 대한 링크를 찾을 때마다 해당 자원에 대한 요청을 시작하고, 불러온 자원을 다 처리할 때까지 나머지 HTML을 분석하는 작업이 중단된다.

이처럼 HTML 파싱을 차단하는 CSS, 자바스크립트 리소스를 블록 리소스라고 한다.

  • CSS를 로드하는 <link> 또는 <style> 태그는 <head> 태그 안에 둔다

    • 페이지가 처음 로드되면 HTML과 CSS가 동시에 파싱되기 시작하는데, CSS가 head 태그 내에 빨리 선언되어 있어야 빠른 first meaningful paint를 할 수 있게 된다.
    • 문서 최하단에 stylesheet를 두면 이러한 점진적 렌더링이 불가능하다.
  • 자바스크립트를 로드하는 <script> 태그는 <body> 맨 하단에 둔다.

    • script 태그를 만날 때까지의 HTML을 먼저 파싱하여 사용자에게 표시할 수 있다.
    • 모든 DOM 요소가 생성된 후 스크립트 다운로드가 시작되어야 DOM 요소를 조작하는 자바스크립트 코드가 오류를 발생시키는 것을 막을 수 있다.

2) CSS 최적화

지금까지 css를 제대로 공부하고 최적화를 염두에 두며 코딩한 적이 한번도 없어서… 이 부분은 더 공부한 후에 수정해야 할 것 같다 ㅠㅠ 우선 현재까지 알아본 바로는 다음과 같다.

  • media 속성을 사용하여 필요한 경우에만 CSS가 로드될 수 있도록 하여 불필요한 블로킹을 방지한다.
<link rel="stylesheet" href="main.css" />
<link rel="stylesheet" href="print.css" media="print" />
<link rel="stylesheet" href="mobile.css" media="screen and (max-width: 480px)" />
  • Reflow가 발생하는 속성보다 Repaint만 발생하는 CSS 속성을 사용하여 렌더링 트리 생성 및 레이아웃이 재발생하는 것을 막는다.

    • width, height 대신 → transform : scale()
    • top, right, bottom, left 대신 → transform : translate()



참고한 자료


Written by@[hyem]
Hyem's Dev Note

GitHub