이전에 렌더링 최적화 글을 작성하면서 브라우저가 어떻게 성능최적화를 하는 지에 대해서 자세하게 검색해본 적이 있습니다.

 

 

[CSS] 브라우저의 Layer Model과 하드웨어 가속을 이용한 렌더링 최적화에 대해 알아보자!

이전 글에 이어서, 이번에는 Layer Model에 대한 복습과 함께 CRP 과정에서 발생할 수 있는 하드웨어(GPU) 가속에 대해 조금 더 자세하게, 그리고 이해하기 쉽게 뜯어보려고 합니다. 사실 지난 포스팅

ssocoit.tistory.com

 

이 때 제가 많은 도움을 받았던 영상이 바로 NAVER DEVIEW 2018의 웹 성능 최적화에 필요한 브라우저의 모든 것 인데요!

복습 차원에서 이 영상을 간단하게 요약해보려고 합니다.

 

해당 영상은 아래 링크에서 확인하실 수 있습니다.

 

웹 성능 최적화에 필요한 브라우저의 모든 것

NAVER Engineering | 웹 성능 최적화에 필요한 브라우저의 모든 것

tv.naver.com

 

그리고 영상에서 사용된 PPT는 아래에서 확인하실 수 있습니다.

 

[125]웹 성능 최적화에 필요한 브라우저의 모든 것

웹 성능 최적화에 필요한 브라우저의 모든 것 이름: 이형욱 소속: NAVER

www.slideshare.net

 

목차


    0. 브라우저가 동작하는 방법

    먼저 브라우저 내에서 화면 렌더링이 어떻게 일어나는지 알아봐야겠죠?

     

    화면 렌더링이 어떻게 동작하는지에 대해서 가장 간략하게 표현해놓은 사진이 바로 아래 사진입니다.

    많은 곳에서 아래와 같은 그림으로 설명하고 있으며, 최근에는 HTML과 CSS를 바탕으로 DOM과 CSSOM을 생성하는 과정을 JS 하나로 퉁(?)치는 경우도 많다고 합니다.

     

     

    이제 각 과정을 조금 더 자세하게 살펴봅시다!

     

    0.0. DOM 생성 과정

    HTML을 받아온다고 해서 그 내용을 바로 화면에 출력할 수는 없습니다.

    컴퓨터가 이해하고 가공할 수 있도록 DOM형태로 파싱을 하는 과정이 필요한데, 그 과정이 바로 아래와 같습니다.

    만약 HTML문서에서 Hello를 지우고 Hi를 넣고 싶다면 매번 쭉 찾아서 바꾸는 복잡한 과정이 필요합니다.

    근데 DOM이라고 트리를 만들면 특정 Node를 찾아서 Hi를 넣으면 되고, 쉽게 삭제하거나 추가할 수 있습니다.

     

    이런 DOM모델은 XML같은 Document를 처리하는 모델에서 많이 쓰이고 있습니다.

     

     

    위 과정을 조금 더 자세하게 펼치면 아래와 같습니다.

    바이트형태를 받아서 문자화 시키고, 이걸 토크나이징 과정을 통해서 DOM으로 만들게 됩니다. (뒤에서 말하겠지만, CSS를 이용해 CSSOM을 만드는 과정도 같은 방식입니다.)

     

    DOM트리를 만드는 것에 관해 조금 더 이야기해보면, 브라우저는 기본적으로 HTML을 한번에 처리하지 않고 데이터를 받을 때마다 조금씩 처리해서 DOM트리를 만듭니다.

    DOM트리를 만들 때 핵심은 바로 예외처리인데, 일반적으로 HTML문서를 만들 때 이렇게 Well-Form한 형태로 만들지 않습니다.

    무언가 빠지거나 할 수 있는데, 이런 에러같은 페이지를 만났을 때 예외처리 방식에 따라 DOM트리의 형태가 달라질 수 있습니다.

    그래서 최근 HTML5 스펙에는 에러처리 역시 명시가 되어있어서 이렇게 처리하라고 되어있다고 합니다.

     

     

    0.1. JavaScript  처리

    이번에는 JavaScript를 처리하는 과정입니다.

    JS는 여러 경로를 통해 실행이 되는데, 그 경로는 HTML 파싱 과정의 Script 태그, 유저의 Input 등 굉장히 다양합니다.

     

     

     

    JS엔진인 V8 역시 아래와 같은 방식으로 처리된다고 합니다.

    원래는 V8엔진의 경우 JS를 받으면 JIT 컴파일 과정을 통해 머신코드를 생성했습니다.

     

    그리고 웹킷 계열(iOS나 사파리)의 경우 인터프리터가 존재해서 JS를 파싱해서 바이트코드를 실행하는 케이스도 존재했습니다.

     

    그런데 V8의 JIT Compile 과정은 속도는 굉장히 빠르지만 컴파일 시간이 오래걸리고 메모리를 많이 잡아먹습니다.

     

    그래서 V8도 웹킷 계열의 인터프리터의 장점을 받아들여서 2017년에 Ignition이라는 인터프리터를 도입했고, JS 코드를 받으면 먼저 인터프리터가 바이트코드를 만들어서 바로 실행하거나, 필요한 경우 최적화를 위해 JIT 컴파일을 하는 과정을 거친다고 합니다.

     

     

    0.2. CSSOM 생성

    그 다음은 .css파일을 파싱하는 과정입니다.

    HTML은 단순한 하나의 문서입니다.

    HTML에는 렌더링 방식에 대한 내용이 없습니다.

    대신 CSS가 렌더링 방식에 대한 정보를 모두 가지고 있습니다.


    Recalculate Style이라는 과정은 파싱된 DOM 트리의 노드를 계산하는 과정입니다.

    그리고 CSS를 파싱하는 과정은 Dev Tool에는 표시가 되지 않습니다.

     

     

    CSSOM 역시 Tree형태로 되어있습니다.

    Cascade같은 상속 개념을 적용하기에 Tree가 좋기 때문에 이런 식으로 만든다고 합니다.

    CSSOM도 마찬가지로 JS API가 있고, 이 말은 JavaScript를 이용해서 CSS를 수정할 수 있다는 말이 됩니다.

     

     

    0.3. Render Tree 생성

    DOM Tree와 CSSOM Tree의 정보를 Lookup해서 만드는 트리가 바로 Render Tree입니다.

    Render Tree는 화면에 렌더링을 하기 위한 정보들을 가지고 있는 트리입니다.

    아래 그림만 보면 DOM Tree와 굉장히 비슷하지만 약간 다른 점이 존재합니다.

    특히 Render Tree는 DOM Tree와는 다르게 HTML파일과 1:1관계를 가지고 있지 않습니다.

     

    그리고 렌더링을 위한 트리이기 때문에 화면에 보이는 요소들을 중심으로 만들어집니다.

    이 말은 화면에 보여지지 않는 부분은 Render Tree에 들어가지 않는다는 말과 같습니다.

    예를 들면 Head 태그에 있는 내용은 화면에 보여질 필요가 없기 때문에 Render Tree에 들어가지 않습니다.

     

     

    아래 그림은 DOM Tree와 CSSOM Tree가 어떻게 만나서 Render Tree를 만드는 지를 보여줍니다.

    가장 눈에 띄는 특징은, DOM Tree의 web performance가 Render Tree에는 없습니다.

     

    왜 없을까요?

     

    바로 display: none을 했기 때문에 화면에 보일 필요가 없기 때문입니다.

    화면에 보일 필요가 없다면 굳이 Render Tree에 들어갈 필요가 없겠죠?

     

     

    0.4. Layout 과정

    브라우저 렌더링 엔진이 어떻게 만들어졌을까요?

    IE나 파이어폭스나 웨일이나 마음대로 만드는게 아니라 표준 스펙이 있습니다.

    CSS 2.1 스펙이라는 것이 있는데, 이게 바로 브라우저 내 CSS 사용의 표준이 되는 문서입니다.

    여기에 따르면 브라우저 세계에서는 모든게 다 박스로 구성되어 있습니다.

    그리고 이러한 박스의 크기와 위치를 계산하는 과정이 바로 Layout입니다.

    이것만 알면 렌더링을 할 수 있겠죠?

     

    추가적으로 Global(전체)과 Incremental(부분) Layout이 존재한다는 것만 알고있으면 됩니다!

    (해당 내용은 뒤에 다시 설명합니다.)

     

     

    Layout의 기본은 각 박스의 크기(너비와 높이)와 위치(좌표)만 계산하면 됩니다.

     

    일반적으로 브라우저의 박스들의 width(너비)은 부모 크기 width를 기준으로 계산됩니다.

    최상위 요소는 window를 기준으로 계산이 되는데, 여기서는 1024가 되겠습니다.

    그리고 1024의 오른쪽에 있는 37은 해당 요소의 height(높이)가 됩니다.

    그 외에 앞에 있는 요소는 위치를 의미합니다.

    중요한 것은 크기를 계산할 때 Global Layout은 전체를 한번에 Layout 하는것이고, Incremental layout은 부분적으로 Layout하는 것을 의미합니다.

    Global layout이 발생하는 두 가지 조건이 바로 윈도우 사이즈를 변경하는 것과 폰트를 변경하는 것입니다. (나머지는 전부 부분적으로 layout이 발생합니다.)

     

     

    그리고 브라우저의 모든 element, 박스들은 block 형태와 inline 형태가 존재합니다.

    이것들이 레이아웃되는 방식은 전부 CSS 2.1에 명시가 되어있습니다.

    block 박스는 한 줄을 전부 먹고(아래위로 쌓임), inline은 좌우로만(옆으로 쌓임)  쌓이는 알고리즘을 가지고 있습니다.

     

    그렇다면 어떤 element가 어떤 박스 타입인가에 대해 궁금해할 수도 있는데, 이것들 역시 이미 명시가 되어있습니다.

    따로 이것들을 바꿀 수도 있지만, 바꾸지 않으면 기본적으로 설정된 내용이 적용됩니다.

    아래 사진에서 맨 오른쪽 요소들을 보면 적혀있는 것들이 block 타입이고, 그 외의 모든 박스들이 inline 타입을 가집니다.

    그래서 브라우저들은 element의 박스 타입을 보고 layout이 됩니다.

     

     

    0.5. Paint 과정

    브라우저의 페인트 과정은 프린트와 비슷합니다.

    뭔가 짜잔 하면서 렌더링이 되는게 아니라 프린트처럼 한 픽셀 한 픽셀 그립니다.

    즉 페인트를 하기 위해서는 render tree를 하나씩 하나씩 그려야 한다는 것이죠.

     

     


    1. 새로운 브라우저 렌더링 플로우

    최신 브라우저가 렌더링 하는 방식은 위의 방식에서 일부 요소들이 추가가 되었습니다.

    과거 브라우저 렌더링 방식은 로딩이 중심이었는데, 이제는 로딩 이후의 과정이 중요해졌습니다.

    사용자와의 인터랙션을 처리하기 위한 부분은 렌더 트리 생성 이후이기 때문에, 그 이후를 보다 자세하게 나눠서 보게 된 것이죠.

     

    여기서 새롭게 등장한 친구들인 Update Layer TreeComposite에 대해 알아보겠습니다.

     

     

    1.0. Update Layer Tree 과정

    새롭게 등장한 요소중에 가장 눈여겨봐야 할 점이 바로 Layer입니다.

    Layer렌더링될 요소들을 층 형태로 나누어둔 것을 의미합니다.

    그리고 Update Layer Tree렌더링이 될 최종 레이어들을 계산해서 생성하는 과정입니다.

     

    브라우저에는 Dom Tree와 Render Tree 말고도 또 다른 Tree가 있는데, 그게 바로 Layer Tree입니다.

    Layer 역시 Tree 형태로 생성이 되는 것이죠.

    TMI를 하나 말씀드리면 브라우저의 내부 자료 구조를 많은 사람들이 Forest라고 부르는 이유가 이렇게 Tree가 많기 때문이라고 합니다.

     

    이렇게 생성된 Layer를 바탕으로 렌더링이 처리됩니다.

    Layer가 생성되는 조건은 아래와 같은 이유들이 존재합니다.

    이 조건들을 통해 새로운 레이어가 생성이 되고, 이 레이어를 가지고 브라우저는 화면을 처리합니다.

     

    여기서 8번이 조금 특이한데, 브라우저는 생성 조건 이외에도 자체적으로 레이어를 생성하기도 합니다.

    실제로 Dev Tool에는 예측 가능한 레이어를 볼 수 있는 기능이 있는데, 브라우저에서 내부적으로 만든 레이어도 여기서 확인할 수 있습니다.

    2개의 같은 Z-index인 레이어가 오버래핑될 때는 브라우저에서 레이어를 만들어버립니다.

    또한 브라우저의 스크롤바도 별도의 레이어로 생성해서 렌더링합니다.

    정리하면 이런저런 다양한 이유로 브라우저에서 레이어를 생성하기도 한다는 것을 알아두시면 좋습니다.

     

    1.1. Composite 과정

    Composite여러 레이어들을 합성해서 한 장의 비트맵으로 만드는 것을 의미합니다.

    전체 한 판을 쭉 그리는 것이 아니라 레이어별로 Paint를 한 이후에 Composite 과정에서 합성을 하게 됩니다.

    그리고 전체 화면을 한번에 그리지 않고 여러 타일로 나눠서 그리는 것Tiled Backing Store 기법이라고 부르고, 이 기법을 통해서 화면을 재사용할 수 있습니다.

     

     

    만약 브라우저에서 레이어링 기법을 사용하지 않고 한 장으로 만든다면 어떻게 될까요?

    가장 최신의 고성능 컴퓨터라도 성능에서 문제를 겪을 여지가 존재합니다.

    기본적으로 paint 과정은 굉장히 cost가 큽니다.

    만약 아래 그림에서 나뭇잎 하나의 위치가 바뀐다면 전체 배경을 다시 그려야하는 과정을 거치게 되겠죠?

     

    이럴 때 각 요소들을 따로따로 레이어 처리를 한다면 paint 측면에서 훨씬 효율적일 수 있겠죠?!

     

     


    2. 어떻게 브라우저가 프레임을 만들까?

    지금까지는 일반적인 브라우저 화면이 어떻게 렌더링이 되는지에 대한 기초를 살펴봤습니다.

    그렇다면 이번에는 웨일이나 크롬, 오페라와 같은 최신 브라우저에서 프레임이 어떻게 만들어지는지에 대한 내용을 알아보도록 하겠습니다.

     

    2.0. VSync

    VSync그래픽 카드의 프레임 생성과 모니터의 프레임 출력을 동기화시켜주는 것을 의미합니다.

    조금 어렵게 말하면 VSync는 디스플레이의 프레임버퍼에 있는 내용을 어떤 주기로 화면에 Fetch 하느냐와 관련이 있습니다.

    보통 기준이 60hz이고, 1000ms를 60프레임으로 쪼갠 16.6ms 단위로 모니터에 Fetch한다고 보시면 되겠습니다.

    그리고 그 단위를 VSync Tick이라고 부릅니다.

     

     

    구글 크롬팀의 자료를 살펴보면, VSync를 이용해서 화면을 출력할 때와 이용하지 않을 때를 비교한 사진입니다.

    만약 VSync를 사용하지 않는다면 2번 프레임에서 문제가 발생하고, 3번에서 만든 프레임과 4번에서 만든 프레임이 겹쳐서 3번이 필요 없는 프레임이 되어버렸습니다.

     

    만약 VSync를 사용한다면 이런 문제를 해결할 수 있겠죠?

     

     

    그렇다면 어떻게 브라우저에서 프레임을 만들까요?

    위에서 설명한 브라우저 렌더링 과정을 VSync 틱(16.6ms)이 발생하면 수행하고 그 다음 VSync 틱이 발생하기 전까지 끝내면 됩니다.

     

     

    하지만.. 굉장히 쉬운 이야기인데, 세상은 그렇게 녹록하지 않습니다.

    기본적으로 브라우저의 모든 컨텐츠들은 메인 스레드에서 처리됩니다.

    최신의 멀티프로세스를 사용하더라도 브라우저는 하나의 싱글코어밖에 사용하지 않는 구조로 되어있습니다.

     

    왜 이런 구조로 만들어졌을까요?

    HTML과 JS는 병렬로 처리할 수 없는 구조입니다.

    다른 스레드에서 간섭하게 되면 섞일 수 있기 때문입니다.

     

    그럼에도 불구하고 만약 병렬로 처리한다고 한다면 어떻게 해야할까요?

    브라우저 렌더링 과정을 다른 스레드에서 처리하기 위해서는 아래 내용을 전부 복사하고 다른 스레드에서 처리하고 메인 스레드로 던져주면 됩니다.

     

     

    근데 이게 어려운게 해당 과정이 굉장히 자주 반복됩니다.

    또한 최신 브라우저의 내용은 굉장히 빠른 속도로 바뀌기 때문에 복사해서 뭔가 처리하고 결과를 돌려주기가 쉽지 않습니다.

    그리고 각 페이지들의 노드 개수가 몇 천, 또는 몇 만 개까지 늘어날 수 있는데, 이런 큰 자료들을 복사하기에는 16.6ms는 부족한 시간일 수 있습니다.

     

     

     

    2.1. Composite Thread

    하지만 웨일, 크롬, 오페라와 같은 최신 브라우저는 이와 같은 문제를 해결했습니다.

    먼저 Compositor Thread를 만들어서 Composite 과정을 메인스레드에서 분리했습니다.

    레이어의 합성은 정보가 그다지 많이 필요하지 않습니다.

    기껏 해봐야 레이어들의 개수, 레이어들의 z-index 정보, 레이어들의 좌표 정보 정도만 메인 스레드에서 복사하면 Compositor Thread에서 합성을 할 수 있습니다.

     

    Compositor Thread를 만들고 해당 작업을 분리해내면 한 가지 부가적인 장점이 생기는데, 스크롤링을 Composite 과정에서 처리할 수 있게 됩니다.

    기존에는 화면을 Main Thread가 가지고 있기 때문에 여기서만 스크롤링을 처리할 수 있었는데, 이제는 Composite도 모든 화면을 가지고 있기 때문에 Main Thread의 도움 없이 스크롤링을 Compositor Thread에서도 처리할 수 있게 된 것이죠.

     

     

     

    그래서 스크롤, 애니메이션, 줌 인, 줌 아웃과 같은 기능Compositor Thread에서 단독으로 처리할 수 있게 되었습니다.

     

     

    2.2. Raster Thread

    하지만 그럼에도 불구하고 아직 Paint 과정은 떼지 못했습니다.

    Paint를 떼기 위해서는 Render Tree가 필요하기 때문이죠.

    이 Render Tree는 굉장히 크기 때문에 한동안 Main Thread에서 분리하지 못하고 있었습니다.

     

    그러나 개발자가 누굽니까?

    이런 어려운 일도 해결해 내는 것이 바로 개발자 아니겠습니까?

    이 문제를 2014년에 Raster Thread를 이용해서 해결해냈습니다.

     

    실제로 브라우저의 개발자도구를 켜면, Rasterizer 과정을 볼 수 있습니다.

     

     

    Raster비트맵을 만드는 과정을 의미합니다.

    조금 더 자세하게 말하면 페인트 해야할 레이어들을 실제 화면의 픽셀로 바꾸는 과정을 의미합니다.

    다시 말해 Raster Thread에서는 비트맵을 만들게 되죠.

     

    그렇다면 어떤 방식으로 Main Thread가 아닌 곳에서 따로 비트맵을 만들 수 있을까요?

     

    이걸 위해서는 새로운 기술 하나를 알아야 합니다.

    SKIA라는 회사에서 "Record and replay" 라는 기능을 만들었는데, draw line이라는 동작이 있다면 해당 동작을 실제로 하지는 않고 keep해둡니다.

    위에서 말한 것처럼 모든 그래픽 커맨드들을 저장해뒀다가 나중에 실행할 수 있는 매커니즘을 만들었고, 이 기법을 크롬에서도 사용을 하고 있습니다.

     

     

    이제 실제로 어떻게 동작하는지를 살펴보겠습니다.

    Main Thread에서는 동작을 Record(저장)만 해둡니다.

    Record 자체는 Paint에 비해서 그렇게 큰 시간이 필요하지 않습니다.

     

    해당 내용들은 Compositor Thread로 넘어가게 되고, Compositor Thread는 각 레이어들을 타일 형태로 나눠서 Raster Thread에게 전달합니다.

    Raster Thread는 Record한 내용을 바탕으로 각각의 타일들을 비트맵으로 만들어냅니다.

    그리고 각 타일들은 Composite 과정이 수행되고, 우리가 보는 화면에 출력되는 것이죠.

    그리고 이렇게 Thread를 분리함으로써 모든 과정을 16.6ms 안에 처리할 수 있게 되었습니다!!

    (Rasterize된 타일들은 GPU로 넘어가서 GPU에서 Composite 과정이 처리될 수도 있습니다! 이 경우 그래픽카드의 성능에 따라 처리 속도가 훨등히 빨라지는 장점을 얻을 수도 있습니다!!)

     

     


    3. VSync를 바탕으로 하는 브라우저 렌더링 과정

    이제는 이렇게 만들어진 프레임들을 어떻게 브라우저가 VSync를 바탕으로 렌더링 하는지에 대해서 알아봅시다.

     

    웨일이나 크롬, 오페라와 같은 브라우저는 멀티프로세스 기반의 브라우저인데, 브라우저를 구성하는 프로세스들이 굉장히 많습니다.

    브라우저 프로세스가 있고, 렌더러 프로세스가 있고, GPU 프로세스가 있습니다.

     

    브라우저 프로세스는 사용자의 입력을 받고 UI를 구성하는 프로세스입니다.

    렌더러 프로세스는 HTML을 파싱하고 Layout을 구성하고, Rendering 하는 모든 일들을 처리합니다.

    그리고 이 렌더러 프로세스들은 GPU 프로세스와 연결됩니다.

     

    기본적으로 렌더러 프로세스는 보안을 위해 샌드박스되어있습니다.

    샌드박스 되어있다는 말은 렌더러 프로세스가 할 수 있는 일은 CPU에서 처리해야하기 때문에, GPU에서 처리할 수가 없다는 말과 같습니다.

    그래서 추가적인 GPU 프로세스를 통해 GPU를 이용해서 화면에 렌더링 하는 과정을 거치게 됩니다.

    (GPU를 사용하게 되면 CPU만 사용하는 것보다 조금 더 효율적으로 처리할 수 있겠죠?! 다만 GPU를 사용함으로써 발생하는 데이터 전송과 같은 cost를 고려할 필요도 있습니다.)

     

     

    3.0. VSync와 사용자 입력

    이번에는 사용자에게 Input을 받는다고 생각을 해보겠습니다.

    각각의 Input값이 들어오는 주기는 VSync가 작동하는 주기와 다릅니다. (사용자가 Input값을 언제 입력할 지는 컴퓨터가 알 수가 없기 때문입니다!!)

    그래서 아래와 같은 혼선이 발생할 수 있습니다.

     

     

    위 두 케이스를 하나씩 뜯어보겠습니다.

    가장 이상적인 경우는 아래와 같습니다.

    Input이 VSync 전에 들어온다면 해당 Input을 바탕으로 VSync가 일어나게 되고, 정상적으로 Draw, Composite 과정이 진행되겠죠?

     

     

    만약 Input이 VSync 이후에 들어온다면 어떻게 될까요?

    해당 Input에 의한 렌더링 처리는 다음 VSync 틱에 처리가 되어서 한 칸씩 밀리게 되겠죠?

    그러면 일정한 프레임을 지키지 못하게 됩니다.

     

     

    그래서 브라우저에서는 Input이 들어오고 나서 VSync 틱을 진행하도록 하는 방식을 사용하고 있다고 합니다.

     

    아래 자료는 지금까지 설명한 내용을 요약한 구글에서 제공한 그림입니다.

    Input이 들어와서 Input을 가지고 touch event를 작동시키고, 그것에 의해 VSync에 의해 프레임을 만들어달라고(BeginFrame) 하게 되면 렌더링 과정이 진행되고 Composite이 최종적으로 진행되어서 해당 VSync 틱의 렌더링 화면이 우리 눈 앞에 보여지게 됩니다.

     

    재밌는 것은 BeginMainFrame을 보면 Layout과 Paint 과정 이전에 Scroll handler, rAF가 존재합니다.

    이것은 Scroll handler, rAF에 의해 변화된 DOM을 바로바로 Layout과 Paint에서 처리하게 된다는 것을 의미합니다.

    여기서 또 하나 알 수 있는 것이, 애니메이션을 만들 때 rAF는 VSync와 같은 사이클로 동작하기 때문에 브라우저의 렌더링 사이클과 다르게 동작하는 DOM Timer보다 훨씬 화면을 자연스럽게(VSync에 맞게) 처리할 수 있음을 알 수 있습니다.

     

     

    3.1. 시간이 남는다면?

    하나의 VSync 틱이 60hz를 기준으로 16.6ms동안 진행된다고 위에서 언급했었죠?

    그런데 만약 Input을 받고 Rendering까지 진행했는데도 시간이 남는다면 어떨까요?

    남는 시간에는 GC(가비지 컬렉션)를 돌린다거나 Idle Callback을 호출합니다.

     

    Idle Callback이라는 개념은 조금 생소할 수 있으니 조금 더 설명해보면!!

    Idle Request Callback이라는게 존재하는데, 여기에 이벤트를 달아놓으면 브라우저가 VSync 틱이 발생했을 때 시간이 남으면 해당 Callback을 실행할 수 있습니다.

    VSync 틱에서 남는 시간을 알차게 사용할 수 있는 것이죠!

     

    즉 브라우저는 이렇게 VSync 틱을 기준으로 Input, Rendering, GC, Idle Callback을 처리한다고 볼 수 있습니다.

     

    3.2. 웨일 브라우저를 통한 복습

    지금까지 설명한 내용들을 웨일 브라우저의 Tracing Tool을 이용해서 다시 한 번 확인할 수 있습니다.

    Tracing Tool은 실제 Internal에서 동작하는 내용들을 Dev Tool보다 훨씬 자세하게 볼 수 있는 도구입니다.

     

    위에서 설명한 내용들을 실제로 확인해 보시죠!!

    아래는 BeginMainFrame 과정을 그래프로 나타낸 그림입니다.

     

    아래는 전체 과정을 표시한 내용입니다.

     

     

    이번에는 20ms에 한 프레임을 찍는 케이스입니다.

    실제로 프레임을 찍는 시간은 20ms가 되지 않지만, Main Thread가 기존에 요청받은 일을 처리하다가 밀려서 처리하는 일이 발생할 수 있다는 내용을 나타내고 있습니다.

     

     


    4. 실제 웹서비스 최적화에 도움 될만한 팁들

    4.0. 파이프라인 작동 위치 알아두기

    어떤 동작이 발생했을 때 어디를 수정하는지를 아는 것은 굉장히 중요합니다.

    어떤 것을 하고 있는지, 무엇을 수정하는 지에 따라 실제 파이프라인에서 어떤 부분들을 수정해야 하는지가 달라지고, cost 역시 달라지기 때문입니다.

    오른쪽으로 갈수록 보다 저렴하고 빠르게 처리할 수 있겠죠?

    (왼쪽에 있는 요소를 변경하게 되면 그 요소부터 오른쪽에 있는 파이프라인 요소들이 모두 동작하게 됩니다.)

     

     

    실제로 어떤 요소가 어떤 파이프라인을 동작하게 만드는지는 이미 잘 정리된 곳들이 많으니 참고하시면 좋습니다.

    개인적으로 CSS Triggers라는 사이트를 애용하니 참고하세요!

     

    CSS Triggers

    @PROPERTY_DESCRIPTION@ B G W E Change from default B G W E Subsequent updates

    csstriggers.com

     

     

    4.1. 각 스테이지별 Cost 확인하고 최적화하기

    Layout이 효율적이기 위해서는 DOM Elements의 개수를 약 1000개정도로 제한하는 것이 좋습니다.

    또한 불필요한 Layout cost를 줄이기 위해 애니메이션을 처리할 때는 transform이나 web animations를 사용하는 편이 좋습니다.

     

    Paint 과정에서 cost를 아끼는 방법에는 GPU Rasterization이 있습니다.

    CPU만 사용하는 것보다 GPU를 같이 사용하는 것이 훨씬 효율적일 수 있겠죠?

    이걸 사용하기 위해서는 meta nameviewport를 작성하면 됩니다.

    그러면 웨일이나 오페라, 크롬과 같은 브라우저에서는 컨텐츠를 GPU를 통해 렌더링하게 됩니다.

     

     

    Compositing 과정에서는 Layer들을 다루기 위해서 메모리를 사용해아 합니다.

    과도하게 메모리를 사용한다면 브라우저가 렌더링 도중에 멈추는 현상이 발생할 수 있겠죠?!

    따라서 무작정 빠르다고 Layer를 늘리는 것보다는 30개 정도로 Layer를 구성하는 편이 좋다고 알려져 있습니다.

     

     

    마지막으로 위의 과정들을 하나의 VSync 틱 안에 처리해야한다는 것을 알아둔다면 웹 서비스를 개발하거나 튜닝할 때 조금 더 효율적으로 개발할 수 있을 것입니다.

     

     


    5. 참고자료

     

    웹 성능 최적화에 필요한 브라우저의 모든 것

    NAVER Engineering | 웹 성능 최적화에 필요한 브라우저의 모든 것

    tv.naver.com

     

    [125]웹 성능 최적화에 필요한 브라우저의 모든 것

    웹 성능 최적화에 필요한 브라우저의 모든 것 이름: 이형욱 소속: NAVER

    www.slideshare.net

     

    Inside look at modern web browser (part 3) - Chrome Developers

    Inner workings of a browser rendering engine

    developer.chrome.com

     

    CSS Triggers

    @PROPERTY_DESCRIPTION@ B G W E Change from default B G W E Subsequent updates

    csstriggers.com

     

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기