[브라우저] 렌더링 파이프라인 딥다이브

ChoiYongHyeun·2024년 2월 11일
2

브라우저

목록 보기
5/16
post-thumbnail

2024/02/14 업데이트

캐싱 및 리플로우 여부에 따른 렌더링 성능 시뮬레이터 만들기
사용하는 메소드 별 렌더링 성능을 테스트 할 수 있는 페이지를 만들어봤습니다 😻

공부 해본 이유

우선 이전에 추상화 된 브라우저 렌더링 과정에 대해 공부했었다.


그냥 아 브라우저는 파싱 -> layout -> paint 하는 과정으로 렌더링 되는구나 ~ 하고 가볍게 넘어갔었는데

개발자도구를 살펴보다보면 풀리지 않는 의문이 있었다.

도대체 pre-Paint , Paint 는 뭐고 이렇게 색상이 다른거는 어떤 의미일까 ?

또 !

만약 렌더링 도중 자바스크립트 엔진이 reflow , repaint 를 요청하면 어떤 일이 벌어질까 ?

정말 운이 좋게도 많은 동영상들과 많은 아티클들이 있었다.

이번 공부는 구글 크롬의 Chromium 의 렌더링 엔진을 기준으로 기술한다.

참고 자료

[10분 테코톡] 슬링키의 브라우저 렌더링 파이프라인
성능 최적화를 위해 알아야 할 Chromium 렌더링 파이프라인
렌더링 성능 개선(1) — 렌더링 과정 이해하기
How does browser work step by step [latest] — rendering phase (part 3)
[FE] 브라우저 렌더링 Browser rendering

참고자료들을 머리말에 먼저 두는 이유는 이런 어려운 내용들을 열심히 기술해줘 큰 도움을 준 원작자들에게 매우 고맙기도 하며 , 내가 정리한 내용들보다 훨씬 잘 설명하고 있기에 더 깊게 공부하고 싶은 사람들은 원작자들의 아티클을 읽는 것이 더 큰 도움이 될 것이라 생각했기 때문이다.

항상 큰 도움을 주는 10분 테크톡 .. 감사합니다 😻


추상화 된 브라우저 렌더링 과정

브라우저 렌더링 과정에 대해 찾다보면 추상화 된 다음과 같은 파이프라인을 볼 수 있다.

HTML 문서를 lexical meaning 에 따라 파싱하여 DOM 노드를 생성하고

CSS 문서도 lexical meaning 에 따라 파싱하여 CSSOM 노드를 생성하고

이 둘을 결합해 Render Tree 를 생성한다.

이러한 Render Tree 에서 기하학적 속성들을 이용하여 노드들이 위치 할 layout 을 계산하고

Render Tree 를 위치에 맞게 user Interfacepixel 단위로 paint 한다.

이런식으로 말이다.

이런 설명만 들으면 몇 가지 의문이 든다.

  • layout 을 계산한 결과를 담는 자료구조는 없을까 ? 라든지

  • repaint , reflow 가 일어나면 Render Tree 는 어떻게 재구성될까 ? 라든지

  • 내가 브라우저에 렌더링 해둔 태그가 있을 때 스크롤을 밑으로 N px 을 내리면
    그 태그는 1px 씩 내릴 때 마다 1px 위의 자리에 다시 그려지는걸까 ? 아니면 모든 페이지에 미리 그려두고 뷰포트만 이동하는걸까 ?

  • 개발자도구 - Performance 에 나오는 pre-paint , commit 등이 의미하는건 뭘까 ?


브라우저 렌더링 파이프라인

전체 브라우저 렌더링 파이프라인을 도식화 시켜둔 자료이다.

앞으로는 해당 내용들에 대해 깊게 들어가며 기술하도록 하겠다.

간략한 내용만 짚어보자면

  • 브라우저 렌더링은 Render ProcessGPU Process 를 통해 일어나며 Render ProcessGPU Process 에서 렌더링 할 객체와 명령어를 생성하고 GPU Process 는 렌더링 할 객체와 명령어를 전달받아 렌더링 할 비트맵을 생성 후 유저인터페이스에 띄운다.

  • Render Process 는 두 가지 종류의 스레드로 이뤄져있다. Main Thread 에서는 Render Tree 를 생성하고 Compositor Thread (합성 쓰레드) 는 병렬적으로 존재하는 스레드로 GPU Process 와 상호작용 한다.

  • 렌더링 될 노드들은 Layer 단위로 구성되며 이러한 레이어들은 브라우저에 렌더링 된다. 우리의 노드들이 특정 애니메이션을 통해 이동이 되면 픽셀 단위로 재렌더링 되는 것이 아니라 레이어가 이동한다.


멀티플 프로세스 아키텍쳐

구글 브라우저는 여러 프로세스로 이뤄진 아키텍쳐이다.

여러 프로세스로 이뤄진 아키텍쳐이기 때문에 각 프로세스들은 독립적인 단위로 병렬적인 처리를 가능하게 한다.

렌더링과 관련있는 프로세스는 Render Process , GPU Process 이다.

이 때 Render ProcessBlink Engine 이 담당하게 되며 Tab 별로 하나씩 독립적으로 생성된다.

그 말은 내가 구글 크롬에서 3개의 탭을 띄워두면

각 탭별로 독립적인 3가지 렌더 프로세스가 생성되며 각 렌더 프로세스들은 서로에게 영향을 끼치지 않는다.

아니 , 어차피 사용자는 한 번에 한 탭밖에 못보는데 뭐하로 다 독립적으로 만들어두나요 ? 그냥 하나의 프로세스로 다 관리하면 안되나요 ?

라는 의문이 들 수 있다.

하지만 탭 별로 프로세스를 독립적으로 관리함으로 인해서

다른 탭의 렌더링의 변화가 다른 탭에도 영향을 미치는 미연의 문제를 방지 할 수 있고

또 다른 탭의 렌더 프로세스에 장애가 생겼을 때, 다른 렌더 프로세스에 영항을 미치는 장애 전파를 막을 수 있다.

또 ! Render Process 는 하는 일이 매우 많고 무겁다. 그렇기에 여러개의 탭이 하나의 프로세스를 공유하다보면 프로세스의 부하가 심해질 수 있기 때문에

독립적은 하나의 프로세스를 탭 별로 가지고 있는 것이 안정적이다.

GPU Process 는 탭 별로 하나씩 생성되는 것이 아닌, 모든 탭들을 하나의 프로세스가 담당한다.

그런 이유는 GPU Process 는 단순하게 전달받은 객체와 명령들을 실행해 띄우기만 하면 되는

매우 단순한 기능을 가지고 있기 때문이다.

여러 탭에서 하나의 프로세스를 공유함으로 인해서 리소스를 효율적으로 관리 할 수 있게 만든다.

정리

  • 브라우저의 렌더링은 Render ProcessGPU Process 를 통해 일어난다.
  • Render ProcessTab 별로 하나씩 생성된다. 이를 통해 Render Process 의 안정화 및 다른 Tab 으로의 장애 전파를 방지한다.
  • GPU Process 는 모든 Tab 들이 하나를 공유하여 효율적인 리소스를 관리한다.

Render Process - Main Thread

그럼 이제 본격적으로 렌더링을 위해 각 프로세스들이 하는 일들을 하나씩 알아가보자

Parse

`Parse` 단계는 `DOM` 을 생성하는 과정이다.

DOM 이란 텍스트 문서에 불과한 HTML 문서 문자열들을 Blink Engine 이 가공 가능한 자료구조로 만든 것을 의미한다.

Blink EngineC++ 로 구성되어 있으니 DOMC++ 언어로 생성된 자료구조이다.

DOM 들은 부모 자식 관계 및 lexical meaning 에 따라 구분된 트리구조 형태로 저장된다.

Style

StyleHTML => DOM 처럼 CSS => CSSOM 을 생성하고 생성한 CSSOM 을 이용해

Render Tree 를 구성하는 과정이다.

우선적으로 CSS 를 파싱하여 트리구조의 CSSOM 을 생성하고

DOM 트리를 순회하며 CSSOM 노드의 조건에 맞는 노드들에게 해당되는 Computed Style 이란 객체를 생성한다.

Computed Style 객체의 프로퍼티에는 해당 노드의 선택자 (CSS 에서 정의된 선택자) , value 값에는 스타일 프로퍼티와 스타일 밸류값이 들어있다.

Computed Style 자체는 트리구조가 아닌 일반적인 하나의 객체임을 기억하자

이제 HTML 문서만으로 구성된 DOM 의 각 노드들에 렌더링과 관련된 프로퍼티인

NodeRenderingData 객체의 ComputedStyle 프로퍼티에 위에서 계산된 Computed Style 객체의 주소를 할당한다.

자바스크립트에서도 해당 노드의 ComputedStyle 프로퍼티가 가리키고 있는 포인터를 확인 할 수 있다.

getComputedStyle 로 특정노드에 할당된 ComputedStyle 객체를 확인 할 수 있다.

정리

  • Style 단계에서는 CSS 문서를 파싱하여 CSSOM 을 생성하고 DOMCSSOM 을 순차적으로 순회하며 Computed Style 객체를 생성한다.
  • Computed Style 객체들은 DOM 의 노드들에 설정될 스타일 속성을 담은 객체이다.
  • DOM 에서 각 노드들은 계산된 Computed Style 의 포인터를 할당받음으로서 style 관련 속성을 담는다.

    나는 DOM , CSSOM 을 이용해 새로운 Render Tree 를 생성하는줄 알았는데 DOM 에서 각 노드들이 스타일 관련 객체들을 하나씩 프로퍼티로 추가하는 것이였다.

Layout

DOM 의 노드들의 ComputedStyle 객체를 확인하여 각 노드들이 위치해야 할 Layout 의 정보를 담은

Layout Object 를 생성하는 과정이다.

Layout 은 노드들이 렌더링 되어야 할 위치를 px 단위로 계산하는 과정이다.
렌더링 될 위치를 계산하기 위해선 해당 노드의 크기와 관련된 속성이나, 직접적인 위치등을 설정한 스타일을 계산해야 한다.
또 이러한 속성들은 DOM 의 상속적인 관계에 영향을 받는다.

기하학적 요소와 관련있는 width , height, font-size , top , left ... 등의 스타일 프로퍼티를 이용하여 노드의 위치들을 담은 Layout Object 를 생성하고 해당 Layout ObjectDOM 노드의 NodeRenderingDataLayoutObject에 할당된다.

Layout Object 들은 여러 종류의 프로토타입들로 이뤄져있다. block level elementlinine level exlement 냐에 따른 layout 속성이 다를 것이기 때문이다.

이후 구성된 Layout Object 들을 이용하여 Layout Tree 를 생성한다.

  1. 일반적으로 Layout TreeDOM Tree 와 매우 유사한 모양을 가지고 있다.
    Layout 은 부모, 자식 간의 상대적인 관계를 유념하며 계산되어야 하기 때문이다.

  2. Layout Tree 에서는 Layout 과 관련된 속성들이 담겨있다.
    (width , height , top , left ... 등과 같은 것들 말이다.)

Layout Tree 를 생성하는 이유 : dirty bit을 관리하기 위해

Layout 을 계산하는 과정은 매우 무거운 과정이다.

단순하게 px 단위로 이뤄져있다면 뭐 쉽겠지만 % , rem ,vh , vw .. 등과 같이 상대적인 조건으로 이뤄져있다면

부모 노드의 크기나 DOM 내의 상대적인 관계들을 모두 고려하여 px 단위로 계산하는 과정이 Layout 과정이다.

이 때 특정 노드의 기하학적 특성이 변경되면 관련이 있는 노드들의 단위도 모두 수정해야 하기에

모든 DOMComputed Style 을 모두 재계산 해야 하는 높은 비용의 과정이 발생하게 된다.

이 때 효율적으로 Layout 을 하기 위해서는 변화가 발생한 노드와 해당 노드와 관련이 있는 노드들만 수정하는 것이 좋을 것이다.

이러한 과정을 관리하기 위한 자료구조로 Layout Tree 를 생성한다.

변화가 발생한 노드와 해당 노드와 관련이 있는 노드들만 수정하는 과정은 메모리에서 수정이 일어난 메모리 주소와 관련 메모리 주소의 값을 변경하는 dirty bit 과 관련이 깊다.

layout Tree 는 각 노드들은 style 과정에서 기하학적 속성이 변경된 노드임을 나타내는 dirty bit flag 를 가지고 있다.

특정 노드의 layout 속성이 변경되면 layout Tree 에서 해당 노드의 dirty bit flag 가 활성화되고

이러한 flag 는 관련이 있는 노드들에게 전파되며 layout 과정에서 dirty bit flag 가 활성화 되어 있는 노드에 대해서만 재계산한다.

해당 노드에 대한 layout 만 새롭게 수정 , DOM 에게 변경된 객체만 다시 붙여주면 된다.

생각해보자 만약에 layout Tree 가 없었다면 layout Object 들은 트리구조가 아닌 일반적인 한 객체이기 때문에 관계를 추정 할 수 없을 뿐더러

모든 layout Object 들을 모두 훑어보며 계산해봤어야 할 것이다 !

Layout Tree 는 캐싱되며 변화가 발생하면 새롭게 캐싱된다

첫 렌더링 이후 DOM 노드 중 한 노드의 layout Tree 에 영향을 미치지 않는 스타일을 변경했다고 해보자

그러면 Computed Style 은 다시 계산 되어 DOM 에 착 붙을 것이다.

그러면 Layout Tree 또한 다시 계산하여 DOM에 붙이게 될까 ?

Layout Tree 는 이전 렌더링 과정에서 캐싱된다.

그로인해 Layout Tree 에 변화가 없다면 캐싱되어 있던 Layout Tree 를 이용하여 렌더링 하게 된다.

Layout Tree 는 캐싱되기 때문에 repaint 만 일어났을 때 reflow 가 다시 일어나지 않는다는 것이다.

하지만 만약 layout Tree 에 영향을 미치는 스타일이 변경된다면 ?

layout Tree 에서 변경된 노드의 dirty bit flag 가 활성화 되고, 변경된 노드에 대해서만 layout 이 재 계산, 새로운 layout Tree 가 생성되고 캐싱된다.

정리

  • Layout 단계에서는 DOM의 구조와 ComputedStyle 객체를 이용하여 Layout Tree 를 생성한다.

  • Layout Tree 는 각 노드들의 기하학적 위치와 관련있는 스타일들을 저장하고 있는 자료구조이며 Layout Tree 내의 Layout Object 들은 DOMNodeRenderingData 의 프로퍼티에 할당된다.

  • Layout Tree 는 캐싱되며 Layout Tree 가 변경되면 변경이 일어난 노드의 수정이 일어나며 새롭게 생성된 Layout Tree 가 캐싱된다.

pre-paint

노드들의 위치나 크기에 영향을 미치는 스타일 속성들을 layout Tree 에서 관리한다고 하였다.

이런 layout Tree 를 관리하는 프로세스는 Render Process 이다.

이 때 Render Process 가 아닌 이후에 일을 담당 할 GPU Process 에서 관리하는 속성 들이 몇가지 존재한다.

그것은 transform , opcaity , scroll , clip 속성이다.

해당 속성들은 Render Process 에서 관리하지 않기 때문에 layout Tree 에서 관리되지 않지만

GPU Process 에서 관리 할 수 있도록 해당 스타일들을 트리 구조로 저장하는 과정이 pre-paint 과정이다.

이렇게 생성된 트리 구조는 Property Tree 라고 불린다.

정리

  • pre-paintDOMComputedStyle 객체 중 RenderProcess 에서 관여하지 않는 스타일 속성들 (transform , scroll , clip , opcaity) 을 GPU Process 에서 접근 할 수 있도록 트리 구조의 객체로 만드는 과정을 의미한다.

Paint

PaintNodeRenderingData 에 존재하는 객체들을 GPU Process 에서 관리 할 수 있는 객체 형태로 wrapping 해주는 과정이다.

GPU Process 에서 사용 할 메소드들이 존재하는 DisplayItem 이란 객체에 해당 객체를 감싸 DisplayItemList 라는 자료구조에 담아두고

DisplayItemList 배열들을 저장할 PaintArtifact 에 담아준다.

이러한 DisplayItem 에는 3가지 정보가 포함된다.

  • Action (e.g Draw Rect)
  • Position (e.g 0,0,300,300)
  • Style (e.g backgroundColor : red)

정리

  • Paint 단계는 Render Process 에서 생성한 DOM Tree 들을 GPU Process 에서 실행 할 수 있도록 GPU 가 인식 할 수 있는 명령어가 담긴 객체의 형태로 감싸주는 과정이다.

Layerize

개발자 도구 -> Layers 에 들어가면 페이지의 레이어들을 살펴 볼 수 있다.

이처럼 우리의 페이지는 하나의 큰 스케치북에 그림을 한 꺼번에 렌더링하는 것이 아닌

하나의 큰 스케치북에 여러 개의 그림으로 구성된 레이어들을 붙여넣는 형태로 렌더링 된다.

Layerize 단계에서는 렌더링 할 레이어들을 기획하고, 레이어 별로 노드들을 분리시켜두는 과정을 의미한다.

레이어를 나눌 때 렌더링 엔진은 다음과 같은 기준들을 이용해 레이어를 나눈다.

레이어를 나누는 기준

렌더링 속성

  • Opacity
    Opacity 를 사용하면 다른 레이어들 위에서 사용되는 경우가 존재한다. 그렇기에 이런 노드는 다른 레이어들과 겹칠 수 있기 때문에 독립적인 레이어로 구성한다.
  • Transform
    transform 이 일어나는 노드들의 애니메이션은 해당 레이어에게만 애니메이션을 적용시킬 수 있도록 하여 이 전 단계들을 반복하는 overload 를 줄일 수 있도록 특정한 레이어로 구성한다.
  • Perspective , TranslateZ
    3D 변환이 포함된 요소들은 자동으로 별도의 레이어로 승격된다. 리소스를 많이 잡아먹는 레이어들은 별도의 레이어로 구성하여 하드웨어 가속이나 렌더링 오버헤드를 감소시킨다.
  • filter
    복잡한 필터 효과를 적용 할 때 렌더링 성능을 향상시키기 위해 별도의 레이어에 배치한다. 이 또한 하드웨어 가속이나 렌더링 오버헤드를 감소시키기 위함이다.

포지셔닝 속성

  • position
    fixed로 고정적인 위치가 지정된 요소는 별도의 레이어에 배치되어 위치 변경을 효율적으로 렌더링 하고 처리 할 수 있도록 한다.
  • Z-index
    Z-index 는 레이어 별로 위에 쌓이는 순서를 결정하기 때문에 Z-index 가 설정된 노드들은 개별적인 레이어로 배치된다.

스크롤링 및 오버플로

  • scrollable
    스크롤이 가능한 요소 또는 자동으로 설정된 오버플로 속성이 있는 경우는 기본적인 레이어를 넘어 확장되곤 한다. 이로인해 스크롤 성능을 최적화 하기 위해 별도의 레이어에 배치된다.

    우리가 어떤 노드에서 스크롤을 할 경우 해당 레이어가 움직이는 것이다.
    위 예시에서도 스크롤을 할 때 유튜브 전체를 담고있는 레이어가 상하로 움직이는 모습을 볼 수 있다.

  • animation scroll
    부드러운 스크롤 성능을 보장하기 위해 별도의 레이어로 승격될 수 있다.

복잡성과 규모

  • 위와 같은 내용들 뿐 아니라 브라우저는 DOM 의 구조가 복잡하거나 중첩되어 있을 수록 렌더링 성능을 최적화 하기 위해 별도의 레이어로 배치한다.
  • 애니메이션이 적용된 노드나 이미지나 비디오 같은 큰 요소들도 별도의 레이어로 배치 할 수 있다.

동적 변경

  • 렌더링이 자동적으로 변경되는 노드의 경우에는 하드웨어 가속화를 이용하기 위해 별도의 레이어로 승격시키기도 한다. (will-change 속성이 존재하는 경우가 이에 해당 함)

레이어를 나누는 이유

레이어를 나눠두면 GPU Process 에서 병렬적으로 레이어들을 관리 할 수 있기 때문에

더 빠른 렌더링 및 향상된 성능을 제공 할 수 있다.

또한 레이어를 나눠두면 브라우저의 변경 사항이 발생했을 때 모든 레이어들을 다시 그리기보다

변화가 발생한 레이어만 다시 그리면 되기 때문에 오버헤드가 적다.

최종 결과물

Render ProcessMain Thread 에서 최종적으로 내는 결과물은 각 레이어들을 담고 있는 Composited Layer List 라는 자료구조이다.

Render Process - Main Thread 에서의 내용 정리

  • Parse , style : HTML 문서와 CSS 문서를 파싱하여 DOMCSSOM 을 구성하고 DOM 의 노드 별 Computed Style 객체를 할당한다.
  • layout : DOM 의 구조와 ComputedStyle 객체의 정보를 이용하여 노드들의 기하학적 속성을 담은 Layout Object 를 구성하여 DOM 에 할당시키고, layout Tree 를 구성하여 Layout 의 변화에 대응하도록 한다.
  • pre-paint : GPU Process 에서 관리될 스타일 속성들을 따로 트리구조로 만들어두는 과정을 의미한다.
  • Paint : DOMNodeRenderingData 객체들을 GPU Process 에서 실행 할 수 있는 명령어가 존재하는 PaintArtifact 객체 형태로 감싸는 단계를 의미한다.
  • Layerize : 렌더링 할 레이어들을 DOM 의 구조나 ComputedStyle등을 살펴보며 구성하는 단계를 의미한다.
    최종적으로 구성된 Layer 들은 Composited Layer List 라는 자료구조에 담겨 반환된다.

Commit

`Commit` 단계는 `Main Thread` 에서 생성된 `Composited Layer List` 와 `Property Tree` 들을 `Composited Thread` 로 옮기는 과정이다.

Commit 단계는 메인 스레드 단계에서의 마지막 작업이다.

Commit 단계 이후부터는 병렬적으로 처리되기 때문에 커밋 이후에는 자바스크립트를 실행하거나 렌더링 파이프라인을 다시 시행 할 수 있다.

물론 비동기작업같은 경우에는 멈추지 않고 비동기적으로 실행되고 있다.


Render Process - Composited Thread

자 여태까지는 Main Thread 에서만 일어나는 일에 대해 공부했다.

이제 합성 레이어에서 일어나는 일들에 대해 공부해보자

Main ThreadComposited Thread 로 구분해뒀을까 ?

Main Thread 에서 일어나는 일들은 모두 순서가 존재해야 하는 프로세스들이기에 메인 스레드 하나로 충분히 가능하였다.

Compoisted Thread 에서 일어나는 일들은 multi threadGPU Process 와 상호작용 해야 하기 때문에 Composited Thread 로 구성되어 있다.

또한 렌더링 과정동안 Main Thread 에서 일어나는 일들을 block 하지 않기 위해 병렬적이고 독립적인 처리가 가능한 Composited Thread 로 구성해둔다.

정리

  • Composited Thread 로 구성해둠으로서 메인스레드에서 일어나는 일들과 독립적이고 병렬적으로 처리 할 수 있어 오버헤드도 줄이고 더 높은 렌더링 속도를 기대하게 할 수 있다.
  • 또한 multiple threadGPU Process 와 상호작용 해야 하기 때문에 Composited Thread 로 구성해두는 것이 좋다.

Tiling


우리는 렌더링 할 레이어들을 나눠두었었다. 타일링 과정은

지금 당장 보이는 영역에 대한 레이어만 렌더링 하자는 것이다.

보이는 영역 외의 부분들도 렌더링 하여 리소스를 소비하는 것보다

현재 보이는 영역만 렌더링 하는 것이 리소스를 효율적으로 관리 할 수 있게 한다.

그로 인해 이전에 구성해둔 개개인의 레이어들을 여러 개의 타일로 나눠

같은 레이어더라도 화면에 보이는 타일만 우선적으로 렌더링 할 수 있도록 하기 위함이다.

그러기 위해 다음에 일어날 레스터화 될 때 우선순위를 위해 뷰포트 포함 여부 등의 정보를 담고 있는다.

GPU Process - Raster

Render Process - Composited ThreadGPU Process 는 서로 번갈아가며 일을 진행한다.

그렇기에 GPU Process 에서 진행되는 일은 작업 옆에 GPU Process 라는 단어를 붙이도록 하겠다.

Raster 단계는 타일링 된 레이어들에 담긴 객체의 명령어들을 시행하여 렌더링 할 비트맵을 생성하는 과정이다.

이 단계에서 우리가 Paint 단계에서 NodeRenderingData 를 명령어가 담긴 객체로 감싸주었던 DisplayItem 메소드를 시행하게 되고

pre Paint 단계에서 생성한 Property Tree 에 담긴 속성을 이용해 비트맵을 생성하고 생성한 비트맵을 GPU 메모리에 저장한다.

이렇게 저장된 비트맵은 DrawQuad 라는 명령어를 통해 불러올 수 있게 된다.

이렇게 Quad 단위의 데이터는 타일을 어디에, 어떻게 그릴지에 대한 정보를 포함하고 있다.

정리

  • Raster 단계에서는 Property Tree 의 속성과 타일링 된 레이어들의 메소드를 통해 타일 별 렌더링 될 비트맵을 생성하여 GPU 메모리에 저장한다.
  • 이렇게 저장된 비트맵들은 DrawQuad 라는 명령어를 통해 참조 할 수 있다.

    타일링 된 레이어들이 Raster 단계를 거쳐 DrawQuad 라는 단위로 변경되었다.

구글 브라우저는 SKIA 라는 라이브러리를 이용하여 비트맵을 생성한다.
그래서 생성하는 명령어도 SKIA 의 명령어이다.

GPU 가속

GPU 가속은 Raster 단계와 큰 밀접한 관계가 있다.

GPU 가속이란 렌더링 및 그래픽 작업을 위해 GPU 를 사용하는 것을 의미하는데

GPU 는 병렬 처리 기능이 존재하며 그래픽 작업에 특화된 디바이스이다.

예전에는 비트맵을 생성하는 과정이 CPU 단에 있는 Render Process 단계에서 진행되었으나

그래픽 집약적인 행위를 하는 GPU Process 에게 행위를 오프로드 함으로서

더 빠른 렌더링 성능을 가져올 수 있게 되었다.

이러한 행위를 하드웨어 가속 이라 하며 CPU 가 하던 일을 GPU 가 하게되었으니 이를 GPU 가속이라 한다.

Render Process - Activate

Activate 단계에서는 Raster 화 된 DrawQuad 들을 하나의 Compositor Frame 안에 묶어 렌더링 할 프레임을 생성하는 과정이다.

GPU Process - Aggregate

Compositor FrameRender Process 에서만 생성되는 것이 아니라 여러 프로세스에서도 생성된다.

그렇기에 여러 프로세스에서 생성된 Compositor Frame 들을 하나의 Compositor Frame으로 묶는 과정을 Aggregate 라고 한다.

GPU Process - Display

Display 단계예서는 묶인 Compositor Frame 을 이용해 GPU 로 렌더링 하는 단계이다.


PS. 어떤 요소를 이동 시킬 때 transform 을 사용하는것이 좋은 이유

그러면 예전에 어떤 노드를 이동 시킬 때 top , left 를 이용하는 것보다 transform 을 이용하는 것이 더 효율적이다라는 글을 보았을 때는

그냥 그렇구나 하고 넘어갔는데

이렇게 렌더링 파이프라인에 대해 공부하고 나니 그 이유를 알겠다.

transform 을 변경시키면 기존의 DOMlayout 을 변경시키지 않고

Property Tree 만 변경하여 GPU Process 에게 넘겨줘 레이어들만 이동시키면 되기 때문이다.

시간이 오래 걸리는 CPU Process 에서 일어나는 일들을 모두 스킵하고 GPU Process 에서만 빠르게 렌더링 할 수 있기에 GPU 가속을 쓸 수 있다는 것이구나

와우 오마이갓


회고

와 정말 잘 정리해줘서 영상을 올리거나 아티클을 올린 사람들에게 무수한 감사를 드립니다 ..

profile
빨리 가는 유일한 방법은 제대로 가는 것이다

2개의 댓글

comment-user-thumbnail
4일 전

렌더링 과정과 그 이유가 써있어서 보기 너무 편했어요! 글 잘봤습니다!

1개의 답글