d2.naver.com Open in urlscan Pro
175.158.5.161  Public Scan

Submitted URL: http://d2.naver.com/helloworld/5237120
Effective URL: https://d2.naver.com/helloworld/5237120
Submission: On April 15 via manual from US — Scanned from DE

Form analysis 3 forms found in the DOM

/

<form action="/" style="height: 0px; transition: all 0.5s ease 0s;"><input type="text" value="" placeholder="D2에서 검색" class="search_area"><button type="sunmit" class="blind"><i class="xi-search"></i></button></form>

/

<form action="/"><input type="text" value="" placeholder="D2에서 검색" class="search_area"><button type="sunmit" class="btn_search"><i class="xi-search"></i></button></form>

<form>
  <fieldset>
    <legend class="u_vc">댓글 쓰기</legend>
    <div class="u_cbox_write" data-focus="write#beforeClickWriteBox">
      <div class="u_cbox_write_inner">
        <div class="u_cbox_write_area"><strong class="u_vc">댓글 입력</strong>
          <div class="u_cbox_inbox"><textarea title="댓글" id="cbox_module__write_textarea" class="u_cbox_text" rows="3" cols="30" data-log="RPC.input"></textarea><label for="cbox_module__write_textarea" class="u_cbox_guide"
              data-action="write#placeholder" data-param="@event">댓글을 작성하려면 <a href="#" class="u_cbox_link">로그인</a> 해주세요</label></div>
        </div>
        <div class="u_cbox_upload_sticker " style="display:none"></div>
        <div class="u_cbox_write_count"><span class="u_vc">현재 입력한 글자수</span><strong class="u_cbox_count_num">0</strong>/<span class="u_vc">전체 입력 가능한 글자수</span><span class="u_cbox_write_total">400</span></div>
        <div class="u_cbox_upload">
          <div class="u_cbox_addition"></div><button type="button" class="u_cbox_btn_upload" data-action="write#request" data-log="RPC.write#RPC.reply#RPC.rereply"><span class="u_cbox_ico_upload"></span><span
              class="u_cbox_txt_upload">등록</span></button>
        </div>
      </div>
    </div>
  </fieldset>
</form>

Text Content

NAVER D2

메뉴
 * Hello world
 * D2 News
 * D2 Program
 * About D2

검색

검색



최신 브라우저의 내부 살펴보기 3 - 렌더러 프로세스의 내부 동작

등록일2019.04.22||코멘트28902

이 글은 Google Developers 사이트에 공개된 Mariko Kosaka의 "Inside look at modern web
browser"(최신 브라우저의 내부 살펴보기) 시리즈를 번역한 글입니다. 이 시리즈는 Chrome을 중심으로 최신 브라우저를 들여다봅니다.
Chrome이 속도뿐만 아니라 안정성을 위해 어떤 아키텍처를 사용하는지 설명하는 것에서 시작해, 웹 페이지가 어떤 단계를 거쳐 화면에 그려지는지
설명합니다. 이와 더불어 성능 향상을 위해 웹 개발자가 고려하면 좋을 사항도 다룹니다.

시리즈의 세 번째 글인 "Inside look at modern web browser (part 3)"에서는 렌더러 프로세스가 HTML 문서를
받았을 때 어떤 절차를 거쳐 화면을 구성하는지 설명합니다. 이 과정을 효율적으로 처리하기 위해 렌더러 프로세스가 어떤 아키텍처를 가지고 있는지
살펴보고, 웹 개발자가 고려하면 좋을 내용을 소개합니다.

> 저작권
> 이 글의 원문은 다음과 같은 저작권 기준을 따릅니다.
> 
> Except as otherwise noted, the content of this page is licensed under the
> Creative Commons Attribution 3.0 License, and code samples are licensed under
> the Apache 2.0 License. For details, see our Site Policies. Java is a
> registered trademark of Oracle and/or its affiliates.




렌더러 프로세스의 내부 동작

이 글은 Chrome의 내부 동작을 살펴보는 "Inside look at modern web browser" 시리즈의 세 번째 글이다. 이전
글에서는 다중 프로세스 아키텍처와 내비게이션 과정에 대해 설명했다. 이 글에서는 렌더러 프로세스 내부에서 어떤 일이 일어나는지 살펴볼 것이다.

렌더러 프로세스는 여러 측면에서 웹 페이지의 성능에 영향을 끼친다. 렌더러 프로세스 내부에서 많은 일이 일어나기 때문에 이 글은 개요 수준의
일반적인 내용만을 다루겠다. 웹 페이지의 성능에 관해 더 깊이 알아보고 싶다면 Google Developers 사이트의 Web
Fundamentals 카테고리에서 Performance 항목의 글들을 참고한다.




렌더러 프로세스는 웹 콘텐츠를 처리한다

렌더러 프로세스는 탭 내부에서 발생하는 모든 작업을 담당한다. 렌더러 프로세스의 메인 스레드가 브라우저로 전송된 대부분의 코드를 처리한다. 간혹
웹 워커나 서비스 워커를 사용하는 경우에는 워커 스레드가 JavaScript 코드의 일부를 처리한다. 웹 페이지를 효율적이고 부드럽게 렌더링하기
위해 별도의 컴포지터 스레드와 래스터 스레드가 렌더러 프로세스에서 실행된다.

렌더러 프로세스의 주요 역할은 HTML과 CSS, JavaScript를 사용자와 상호작용을 할 수 있는 웹 페이지로 변환하는 것이다.



그림 1 메인 스레드와 워커 스레드, 컴포지터 스레드, 래스터 스레드가 있는 렌더러 프로세스




파싱




DOM 구축

페이지를 이동하는 내비게이션 실행 메시지를 렌더러 프로세스가 받고 HTML 데이터를 수신하기 시작하면 렌더러 프로세스의 메인 스레드는
문자열(HTML)을 파싱해서 DOM(document object model)으로 변환하기 시작한다.

DOM은 브라우저가 내부적으로 웹 페이지를 표현하는 방법일 뿐만 아니라 웹 개발자가 JavaScript를 통해 상호작용을 할 수 있는 데이터
구조이자 API이다.

HTML 문서를 DOM으로 파싱하는 방법은 HTML 표준에 정의되어 있다. 브라우저에서 HTML 문서를 열었을 때 오류를 반환받은 적이 없을
것이다. 예를 들어 닫는 </p> 태그가 누락된 HTML 도 유효한 HTML이다. Hi! <b>I'm <i>Chrome</b>!</i>와 같이
잘못된 마크업(<b> 태그가 <i> 태그보다 먼저 닫혔다)도 Hi! <b>I'm <i>Chrome</i></b><i>!</i>라고 쓴 것처럼
다뤄진다. 오류를 우아하게 처리하도록 HTML 명세가 설계됐기 때문이다. 이러한 일이 어떻게 처리되는지 궁금하다면 HTML 명세에서 "An
introduction to error handling and strange cases in the parser"(파서의 오류 처리 개요와 오류
사례)를 읽어 보길 바란다.




하위 리소스(SUBRESOURCE) 로딩

웹 사이트는 일반적으로 이미지, CSS, JavaScript와 같은 외부 리소스를 사용한다. 이러한 파일은 네트워크나 캐시에서 로딩해야 한다.
DOM을 구축하기 위해 파싱하는 동안 이런 리소스를 만날 때마다 메인 스레드가 하나하나 요청할 수도 있을 것이다. 하지만 속도를 높이기 위해
'프리로드(Preload) 스캐너'가 동시에 실행된다. HTML 문서에 <img> 또는 <link> 와 같은 태그가 있으면 프리로드 스캐너는
HTML 파서가 생성한 토큰을 확인하고 브라우저 프로세스의 네트워크 스레드에 요청을 보낸다.



그림 2 HTML을 파싱하고 DOM 트리를 만드는 메인 스레드




자바 스크립트가 파싱을 막을 수 있다

<script> 태그를 만나면 HTML 파서는 HTML 문서의 파싱을 일시 중지한 다음 JavaScript 코드를 로딩하고 파싱해 실행해야
한다. 왜 그럴까? JavaScript는 DOM 구조 전체를 바꿀 수 있는 document.write() 메서드와 같은 것을 사용해 문서의
모양을 변경할 수 있기 때문이다(HTML 명세의 "Overview of the parsing model"(파싱 모델 개요)에 있는 다이어그램이
이 상황을 잘 표현하고 있다). HTML 파싱을 재개하기 전에 HTML 파서는 JavaScript의 실행이 끝나기를 기다려야 한다.
JavaScript를 실행할 때 어떤 일이 발생하는지 궁금하다면 "JavaScript engine fundamentals: Shapes and
Inline Caches"(JavaScirpt 엔진의 기본: 형태와 인라인 캐시) 글의 영상과 내용을 참고한다.




리소스를 어떻게 로딩하길 원하는지 브라우저에 힌트를 주는 방법

웹 개발자가 브라우저에 리소스 로딩에 대한 힌트를 보내는 방법에는 여러 가지가 있다. JavaScript에서 document.write()
메서드를 사용하지 않는다면 <script> 태그에 async 속성이나 defer 속성을 추가할 수 있다. 이 속성이 있으면 브라우저가
JavaScript 코드를 비동기적으로 로딩하고 실행하면서 HTML 파싱을 막지 않는다. JavaScript 모듈을 사용할 수도 있다.
<link rel="preload">는 현재 내비게이션을 실행하기 위해 리소스가 반드시 필요하다는 것을 브라우저에 알려서 리소스를 가능한 한
빨리 다운로드하려는 경우에 사용할 수 있다. 브라우저에 힌트를 주는 방법에 관해 더 알고 싶다면 "Resource Prioritization –
Getting the Browser to Help You"(리소스 우선순위 지정 - 브라우저의 도움 받기)를 참고한다.




스타일 계산

DOM만으로는 웹 페이지의 모양을 알 수 없다. CSS로 웹 페이지 요소의 모양을 결정할 수 있기 때문이다. 메인 스레드는 CSS를 파싱하고 각
DOM 노드에 해당되는 계산된 스타일(computed style)을 확정한다. 계산된 스타일은 CSS 선택자(selector)로 구분되는 요소에
적용될 스타일에 관한 정보이다. 개발자 도구의 computed 패널에서 이 정보를 볼 수 있다.



그림 3 계산된 스타일을 추가하기 위해 CSS를 파싱하는 메인 스레드

CSS를 전혀 적용하지 않아도 DOM 노드에는 계산된 스타일이 적용되어 있다. <h1> 태그는 <h2> 태그보다 크게 표시되며 바깥
여백(margin)이 모든 요소에 적용된다. 브라우저에 기본 스타일 시트가 있기 때문이다. Chromium 소스 코드의 html.css 파일을
보면 Chrome의 기본 CSS가 어떤지 알 수 있다.




레이아웃

이제 렌더러 프로세스가 문서의 구조와 각 노드의 스타일을 알지만 페이지를 렌더링하기에는 충분하지 않다. 전화 통화를 하며 친구에게 그림을
설명한다고 생각해 보자. "커다란 빨간색 원이 있고, 작은 파란색 사각형이 있어."라고 말해서는 그림이 어떻게 생겼는지 친구가 정확히 알 수
없다.



그림 4 그림 앞에 서있는 사람, 그리고 다른 사람과 연결된 전화선

레이아웃은 요소의 기하학적 속성(geometry)를 찾는 과정이다. 메인 스레드는 DOM과 계산된 스타일을 훑어가며 레이아웃 트리를 만든다.
레이아웃 트리는 x, y 좌표, 박스 영역(bounding box)의 크기와 같은 정보를 가지고 있다. 레이아웃 트리는 DOM 트리와 비슷한
구조일 수 있지만 웹 페이지에 보이는 요소에 관련된 정보만 가지고 있다. display: none 속성이 적용된 요소는 레이아웃 트리에 포함되지
않는다(그러나 visibility: hidden 속성이 적용된 요소는 레이아웃 트리에 포함된다). 이와 비슷하게
p::before{content:"Hi!} 속성과 같은 의사 클래스(pseudo class)의 콘텐츠는 DOM에는 포함되지 않지만 레이아웃
트리에는 포함된다.



그림 5 계산된 스타일이 있는 DOM 트리를 돌며 레이아웃 트리를 생성하는 메인 스레드



그림 6 줄 바꿈이 변해 이동하는 단락의 박스 레이아웃(원본 동영상)

웹 페이지의 레이아웃을 결정하는 것은 어려운 작업이다. 가장 단순하게 위에서 아래로 펼쳐지는 블록 영역 하나만 있는 웹 페이지의 레이아웃을
결정할 때에도 폰트의 크기가 얼마이고 줄 바꿈을 어디서 해야 하는지 고려해야 한다. 단락의 크기와 모양이 바뀔 수 있고, 다음 단락의 위치에
영향이 있기 때문이다.

CSS는 요소를 한쪽으로 흐르게(float) 하거나, 크기를 벗어난 부분을 보이지 않게 하거나, 글이 쓰이는 방향을 변경할 수 있다. 레이아웃
단계가 엄청난 임무를 맡고 있다는 것을 알 수 있다. Chrome에서는 한 팀이 레이아웃만 전담하고 있을 정도이다. 레이아웃 전담 팀이 하는
일을 자세히 알고 싶다면 BlinkOn 8 콘퍼런스의 발표를 참고한다.

> 역주
> 파싱, 스타일 계산, 레이아웃에 관한 더 자세한 내용은 "브라우저는 어떻게 동작하는가?" 글을 참고한다.
> 
> 역주
> 레이아웃 트리와 다음에 설명할 페인트 트리 사이에 한 가지 작업이 더 있다. 레이아웃 트리를 순회하면서 속성 트리(property
> tree)를 만드는 작업이다. 속성 트리는 clip, transform, opacity등의 속성 정보만 가진 트리이다. 기존에는 이런 정보를
> 분리하지 않고 노드마다 가지고 있었다. 그래서 특정 노드의 속성이 변경되면 해당 노드의 하위 노드에도 이 값을 다시 반영하면서 노드를
> 순회해야 했다. 최신 Chrome에서는 이런 속성만 별도로 관리하고 각 노드에서는 속성 트리의 노드를 참조하는 방식으로 변경되고 있다.




페인트



그림 7 붓을 들고 캔버스 앞에 서서 원을 먼저 그려야 할지 사각형을 먼저 그려야 할지 고민 중인 사람

DOM, 스타일, 레이아웃을 가지고도 여전히 페이지를 렌더링할 수 없다. 그림을 하나 따라 그리려고 한다고 생각해 보자. 요소의 크기, 모양,
위치를 알더라도 어떤 순서로 그려야 할지 판단해야 한다.

예를 들어 어떤 요소에 z-index 속성이 적용되었다면 HTML에 작성된 순서로 요소를 그리면 잘못 렌더링된 화면이 나온다.

> 역주
> 즉, DOM에 선언된 노드 순서와 페인트 순서는 많이 다를 수 있다.



그림 8 z-index 속성을 고려하지 않고 HTML 마크업 순서대로 나타나게 잘못 렌더링된 웹 페이지 요소

페인트 단계에서 메인 스레드는 페인트 기록(paint record)을 생성하기 위해 레이아웃 트리를 순회한다. 페인트 기록은 '배경 먼저,
다음은 텍스트, 그리고 직사각형'과 같이 페인팅 과정을 기록한 것이다. JavaScript로 <canvas> 요소에 그림을 그려 봤다면 이
과정이 익숙할 것이다.



그림 9 레이아웃 트리를 순회하며 페인트 기록을 생성하는 메인 스레드




렌더링 파이프라인을 갱신하는 데는 많은 비용이 든다



그림 10 DOM 트리 및 스타일, 레이아웃 트리, 페인트 트리의 순서로 생성된다(원본 동영상)

렌더링 파이프라인에서 파악해야 할 가장 중요한 점은 각 단계에서 이전 작업의 결과가 새 데이터를 만드는 데 사용된다는 것이다. 예를 들어
레이아웃 트리에서 변경이 생겨 문서의 일부가 영향을 받으면 페인팅 순서도 새로 생성해야 한다.

요소에 애니메이션을 적용하면 브라우저는 모든 프레임 사이에서 이러한 작업을 해야 한다. 대부분의 디스플레이 장치는 화면을 초당 60번 새로
고친다(60fps). 요소의 움직임이 모든 프레임에 반영되어야 사람이 볼 때 부드럽게 느껴진다. 애니메이션에서 프레임이 누락되면 웹 페이지가
'버벅대는(janky)' 것처럼 보인다.



그림 11 애니메이션 타임 라인에서 애니메이션 프레임

화면 주사율에 맞추어 렌더링 작업이 이루어져도 이 작업은 메인 스레드에서 실행되기 때문에 애플리케이션이 JavaScript를 실행하는 동안
렌더링이 막힐 수 있다.



그림 12 애니메이션 타임라인에서 애니메이션 프레임과 JavaScript 때문에 렌더링이 막힌 프레임

JavaScript 작업을 작은 덩어리로 나누고 requestAnimationFrame() 메서드를 사용해 프레임마다 실행하도록 스케줄을 관리할
수 있다. 이 방법에 관한 더 자세한 내용은 "Optimize JavaScript Execution"(JavaScript 실행 최적화) 글을
참고한다. 메인 스레드를 막지 않기 위해 웹 워커에서 JavaScript를 실행할 수도 있다.

> 역주
> requestAnimationFrame() 메서드를 통해 등록한 콜백 함수는 그림 13과 같이 프레임마다 실행된다. 프레임의 간격은 모니터의
> 주사율에 따라 다를 수 있다. 브라우저는 VSync 시그널로 프레임 간격을 파악한다. 브라우저와 VSync에 관한 더 자세한 내용은
> "브라우저는 VSync를 어떻게 활용하고 있을까" 발표의 자료를 참고한다.



그림 13 애니메이션 프레임에 맞춰 애니메이션 타임라인에서 실행되는 더 작은 JavaScript 덩어리




합성




페이지는 어떻게 그려질까



그림 14 가장 단순한 래스터화 과정(원본 동영상)

브라우저는 문서의 구조와 각 요소의 스타일, 요소의 기하학적 속성, 페인트 순서를 알고 있다. 브라우저는 이제 웹 페이지를 어떻게 그릴까? 이
정보를 화면의 픽셀로 변환하는 작업을 래스터화(rasterizing)라고 한다.

가장 단순한 래스터화는 아마 뷰포트 안쪽을 래스터하는 것일 것이다. 사용자가 웹 페이지를 스크롤하면 이미 래스터화한 프레임을 움직이고 나머지 빈
부분을 추가로 래스터화한다. 이 방식은 Chrome이 처음 출시되었을 때 래스터화한 방식이다. 그러나 최신 브라우저는
합성(compositing)이라는 보다 정교한 과정을 거친다.

> 역주
> "최신 브라우저의 내부 살펴보기 1 - CPU, GPU, 메모리 그리고 다중 프로세스 아키텍처" 글에서 CPU와 GPU의 차이를 언급했는데,
> 렌더링 파이프라인에서는 이 단계부터 GPU가 많이 사용된다. 참고로 소개했던 "Mythbusters Demo GPU versus
> CPU"(호기심 해결 - GPU 대 CPU) 영상을 생각해 보면 레이어를 합성할 때 GPU가 좀더 유리하다는 것을 쉽게 이해할 수 있을
> 것이다.
> 
> 역주
> 렌더링 파이프라인을 설명할 때 '페인트(paint)'와 '그리기(draw)'라는 용어가 다르게 사용되고 있다는 점에 주목해야 한다. 페인트는
> 페인트 작업(paint operation)을 만들어 내는 것을 의미하고, 그리기는 페인트 작업을 기반으로 비트맵이나 텍스처를 만들어 내는
> 것을 의미한다. 좀 더 정확히는 합성 프레임(compositing frame)을 만들어 내는 것을 지칭한다.




합성이란 무엇인가



그림 15 합성 과정(원본 동영상)

합성은 웹 페이지의 각 부분을 레이어로 분리해 별도로 래스터화하고 컴포지터 스레드(compositor thread)라고 하는 별도의 스레드에서
웹 페이지로 합성하는 기술이다. 스크롤되었을 때 레이어는 이미 래스터화되어 있으므로 새 프레임을 합성하기만 하면 된다. 애니메이션 역시 레이어를
움직이고 합성하는 방식으로 만들 수 있다.

Chrome 개발자 도구의 Layers 패널에서 웹 사이트가 어떻게 레이어로 나뉘어 있는지 볼 수 있다.

> 역주
> DEVIEW 2018 콘퍼런스의 "웹 성능 최적화에 필요한 브라우저의 모든 것" 발표 자료 22쪽에 있는 다음 그림을 참고하면 레이어 합성을
> 이해하는 데 도움이 될 것이다.
> 
> 
> 역주
> 컴포지터 스레드를 별도로 유지하는 것이 오히려 부담이 더 클 때에는 싱글 스레드에서 합성을 실행하기도 한다. 브라우저의 UI
> 부분(chrome)을 담당하는 컴포지터는 싱글 스레드로 작동한다.
> 
> 역주
> "The Animation Process From 1938"(1938년의 애니메이션 제작 과정) 영상을 보면 레이어를 나누는 것과 애니메이션
> 성능 향상의 관계를 이해하는 데 도움이 될 것이다. 이 영상에서는 배경은 그대로 두고 앞에서 움직여야 하는 전경만 별도의 셀로 만들어서
> 프레임을 촬영한다. 만약 배경과 전경을 분리하지 않았다면(즉, 레이어를 나누지 않았다면) 애니메이션 프레임마다 배경도 같이 그려야 했을
> 것이다.




여러 레이어로 나누기

어떤 요소가 어떤 레이어에 있어야 하는지 확인하기 위해 메인 스레드는 레이아웃 트리를 순회하며 레이어 트리를 만든다(이 부분은 개발자 도구의
Performance 패널에서 Update Layer Tree라고 되어 있다). 뷰포트로 미끄러져 들어오는 들어오는 슬라이드인 메뉴처럼 별도의
레이어여야 하는 웹 페이지의 어떤 부분이 별도의 레이어가 아니라면 CSS의 will-change 속성을 사용해 브라우저가 레이어를 생성하게
힌트를 줄 수 있다.



그림 16 레이어 트리를 만들면서 레이아웃 트리를 순회하는 메인 스레드

모든 요소에 레이어를 할당하면 좋을 것 같지만 수많은 레이어를 합성하는 작업은 웹 페이지의 작은 부분을 매 프레임마다 새로 래스터화하는 작업보다
더 오래 걸릴 수 있다. 애플리케이션의 렌더링 성능은 직접 측정해 봐야 한다. 레이어 합성과 레이어 수, 성능에 관한 더 자세한 내용은
"Stick to Compositor-Only Properties and Manage Layer Count"(컴포지터 전용 속성 고수와 레이어
수 관리) 글을 참고한다.

> 역주
> 레이어가 많으면 합성 비용이 높을 뿐만 아니라 레이어를 메모리에 가지고 있어야 하는 부담도 있다. Chrome은 레이어가 과도하게 많아지는
> 것(layer explosion)을 막기 위해 특정한 경우에는 레이어를 생성하지 않거나 합치기도 한다.




메인 스레드 이후 래스터화와 합성

레이어 트리가 생성되고 페인트 순서가 결정되면 메인 스레드가 해당 정보를 컴포지터 스레드에 넘긴다(commit). 그러면 컴포지터 스레드는 각
레이어를 래스터화한다. 어떤 레이어는 페이지의 전체 길이만큼 클 수 있다. 그래서 컴포지터 스레드는 레이어를 타일(tile) 형태로 나눠 각
타일을 래스터 스레드로 보낸다. 래스터 스레드는 각 타일을 래스터화해 GPU 메모리에 저장한다.

> 역주
> 래스터화 역시 GPU의 도움을 받기 좋은 단계이다. 좀 더 자세한 내용은 "Software vs. GPU rasterization in
> Chromium"(Chromium에서 소프트웨어 래스터화와 GPU 래스터화) 글을 참고한다.
> 
> 역주
> 컴포지터 스레드 안에도 레이어 트리는 여러 개 있다. 메인 스레드가 넘긴(commit) 레이어 트리는 컴포지터 스레드의 펜딩
> 트리(pending tree)로 복사된다. 펜딩 트리는 아직 화면에 그려지지 않았지만 최신 프레임이라고 할 수 있다. 현재 화면에 그려지고
> 있는 이전 프레임은 액티브 트리(active tree)로 그린 프레임이다. 최신 정보로 화면을 갱신할 때는 펜딩 트리와 액티브 트리를
> 교체(swap)한다. 펜딩 트리와 액티브 트리에 관한 자세한 내용은 "Native One-copy Texture Uploads for
> Chrome OS on Intel Architecture Enabled by Default"(Intel 아키텍처에서 Chrome OS의
> Native One-copy Texture Uploads 설정이 기본으로 활성화된다) 글을 참고한다.



그림 17 타일 단위로 비트맵을 만들고 GPU로 보내는 래스터 스레드

컴포지터 스레드는 래스터 스레드간의 우선순위를 지정할 수 있어서 뷰포트 안이나 근처의 것들이 먼저 래스터화될 수 있다. 또한 레이어는 줌인 같은
동작을 처리하기 위해 여러 해상도별로 타일 세트를 여러 벌 가지고 있다.

> 역주
> 타일 세트의 모든 타일이 래스터화되어 있지는 않기 때문에 최대한 구멍을 메울 수 있는 방식으로 여러 타일 세트의 타일을 조합해서 사용한다.
> 이렇게 해도 래스터화하지 못한 영역은 체스판(checkerboard)의 하얀색 부분처럼 빈 곳으로 둔다. 이 단계의 큰 목표 중 하나는 이
> 빈 곳을 줄이는 것이다("Multi-threaded Rasterization"(다중 스레드로 처리하는 래스터화) 참고).

타일이 래스터화되면 컴포지터 스레드는 '합성 프레임'을 생성하기 위해 타일의 정보를 모은다. 이 타일의 정보를 '드로 쿼드(draw
quads)'라고 부른다.

드로 쿼드메모리에서 타일의 위치와 웹 페이지 합성을 고려해 타일을 웹 페이지의 어디에 그려야 하는지에 관한 정보를 가지고 있다. 합성 프레임웹
페이지의 프레임을 나타내는 드로 쿼드의 모음

이후에 합성 프레임이 IPC를 통해 브라우저 프로세스로 전송된다. 이 시점에 브라우저 UI의 변경을 반영하려는 UI 스레드나 확장 앱을 위한
다른 렌더러 프로세스에 의해 합성 프레임이 더 추가될 수 있다. 이러한 합성 프레임은 GPU로 전송되어 화면에 표시된다. 스크롤 이벤트가
발생하면 컴포지터 스레드는 GPU로 보낼 다른 합성 프레임을 만든다.

> 역주
> 위에서 언급했듯이 해상도별 타일 세트에서 타일을 선택적으로 조합하기 때문에 드로 쿼드가 조합에 필요한 정보를 기억해야 한다.
> 
> 역주
> 앞으로는 합성 프레임이 브라우저 프로세스를 거치지 않고 GPU 프로세스로 바로 보내지는 형태로 변경될 예정이다.



그림 18 합성 프레임을 생성하는 컴포지터 스레드. 프레임이 브라우저 프로세스를 거쳐 GPU로 보내진다
- "이 프레임을 렌더링해 줘!"(Render this frame please!).

합성의 이점은 메인 스레드와 별개로 작동할 수 있다는 점이다. 컴포지터 스레드는 JavaScript 실행이나 스타일 계산을 기다리지 않아도
된다. 이것이 합성만 하는 애니메이션이 성능상 가장 부드럽다고 보는 이유이다("High Performance Animations"(고성능
애니메이션) 참고). 레이아웃이나 페인트를 다시 계산해야 할 경우에는 메인 스레드가 관여해야 한다.




마무리

이 글에서는 렌더링 파이프라인에 관해 파싱에서 합성에 이르기까지 살펴보았다. 이제 웹 사이트의 성능 최적화에 관해 더 자세히 알고 싶어졌기를
기대한다.

이 시리즈의 마지막인 다음 글에서는 컴포지터 스레드를 보다 자세히 살펴보고 mouse move나 click과 같은 사용자 입력이 들어올 때 어떤
일이 일어나는지 살펴볼 것이다.



최신 브라우저의 내부 살펴보기

 * 최신 브라우저의 내부 살펴보기 1 - CPU, GPU, 메모리 그리고 다중 프로세스 아키텍처
 * 최신 브라우저의 내부 살펴보기 2 - 내비게이션 과정에서 일어나는 일
 * 최신 브라우저의 내부 살펴보기 3 - 렌더러 프로세스의 내부 동작
 * 최신 브라우저의 내부 살펴보기 4 - 컴포지터가 사용자 입력을 받았을 때

Tag
렌더러프로세스레이아웃
글쓴이고상우|네이버 Whale소개데스크탑 브라우저 UI를 개발하고 있습니다. 크로미움에도 컨트리뷰션하고 있습니다.
NAVERfacebook

URL

관련글

 * 최신 브라우저의 내부 살펴보기 4 - 컴포지터가 사용자 입력을 받았을 때
 * AMP는 어떻게 웹 페이지의 성능을 높일 수 있나
 * 최신 브라우저의 내부 살펴보기 2 - 내비게이션 과정에서 일어나는 일
 * 최신 브라우저의 내부 살펴보기 1 - CPU, GPU, 메모리 그리고 다중 프로세스 아키텍처

댓글

4새로고침

댓글 쓰기
댓글 입력
댓글을 작성하려면 로그인 해주세요

현재 입력한 글자수0/전체 입력 가능한 글자수400

등록

 * ksii798
   ㅉ...쩐다....
   2021-08-20 21:03
   답글0
   공감/비공감공감0비공감0
   
 * alzi****
   자료 공유 감사합니다.
   2020-10-08 06:46
   답글0
   공감/비공감공감0비공감0
   
 * ioio
   감사합니다.
   2020-05-03 23:50
   답글0
   공감/비공감공감0비공감0
   
 * 크앙크앙옵션 열기삭제
   good
   2019-07-14 10:24
   답글0
   공감/비공감공감0비공감0
   비밀번호 입력
   확인취소
   

더보기
 * NAVER Developers
 * DEVIEW
 * OpenSource
 * D2 STARTUP FACTORY

 * 
 * 
 * 

Copyright © NAVER Corp. All Rights Reserved.