브라우저 렌더링 과정과 최적화 방법

Noma·2021년 9월 7일
1

1. 브라우저

브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 브라우저에 표시하는 것이다.

여기서 자원이란? 보통 HTML 문서를 말한다. (+ PDF나 이미지 등 다른 형태도 O) → 자원의 주소는 URI(Uniform Resource Identifier)에 의해 정해짐

브라우저는 HTML과 CSS 명세에 따라 HTML 파일을 해석해서 표시한다. → 명세는 웹 표준화 기구인 W3C에서 정함

브라우저의 기본 구조

  1. 사용자 인터페이스 - 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등 페이지 뷰 이외의 다른 모든 부분
  2. 브라우저 엔진 - 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어
  3. 렌더링 엔진 - HTML, CSS를 파싱해 요청한 콘텐츠를 표시
  4. 통신 - HTTP 요청과 같은 네트워크 호출에 사용됨
  5. UI 백엔드 - 기본적인 위젯(콤보 박스 등)을 그림
  6. 자바스크립트 엔진 - 자바스크립트 코드를 해석하고 실행.
  7. 자료 저장소 - 자료를 저장하는 계층으로 쿠키 등을 저장하는 웹 데이터베이스

2. 렌더링 엔진

렌더링 엔진은 요청 받은 내용을 브라우저 화면에 표시하는 역할을 한다.
브라우저마다 사용하는 렌더링 엔진이 다름 → 크로스 브라우징 이슈가 발생하곤 한다.

파이어폭스 - 게코(Gecko)
사파리 - 웹킷(Webkit)
크롬 - 블링크(Blink)

2.1 동작 과정

(통신으로부터 요청한 문서의 내용을 얻는 것부터 시작한다.)

1. DOM(Document Object Model), CSSOM(CSS Object Model) 생성 (Parsing)

브라우저가 렌더링할 문서인 HTML과 CSS를 나눠서 읽는다. 이때 HTML과 CSS는 단순한 텍스트이므로 HTML Parser와 CSS Parser로 각각 연산과 관리가 가능한 Object Model을 만든다.

(여기서 렌더링 엔진은 더 나은 사용자 경험을 위해 가능한 빠르게 내용을 표시하게 만들어졌는데, 따라서 모든 HTML, CSS파싱이 끝나기도 전에 이후의 과정을 수행하여 미리 사용자에게 보여줄 수 있는 내용들을 출력한다.)

2. 렌더 트리 구축 (Attachment)

전 단계에서 DOM 트리와 CSSOM 트리가 생성되면, 이 둘을 연결하여 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 생성한다.

이는 순수한 요소들의 구조와 텍스트만 존재하는 DOM 트리와 달리 렌더 트리는 스타일 정보가 설정되어 있으며 실제 화면에 표현되는 노드들로만 구성된다.

display:none; 과 같은 속성이 설정된 노드는 제외된다.

3. 렌더 트리 배치 (Layout or Reflow)

렌더 트리가 생성되면 브라우저의 뷰포트 내에서 각 노드들의 정확한 위치와 크기를 계산한다. 이때 %, vh, vw와 같이 상대적인 위치, 크기 속성은 모두 실제 화면에 그려지는 px단위로 변환된다.

4. 렌더 트리 그리기 (Paint)

Layout 과정이 완료되면 요소들의 위치와 크기, 스타일 계산이 완료된 렌더 트리를 사용해 브라우저는 요소들을 실제 화면에 그리게 된다.

이때 처리해야 하는 스타일이 복잡할 수록 시간이 오래 걸린다.

3. 브라우저의 렌더링 과정 정리

  1. 사용자가 브라우저 주소창에 URL 입력한다.
  2. DNS 서버가 입력된 도메인 네임을 실제 서버 주소인 IP주소로 바꿔준다.
  3. http인지 https인지에 따라 해당 통신 방식으로 서버에 요청한다.
  4. 서버의 기본 설정이 대부분 index.html로 되어있어 서버에서 이 파일을 클라이언트로 보내준다.
  5. 브라우저는 텍스트로 이루어진 index.html 파일을 html parser로 파싱하여 DOM tree 만든다.
  6. 중간에 css파일에 대한 link 태그를 만나면 다시 서버에 요청/응답 과정을 거쳐서 css파일을 가져온다.
  7. css parser로 css파일을 파싱하여 CSSOM tree를 만든다.
  8. 완성된 DOM tree와 CSSOM tree를 합쳐서 Render 트리를 만든다.
  9. 이후 노드를 어느 위치에 얼마나 크게 표기할 건지 계산하는 과정(Layout)을 거쳐 화면에 그린다(Paint).
  10. javascript의 경우, html parser가 중간에 script 태그를 만나면 html 파싱을 중단한다.
  11. 제어 권한을 자바스크립트 엔진에게 넘기고 javascript 파일을 로드해서 파싱하고 실행한다.

(이는 script 태그에 어떠한 옵션도 쓰이지 않았을 경우에 해당한다. 만약 script 태그에 defer 옵션이 쓰였다면 html 파싱을 중단하지 않고 병렬적으로 js 파일을 받아온다. 그리고 html 파싱이 끝나면 fetch 해둔 js 파일을 실행한다.)

4. Reflow와 Repaint

렌더링 과정을 모두 마친 후 최종적으로 브라우저에 페이지가 그려진다고 해서 렌더링 과정이 모두 끝난 것이 아니다. 특정 액션이나 이벤트에 따라 HTML 요소의 크기나 위치 등 레이아웃 수치가 수정되면 그에 영향을 받는 자식 노드나 부모 노드들을 포함하여 Layout 과정을 다시 수행하게 된다.(Reflow) 그리고 그 결과물을 다시 화면에 그려주는 Repaint 과정을 거친다.

4.1 Reflow가 일어나는 대표적인 예시

  • 페이지 초기 렌더링 시
  • 브라우저 리사이징 시
  • 노드 추가 또는 제거
  • 요소의 위치, 크기 변경
  • 폰트 변경과 이미지 크기 변경

4.1 Repaint가 일어나는 대표적인 예시

reflow가 일어나면 실제 화면에 반영해주기위해 다시 painting이 일어난다.

그러나 항상 reflow가 발생해야 repaint되는 건 아니다. background-color, opacity처럼 레이아웃에 영향을 주지 않는 스타일 속성의 변경은 repaint만 일어난다.

5. 렌더링 최적화 하기

5.1 Reflow와 Repaint 최소화

reflow가 발생하는 속성보다 repaint만 발생하는 속성을 사용하는 것이 좋다.

🔔 reflow가 일어나는 대표적인 속성
position, width, height, left, top, right, bottom, margin, padding, border, border-width, clear, display, float, font-family, font-size, font-weight, line-height, min-height, overflow, text-align, vertical-align, white-space...

🔔 repaint가 일어나는 대표적인 속성
background, background-image, background-position, ackground-repeat, background-size, border-radius, border-style, box-shadow, color, line-style, outline, outline-color, outline-style, outline-width, text-decoration, visibilty...

5.2 영향을 주는 노드 최소화하기

애니메이션이나 레이아웃 변화가 많은 요소의 경우 position을 absolute나 fixed를 사용하면 영향을 받는 주변 노드들을 줄일 수 있다.

fixed는 주변에 영향을 주지 않아 repaint 비용만 들어서 효율적이다.

5.3 프레임 줄이기

예를 들어 0.1초 마다 1px씩 이동하는 요소보다 0.3초마다 3px씩 이동하는 요소가 reflow 연산 비용이 3배 줄어든다고 볼 수 있다. 따라서 부드러운 효과를 조금 줄이면서 성능을 개선할 수 있다.

5.4 CSS will-change 속성 사용하기

페인트 과정은 요소들이 어떻게 배치되었는가에 따라 작게 나누어 레이어별로 비트맵을 준비한다. 렌더링 이후 변화가 일어날 것 같은 요소에 will-change: 속성이름을 해주면 그 요소는 레이어를 따로 준비해줘서 추후 발생할 변화에 대해 다른 노드에 줄 영향을 없앨 수 있다. (단, will-change를 남발하면 안된다.)


Reference

https://d2.naver.com/helloworld/59361
https://chanyeong.com/blog/post/43

profile
Frontend Web/App Engineer

0개의 댓글