브라우저는 어떻게 동작하는 걸까?

RookieAND·2023년 1월 21일
0

Solve My Question

목록 보기
7/27
post-thumbnail

📖 Introduction

브라우저가 어떻게 일하는지 도 모르면서, 브라우저를 쓰려고 해?

프론트엔드 기술 면접의 단골 질문, 브라우저는 어떻게 서버에서부터 받은 리소스를 화면에 렌더링할까요? 이다. 사실 지금까지 내가 봤던 기술 면접 중에서는 아직 이 질문을 받은 적이 없지만.. (비교적 더 어려운 질문들이 많았다 젠장) 그래도 내심 궁금한 건 사실이었다. 대체 브라우저는 어떻게 이루어졌길래 이렇게 다양한 컨텐츠들을 문제없이 착착 보여줄 수 있는 걸까?

그래서 이번 기회에 Webkit 엔진의 CRP(Critical Rendering Path) 과정과 브라우저의 구성 요소들을 한번 훑어보기로 했다.

✒️ Browser

1. 브라우저의 주요 기능.

  • 브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 (request) 이를 표시하는 것이다.
  • 자원의 경우 보통 HTML 문서를 의미하지만, 이미지나 비디오, 문서 같은 바이너리 데이터일 수도 있다.
  • 자원의 주소는 URL에 의해 정해진다. REST 아키텍쳐에서 나오는 자원의 식별자를 URL로 하기 때문이다.
  • 브라우저는 W3C에서 표준화한 HTML과 CSS 명세에 따라 이를 파싱하여 렌더링을 진행한다.

2. 브라우저의 기본 구조

  1. 사용자 인터페이스
    • 주소 표시줄, 이전 / 다음 버튼, 북마크 메뉴 등 요청한 페이지를 제외한 나머지 UI를 의미.
  2. 브라우저 엔진
    • 사용자 인터페이스 (UI) 와 렌더링 엔진 사이의 동작을 제어한다.
  3. 렌더링 엔진
    • 사용자가 요청한 컨텐츠를 브라우저 화면에 나타내게 해주는 기능을 함.
    • HTML 파일을 요청했다면 HTML과 CSS를 파싱하여 렌더 트리를 만들고, 이를 기반으로 렌더링을 진행함.
    • Chrome의 Webkit, Mozilla 의 Gecko 엔진이 대표적이다.
  4. 통신
    • HTTP, FTP 같은 표준 프로토콜을 사용한 네트워크 호출에 사용된다.
  5. UI 백엔드 : 일반적으로 창이나 콤보 박스 같은 기본적인 위젯을 그리기 위해 쓰임.
  6. JS 인터프리터
    • JS 코드를 파싱하고 바이트 코드로 변환하여 실행 가능하도록 하는 인터프리터
    • Chrome의 V8 엔진이 가장 대중적으로 쓰이는 엔진이다.
  7. 자료 저장소
    • 로컬 스토리지, 쿠키, IndexedDB 같은 저장 메커니즘을 지원하는 저장소.
    • 브라우저가 데이터를 저장해야 할 필요가 있을 경우 사용하는 지속성 레이어.

✒️ Rendering Engine

1. 렌더링 엔진은 어떻게 동작하는가?

  • Chrome에서 쓰이는 Webkit 렌더링 엔진을 기준으로 작성하였다.
  • 위 과정은 1 ~ 4번까지 점진적으로 진행된다.
  • 단, 사용자 경험을 위해 모든 HTML을 파싱하지 않고 일부에 대한 Layout, Paint 작업을 먼저 시행할 수 있다.
  • 이러한 일련의 과정을 CRP(Critical Rendering Path) 이라고 부른다.
  1. 서버로부터 받은 HTML을 파싱하여 DOM, CSSOM 트리를 생성한다 (Parsing)

    • 렌더링 엔진은 HTML 문서를 파싱하고, 컨텐츠 트리 내부에서 태그를 DOM 노드로 변환한다.
    • HTML 내에 CSS가 포함되었다면, 이 또한 CSSOM으로 변환하여 트리를 구성한다.
    • Link 태그를 만나 CSS 요청이 발생했을 경우, 별도의 요청을 보내 받은 CSS를 파싱한다.
    • script 태그를 만나 외부로부터 번들링된 JS 파일을 받아야 할 경우, 파싱 작업은 중단된다.
    • JS는 parser 의 작업을 막는 리소스지만, defer 속성과 async 속성에 따라 차이점이 발생한다.
  2. 두 트리를 매칭시켜 화면에 보여줄 요소들에 대한 렌더 트리를 생성한다. (Attachment)

    • DOM 트리와 시각 정보가 담긴 CSSOM 트리를 매칭시켜 실제 화면에 그려질 렌더 트리를 생성한다.
    • 렌더 트리는 색상, 또는 면적과 같은 시각적 속상이 있는 요소들만 포함하여, 정해진 순서대로 화면에 표시된다.
    • visibility: hidden, opacity : 0 의 경우에는 화면 상에서 보여지지 않을 뿐 실제로 요소가 존재하므로 트리에 포함시킨다.
    • display: none 의 경우 실제로 요소를 화면에서 제외시키기 때문에 렌더 트리 구성에서 제외된다.
    • meta, script, head 태그와 같이 사용자에게 보이지 않아도 되는 노드는 트리 구성에서 제외된다.
  3. 렌더 트리의 요소를 순회하며 각 요소들을 화면에 어떻게 배치시킬지 정한다. (Layout)

    • 루트 노드부터 순회하며 각 노드들의 정확한 크기와 위치를 계산하여 반영한다.
    • % 이나 rem, vh 같은 단위로 설정되었다면, 이를 정확한 픽셀 값으로 변환시킨다.
  4. 배치가 완료되었다면, 트리의 각 노드들을 화면 상의 실제 픽셀로 변환시킨다. (Paint)

    • 계산된 값을 활용하여 렌더 트리의 각 노드를 실제 화면상의 픽셀들로 변환시킨다.
    • 픽셀로 변환된 값은 여러 개의 레이어로 관리되며, 스타일이 복잡할수록 Paint 과정에 소요되는 시간도 증가한다.
    • 해당 과정의 경우 UI 백엔드 파트에서 각 노드를 가로지르며 형상을 그려낸다.

왜 script 태그는 DOM의 파싱을 중단시킬까? CSS는 중단시키지 않던데?

  1. JS
  • JavaScript는 기본적으로 파서 차단 리소스 (parser blocking resource) 이다.
  • 왜냐하면 JS의 DOM API의 경우, 파싱을 통해 생성된 DOM Tree를 변경시킬 수 있기 때문이다.
  • 하지만 JS에서 요구하는 DOM 요소나 스타일 요소가 아직 파싱되지 않았다면 오류를 일으킨다.
  • 이 때문에 <script> 태그의 경우에는 주로 body 태그의 가장 아래에 위치시키는 것이다.
  1. CSS
  • CSS의 경우에는 기본적으로 렌더링 차단 리소스(render blocking resource) 이다.
  • 왜냐하면 CSS는 화면을 렌더링 하기 위해서는 필수적으로 사용되는 리소스이기 때문이다.
  • 따라서 브라우저는 빠르게 CSS를 받는 것이 좋으며, 보통 head 태그 내부에 <link> 태그를 넣는다.

2. async, defer 속성의 차이점에 대해 보자.

  1. 공통점

    • 기본적으로 parser는 script 태그를 만나면 파싱 작업을 중단하고 다운로드를 진행한다.
    • 하지만 defer, async 속성의 경우 JS 파일의 다운로드와 파싱 작업을 병행하도록 한다.
  2. 차이점

  • defer
    • 문서 파싱과 JS 다운로드를 동시에 진행하지만, parser가 문서를 온전히 읽은 후에 스크립트를 실행한다.
    • DOM 요소를 조작해야 하거나, 스크립트 간의 의존성이 존재한다면 defer를 사용하자.
  • async
    • 문서 파싱과 JS 다운로드를 동시에 진행하고, 다운로드가 완료되는 즉시 스크립트를 실행한다.
    • 스크립트가 실행되는 동안 파싱 작업은 잠시 중단되며, 실행이 끝난 후에 문서 파싱 작업을 재개한다.
    • 스크립트가 실행되었으나 이를 참조할 DOM이 아직 파싱되지 않았다면 문제가 발생한다.
    • DOM을 조작하지 않고, 스크립트 간의 의존성이 없이 독자적으로 작동하는 경우에만 사용하자.

✒️ 최신 브라우저에서 추가된 작업들

1. Update Layer Tree

  • 브라우저 렌더링 과정에서 생성되는 Render Tree를 활용하여 화면에 표시될 레이어를 생성함.
  • Layout 과정 이후 실행되며, Paint Layer와 Graphic Layer로 나누어 레이어를 생성하게 됨.

1-1. Paint Layer는 무엇을 의미하는가?

  • 웹페이지를 렌더링 하기 위해 필요한 이미지 단위 요소이다.
  • 각 DOM 요소, 즉 Render Object는 화면에 보다 효율적으로 요소들을 나타내기 위해 레이어 형태로 구성되는데, 이것이 Paint Layer다.
  • 생성된 Paint Layer를 하나로 합성시키면 최종적으로 렌더링 과정이 완료된다.
  • 일반적으로 동일한 좌표 공간을 가지는 Render Object 들은 같은 Paint Layer에 위치한다.
  • 하지만 일부 상황에서는 추가적으로 Layer를 생성하여 별도의 공간을 마련하고, 여기에 요소들을 넣는다.
1. 명시적인 position 속성을 가진 경우 (relative, fixed, absolute..)
2. opacity가 1 미만인 경우
3. Root Element인 경우 (이 경우 Root Layer를 생성함.)
4. filter, mask, transform, mix-blend-mode 속성을 가진 경우.
등등..

1-2. Graphic Layer는 무엇인가?

  • Paint Layer에서 더 나아가 실제로 화면에 띄워질 요소들의 출력을 GPU에게 위임할 수 있음.
  • GPU에게 처리 권한을 위임하여 새롭게 생성해낸 레이어를 Graphic Layer라고 명명함.
  • 본래 브라우저 렌더링의 경우 CPU가 처리하나, GPU가 만든 Graphic Layer를 묶어 하나의 이미지를 만드는 것을 하드웨어 가속이라 함.
  • 아래의 경우 Graphic Layer가 생성되며, 하드웨어 가속이 진행됨.
1. 하드웨어 가속 플러그인을 사용하는 경우
2. video나 canvas 태그를 사용하는 경우
3. 하드웨어 가속이 된 2D canvas 요소인 경우
4. 3D transform 속성이 존재하는 경우
5. transition, animation 속성이 있는 경우
등등...

1-3. 왜 GPU에게 렌더링 과정을 위임하는가?

  • 궁극적인 목적은 렌더링을 더욱 빠르게 진행하기 위함이다.
  • 게임, 3D 와 같이 대규모 연산을 필요로 하는 작업에는 GPU가 적합하기 때문이다.
  • 기존의 CPU에서 처리했던 요소들을 일부 GPU에게 위임하여 기존 대비 빠른 렌더링 속도를 가지기 위함.

1-4. 언제 하드웨어 가속을 처리하는 것이 좋은가?

  • 일반적으로 Render Tree를 구성하는 특정 노드가 주변의 노드보다 렌더링이 빨라야 할 경우 사용된다.
  • video 태그의 경우 매번 변하는 이미지를 화면에 띄워야 하기에 별도로 처리되어야 한다.
  • 3D transform의 경우에도 별도의 레이어에서 애니메이션 처리를 진행하는 것이 더욱 효율적이다.
  • 하지만, 기본적으로 하드웨어 가속을 사용하면 레이어를 분리하여 생성하기에 추가적인 메모리가 발생한다.
  • 또한 CPU에서 GPU로 처리할 데이터를 보내야 하기 때문에 이 과정에서 시간이 소요될 수 있다.
  • GPU의 VRAM이 부족할 경우 정상적인 처리가 어려워지기에 일부 기기에서는 하드웨어 가속을 막아야 한다.

2. Composite

  • 생성된 Paint Layer 들을 하나의 비트맵으로 합성시켜주는 과정.

✒️ Reflow, Repaint

1. Reflow란 무엇인가?

  • Layout 작업을 다시 진행하는 것을 Reflow 라고 부른다.
  • 렌더 트리의 모든 요소에 대한 위치와 크기를 다시 계산해야 하기에 비용이 크다.
  • 아래의 작업이 진행되었다면 브라우저에서 Reflow가 발생한다.
    • DOM 요소 추가, 제거 및 변경
    • CSS 스타일 추가, 제거 및 변경
    • 특정 엘리먼트에 클래스를 추가.
    • CSS 애니메이션과 트랜지션, 애니메이션 내의 모든 프레임에서 발생.
    • 엘리먼트의 크기에 대한 offsetWidth와 offsetHeight 속성을 읽었을 경우.
    • 유저 인터렉션에 의한 Hover 효과, 필드에 텍스트 입력, 창 크기 조정, 글꼴 전환 등.

2. Repaint란 무엇인가?

  • Paint 작업을 다시 진행하는 것을 Repaint 라고 한다.
  • 변경된 시각적 요소를 적용하여 Paint 작업만 진행하므로 비용이 상대적으로 적다.
  • 아래의 작업이 진행되었다면 브라우저에서 Repaint가 발생한다.
    • 가시성과 관련된 CSS 스타일 요소가 변경될 경우 (visibility, opacity)
    • Reflow 가 호출된 직후에 Repaint가 진행된다. Layout 작업 후에는 Paint 작업이 무조건 진행되기 때문이다.
profile
항상 왜 이걸 써야하는지가 궁금한 사람

0개의 댓글