최신 Chrome 브라우저 렌더링 방식을 알아보자!

황주현·2022년 10월 24일
101

브라우저

목록 보기
1/1
post-thumbnail
post-custom-banner

들어가며

개요

브라우저 렌더링 방식에 대해 설명해보시겠어요?

브라우저에 google.com을 검색하면 어떻게 되는지 설명해주세요.

프론트엔드 면접 질문 하면 빠지지 않는 단골 주제는 바로 브라우저의 렌더링 방식 이라고 할 수 있다.
아마 이 글을 보게된 사람들도 면접을 준비하며 온 경우가 많을 것 같다.

이걸 준비하다 보면 이런 생각이 들게 된다.

아니 외우라니까 외우긴 하는데... 대체 이게 프론트엔드랑 무슨 상관이지? 개발만 잘 하면 되는거 아닌가? 😒


사실 이건 내가 처음 했던 생각이었다. (ㅎㅎ;;;)

물론 그렇다고 프론트엔드 면접에 낚시는 어떻게 하나요? 정도의 아예 쌩뚱맞은 것이라고는 생각하지 않았고,

"알면 좋기야 할거같은데... 이게 필수로 알아야 할 정도로 중요한건가?" 라는 생각을 했었다.

이번에는 예전의 나와 같은 생각을 하는 사람들에게 최신의 렌더링 방식을 설명하고 왜 필요한지에 대한 필요성까지 와닿게 해주고자 정리해보려 한다.



근데 왜 때문에 최신?

아니 렌더링 방식 설명하는건 그렇다 치는데... 최신이라는 어그로는 좀.... 🤭

글을 시작하기에 앞서 최신 이라는 키워드에 잠깐 설명을 하고자 한다.

이 주제를 검색해 본 사람은 알겠지만 정말 많은 게시물들이 있다.
그리고 그 중 가장 유명한 아티클은 아마 네이버 D2의 번역 아티클 브라우저는 어떻게 동작하는가? 일 것이다.

(스크롤 길이도 장난 아니다)

이 아티클의 원본, 그리고 번역본은 정말 자세하게 잘 설명되어 있다.
그래서 그런지 다른 블로그의 아티클을 보게되면, 이 글을 참조한 글이 정말 많이 보인다.

근데 사실 이 번역 아티클은 2012년 5월 18일에 작성되었고,
원본 아티클은 무려 2011년 8월 5일에 작성되었다.

현재 작성하는 일자 기준으로 약 11년 정도가 흐른 정보라는 것이다.

나는 이 아티클들의 내용이 잘못됐다고 생각한다기 보다는,
오랜 시간이 흐른 만큼 기술적으로 변경된 부분이 있을거라 생각했다.

이 같은 이유로 최신을 붙여 작성한 글이니 최신 이라는 키워드에 오해하지 않았으면 좋겠다!
(무섭다!)



본격적으로 알아보자

브라우저는 뭐지?

렌더링을 알아보기 전에, 일단 브라우저가 뭔지부터 짚고 넘어가 보자.

여기서 브라우저란

  • 사용자가 갖고자 하는 자원을 서버로 요청하고,
  • 응답 받은 자원을 브라우저에 알맞게 표시하는 행위

를 해주는 소프트웨어~ 라고 보면 된다.

다들 잘 아는 크롬, 파이어폭스, 사파리, 엣지, 인터넷익스플로어(IE) 가 있다.
이번에 작성하는 게시글은 크롬 기준의 렌더링 방식이다.



렌더링 과정은 뭘까?

한번 크롬으로 벨로그 글을 본다 생각해보자.
(DNS 등 중간 과정 없다고 가정)

우선 우리는 브라우저의 주소창에 주소를 적고 엔터를 칠거다.

그럼 브라우저는 입력된 주소값으로 GET 요청을 보내게 된다.
(GET 을 모른다면 이거 공부할때가 아니다. 그것부터 공부해보자.)

요청을 받은 서버는 알맞은 HTML, CSS 파일을 브라우저 에게 다시 보내줄거다.


근데 만약 브라우저가 이후에 아무런 과정 없이 그냥 보여준다면 아래처럼 보일거다.


즉 렌더링이란 앞서 말한 브라우저의 과정 중

응답 받은 자원을 브라우저에 "알맞게 표시하는 행위"

라고 할 수 있다.



렌더링 프로세스와 쓰레드 구성

렌더링 과정은 Renderer Process(렌더러 프로세스)가 담당하게 된다.
Process 내부에는 몇 가지 Thread(쓰레드)가 구성되어 있는데, 이는 아래와 같다.

프로세스? 쓰레드? 무슨 말인지 하나도 모르겠네... 😢

간단하게 생각해서 Renderer Process집 짓기 프로젝트 라면,
각각의 Thread프로젝트에 참가하는 일꾼들이라고 생각하면 된다.

Thread의 역할은 아래에서 다시 설명한다.



렌더링 전체 과정

렌더링의 전체 과정은 8개의 단계로 나눌 수 있다.

  1. Parsing
  2. Style
  3. Layout
  4. Layer
  5. Paint
  6. Tiling
  7. Raster
  8. Draw Quad

각 단계들은 하나의 Main Thread가 아닌 경우에 따라 다른Thread에서 실행이 되는 걸 볼 수 있는데, 이는 최적화를 위해서다.

만약 하나의 Main Thread에서 모든 걸 처리한다면 화면에 지연이 발생 할 것이고, 뚝뚝 끊기는 화면을 보게 될 것이다.

때문에 각각의 역할에 따라 Thread를 분리해서 사용한다.



Main Thread

1. Parsing

파싱해봐
그거 파싱 결과가 어떻게 돼?

이런 이야기를 어디서 한번 쯤 들어본 사람이 있을 거다.

위키백과에서는 / 어떤 문장을 / 그것을 이루고 있는 구성 성분으로 분해하고 / 그들 사이의 위계 관계를 분석하여 / 문장의 구조를 결정하는 것을 말한다 라고 작성되어 있다.

우리가 궁금한 브라우저 렌더링에서의 Parsing 단계는 HTML 코드를 DOM Tree로 만드는 것이다.
(Tree를 모른다면 이걸 공부할 때가 아니다! Tree부터 차근차근 공부해보자!)


여기서 '어떤 문장'HTML 코드라고 생각해보자.
보통 HTML 코드는 아래처럼 생겼다.

<html>
  <body>
    <h1>제목</h1>
    <div><p>내용</p></div>
  </body>
</html>

코드를 보면, html이루고 있는 구성 성분으로 Tag가 존재한다.
<html>, <body>, <p> 같은 태그라고 볼 수 있다.

그리고 이들의 위계관계는 태그의 깊이 정도로 생각할 수 있을거다.

구성성분 : 태그
위계관계 : 태그의 깊이

그럼 이를 토대로 Tree 로 바꾸면 이렇게 표현된다.

이 처럼 Parsing 단계 에서는 HTML 코드를 Tree 구조로 만드는 것이다.



2. Style

우리에게 있는 것 : DOM Tree

현재 우리는 DOM Tree를 가지고 있지만, 이걸로는 화면을 보여줄 수 없다.
각 요소들이 어느정도 크기인지, 글꼴은 무엇을 쓰는지, 색깔은 어떻게 되는지 알아야 한다.

Style 단계에서는 CSS 파일을 계산해 Computed Style을 도출해낸다.
이 단계에서 %, em, rem 같은 상대적 수치들도 모두 px로 계산된다.

관리자 콘솔에서 Computed 탭이 바로 그 내용이다.

잉? 저는 아직 css 파일 작성 안했는데, 그래도 Computed Style이 보이는데요? 🤔

이건 브라우저가 기본적으로 가지고 있는 기본 세팅 CSS 파일이 존재하기 때문이다.
구글 Chromium의 Default CSS 파일은 여기서 확인할 수 있다.



3. Layout

우리에게 있는 것 : DOM Tree with Computed Style

어떤 요소가 있는지도 알고 색상, 크기도 아니까 이제 화면 그릴 수 있겠네요? 😏

라고 생각이 들었다면 한번 아래의 예시를 보자.

친구에게 뭐가 있고, 어떤 색상인지도 얘기해 주었지만 친구는 그릴 수가 없었다.
그 이유는 뭘까?

바로 어디에 어떻게 배치할지를 몰랐기 때문이다.
이 대로 그림을 그렸다가는 친구가 원하는 그림이 나오지 않을 것은 당연하다.

Layout 단계에서는 이 같은 x, y좌표와 요소의 크기에 대한 정보를 계산한 Layout Tree를 만들어낸다.

이는 DOM Tree를 가지고 만드는데, display:none과 같은 표시되지 않는 요소들을 제외하고 Layout Tree를 만든다.



4. Layer

우리에게 있는 것 : DOM Tree, Layout Tree

자, 우리는 이제 요소도 알고 크기도 알고 위치도 안다.
이제 정말 그릴 수 있을까?

정답은 이다.
이유는 뭘까?

바로 뭘 먼저 그려야 할 지 모르기 때문이다.

엥? html 그거 순서대로 적힌대로 그리면 되잖아요 ㅋㅋ 😋

문제는 무조건 html 코드 순서대로 그려지는게 아니기 때문이다.
그림의 z-index 같은 css 요소가 있으면 그거에 따라 그리는 순서를 달리 해주어야 한다.

그 외에도 position:absolutetransform 같은 css가 있다면 맞춰서 처리해야한다.

때문에 Layout Tree에서 필요한 부분만 골라 Layer를 생성해 Layer Tree를 만들어준다.

Layer를 Chrome에서 확인하고 싶다면?

개발자 도구에 Layer를 확인할 수 있는 탭이 있다.
(이건 정리하면서 처음 알았다.)

F12로 개발자도구를 켠 후 우측 상단의 More tools에서 Layers를 클릭하면 된다.

(예시는 네이버 사진)

여기까지만 보면 이게 뭐가 다른거지? 싶은데.. 이걸 기울여보면....

(!!!!!!!)

페이지가 입체적으로 나타나며 어떤게 더 위에 있는지 알 수 있게 되었다.
앞서 말한 transform 같은 속성이 없으면 평면으로 나타내 보여지고, 아니면 입체적으로 표시된다.

그 예로 우측 하단의 광고사진의 CSS를 확인해보면 transform:translateZ(0)가 있는게 확인된다.



5. Paint

우리에게 있는 것 : DOM Tree, Layout Tree, Layer Tree

우리는 이제 Layout TreeLayer TreePaint Record (=페인트기록)을 만들거다.

Paint RecordAction, Position, Style로 구성되어 있다.
Paint Record는 위에서 확인한 Layers 탭에서 Paint Profiler로 확인 가능하다.

Action : drawRect
Position : left:0, top:0, right:1903, left:3277
Style : color '#FFF', strokeWidth:0, ...etc



잠깐!

지금까지 Main Thread에서 일어나는 일들을 알아봤다.
나온 내용이 정말 많았으니 잠깐 쉬어가며 최적화에 대해 잠시 생각해보자.

렌더링 최적화?

지금까지 진행되는 프로세스를 한번 생각해보자.

우리는 DOM TreeStyle Computed를 이용해 Layout Tree를 만들고, Layer Tree를 만들고, Paint Records 까지 만들었다.

즉, 앞선 결과를 이용해 다음 작업을 진행했다는 것이다.

DOM Tree -> Layout Tree + Layer Tree -> Paint Records

여기서 만약 Layout Tree가 조금만 변하게 된다면, 그 후의 과정들을 전부 다시 계산해야 한다.

대부분의 아티클에서 "렌더링 최적화를 위해서는 ~~~ 해야한다." 등의 이야기가 나오는 이유는 바로 이것이다.

이 같은 최적화 방법들은 동일한 계산을 최대한 덜 하도록 해서 속도를 높이는 것에 있다.

이런 렌더링 일련의 과정들을 잘 이해하고 있어야, 어떤 부분에서 최적화를 할 수 있을 지 생각할 수 있다.

이게 우리가 렌더링 과정을 공부하는 이유라고 할 수 있다.


Other Thread

머리도 식혔으니 이제 남은 것들을 알아보자!

이제 3가지 단계만 남았다.
이는 Main Thread가 아닌 각각 Compositor Thread, Raster Thread 에서 진행된다.



6. Tiling

Tiling 단계는 Paint RecordsTile(그 타일 맞음)을 만드는 단계이다.
잘못된 단어 수정 Till -> Tile / ctdlog님 감사합니다 :)

한번에 전체를 렌더링하는 것이 아닌, 필요한 부분만 우선적으로 렌더링 하기 위해 조각조각 나누는 것이다.

velog 메인페이지를 예로 들면 아래와 같다.

velog의 메인페이지는 Document, Scroll Bar 두 개의 레이어가 확인된다.
Document레이어를 Tile로 쪼개면 아래와 같이 나타날 것이다. (예시)

여기서 브라우저는 Viewport에서 보여져야 하는 Tile을 우선적으로 렌더링한다.
이 예제에서는 ①, ②, ③, ④ Tile이 이에 해당된다.

왜 굳이 Tile을 나눠서 하나요? 어차피 다 할 건데.. 🙄

이 다음 단계는 Raster로, 실제 우리가 보는 형태로 비트맵 이미지를 출력해주는 단계이다.

이 단계는 시간이 꽤 소모되므로 큰 하나의 전체 화면을 Raster 하게되면 업데이트 되는 시간이 오래 걸리게 된다.
(토렌트 동작방식 생각해보면 좀 이해가 쉽다)

따라서 속도를 위해 Tile로 쪼개고 Viewport에서 보여져야 하는 Tile를 우선적으로 Raster 하는 것이다.



7. Raster

Raster, 일명 래스터화 라고 불리는 과정은, 화면을 픽셀로 변환하는 작업을 일컫는다.

앞서 진행된 Tile들을 가지고 실제 화면에 보여질 비트맵을 만들어주는 과정이다.
이는 Compositor Thread가 아닌 Tile마다 각각의 Raster Thread 에서 진행된다.

각각의 타일들의 Raster가 완료되면 GPU Memory에 비트맵을 저장하고,
이후 Compositor Thread로 다시 넘겨준다.



8. Draw Quad

드디어 끝!!!!.. 아닌가요 ?? 😥

우리에게 이제 실제 화면에 보여줄 이미지(Bitmaps)가 생겼다.
하지만 이걸 바로 보여주면 어떻게 될까?

정확히 이렇진 않더라도 정상적이진 않을거다.
때문에 우리는 마지막으로 RasterBitmaps들을 다시 합성해주는 과정이 필요하다.

마지막 단계는 Raster가 완료된 Bitmaps들을 이용해 Compositor Frame을 만드는 과정이다.
여기서 Draw QuadsCompositor Frame을 생성하기 위한 Tile의 정보를 의미한다.



마지막. 렌더링

이제 정말 끝났다.
이전 단계에서 나온 Compositor FrameGPU로 보내 화면 렌더링을 진행하면 끝이난다.



정리

(여기까지 읽으셨다면, 고생 많으셨습니다.)

우리의 생각보다 브라우저는 정말 많은 일을 하고 있었다.
지금 굉장히 축약해서 적어놓은 것이지, 사실 훨신 더 많은 내용들이 있다.

이 글만 읽는 것이 아닌, 첨부한 Reference를 참고해 더 자세히 공부해보는 것을 추천한다. (진짜 완전 추천)
(만약 이 글에 틀린게 있다면 Reference에 있는 게 맞다.)

+ 읽어주셔서 감사합니다.
+ 오타, 내용 지적, 피드백을 환영합니다. 많이 해주실 수록 제 성장의 밑거름이 됩니다.

Reference

  1. Inside look at modern web browser (part 3) - Mariko Kosaka
  2. 최신 브라우저의 내부 살펴보기 3_렌더러 프로세스의 내부 동작 - 네이버 D2
  3. Renderingng-data-structures

(글을 정리하다가 안건데, 네이버 D2에서 이 아티클도 번역을 했었다. (갓이버))
(원문의 Part3 이외의 다른 Part도 읽어보면 좋다.)

profile
반갑습니다. 프론트엔드 개발자 황주현 입니다. 🤗
post-custom-banner

12개의 댓글

comment-user-thumbnail
2022년 10월 29일

와우... 주현쓰 정성글이네!! 추천하고 갑니다 :)

1개의 답글
comment-user-thumbnail
2022년 10월 31일

정말 재미있어서 숨을 쉴 수 없습니다. 맙소사, 이와 같은 지식은 어디서 오는 것입니까? 혹여 가보로 내려옵니까? 나의 공중제비를 멈추게 하십시오! 당신과 같은 분들 덕분에 숨을 쉴 수 없습니다. 당신과 같은 똑똑한 분들 덕분에 인생이 굉장히 재미있습니다. 그러한 지식은 비밀히 보관하지 말고, 재빨리 내용물을 꺼내 주십시오. 세상에 이런 정리글이 다 있겠습니까? 완전한 공부 기계가 틀림 없습니다. 좌뇌, 우뇌, - 모두 망가지고 말았습니다. 나의 뇌를 보상해 내십시오! 이것은 살인 지식입니다! 호흡이 곤란합니다! 제발 목숨을 살려 주십시오!

1개의 답글
comment-user-thumbnail
2022년 10월 31일

지립니다! 글 잘 보고갑니데이

1개의 답글
comment-user-thumbnail
2022년 11월 8일

저는 공부를 하지 않습니다. 이 블로그를 보면 되거든요ㅎㅎ

1개의 답글
comment-user-thumbnail
2022년 11월 10일

좋은 글 잘 읽었습니다! 다만 6. Tilling 부분에서 타일(tile)을 깐다라는 의미로, tilling이라는 단어를 사용한 것 같아 till이 아닌 tile이 맞는 것 같습니다. Chrome Developers에 있는 원본 글도 tile 이라고 적혀있더라구요.

1개의 답글
comment-user-thumbnail
2023년 1월 31일

혹시 Chrome에서 Performance로 녹화했을 때 메인쓰레드에서 Paint 작업을 마친 후 Composite Layers가 나타나는 것은 어떤 작업을 하는 것인지 알 수 있나요? 분명 컴포지터 쓰레드에게 일을 위임해서 끝나야 할 것 같은데 꽤 긴 시간 잡고 있어서요

1개의 답글