브라우저 렌더링 과정 요약

pds·2022년 11월 30일
2

TIL

목록 보기
18/60

을 알아보자!


사실 브라우저가 어떻게 동작하여 사용자에게 페이지를 보여주는지도 잘 모르는 상태에서

어쩌다보니 리액트의 렌더링 방식을 먼저 접하게 된 것 같다.

사용자에게 웹 페이지가 보여지기까지의 과정 중 브라우저의 동작에 대해 간단하게 요약해 정리해보았다.


브라우저는 어디에

하나의 웹 사이트가 사용자에게 보여지기 까지의 과정이 요약되어 담긴 "그 아키텍쳐"

우리가 알아볼 건 11번으로 부터 웹페이지 데이터를 얻어서 12번으로 사용자에게 보여줄 때 까지의 과정이다!


결국 브라우저라는건 클라이언트 쪽에 위치한 것이고

간단하게 생각해보면 웹 서버로부터 보여주고자 하는 데이터를 얻어와 사용자에게 보여주는 역할을 하는 것이다.



브라우저 구조


user interface

말 그대로 사용자 인터페이스. 우리가 보고 있는 화면이고 브라우저와 사용자 간 상호작용의 접점이다.


Browser Engine

UI와 렌더링 엔진 사이에 위치하여 사용자 상호작용에 대한 쿼리를 날려 렌더링 엔진을 컨트롤 한다.


Rendering Engine

HTML,CSS,XML등을 파싱하여 사용자가 요청한 사이트를 그린다.

브라우저마다 다른 렌더링 엔진을 가지고 있다.


Networking

HTTP 요청과 같은 네트워크 호출에 사용된다.


Javscript Interpreter

자바스크립트 코드를 해석하고 실행한다.


Data Persistence

쿠키,캐시,로컬스토리지 등이 저장되는 곳


브라우저 렌더링 과정 기초

자 그래서 서버로부터 HTTP통신으로 얻어온 웹 페이지 데이터를 이제 사용자에게 보여줘야 한다.

브라우저가 이를 수행할텐데 어떻게 수행하는지 간단하게 과정을 확인해보았다


근데 왜 알아야 할까

웹 개발 시 사용자 경험 과 관련하여 직면하게 되는 문제가 많다.

느린 리소스 로딩, 불필요한 파일 다운로드 FOUC(초기 스타일이 적용되지 않았다가 적용되는)

등의 문제에 대해서 다루고자 한다면 브라우저가 일반적으로 어떻게 웹 페이지를 렌더링하는지 이해하고 있다면

어떤 방법의 무슨 프레임워크를 사용하던 사용자 경험 향상을 위해 더 빠르게 적응하고 쉽게 적용할 수 있지 않을까 생각한다!


HTML파싱, DOM 생성

서버에서 HTML을 내려받을 때 브라우저는 기본적으로 Conetent-Type: text/html

byte stream 형태로 이를 가져오게 된다.

text/html 라는 MIMETYPE을 보고 파싱하여 브라우저가 이해가능한 노드 트리 자료구조인 DOM으로 생성한다.

변환 : 브라우저가 HTML의 원시 바이트를 읽어와서, HTML에 정의된 인코딩(예: UTF-8)에 따라 개별 문자로 변환합니다.

토큰화 : 브라우저가 문자열을 W3C 표준에 지정된 고유 토큰으로 변환합니다.

렉싱 : 방출된 토큰은 해당 속성 및 규칙을 정의하는 “객체”로 변환됩니다.

DOM 생성 : 마지막으로 HTML 마크업에 정의된 여러 태그 간의 관계를 해석해서 트리 구조로 연결이 됩니다.

이 단계를 HTML마크업을 처리할 때 마다 수행한다.


CSS 파싱 CSSOM 생성

HTML처럼 CSS도 내려받아 순차적으로 읽고 스타일을 적용하도록

트리구조를 DOM트리를 형성하는 방법과 동일하게 생성한다.

DOM과 달리 CSSOM은 숨겨져 있지만 추후 설명할 render-tree에 포함되어 노출되고

개발자가 CSSOM 노드의 css 속성에 접근할 수 있다.


render tree

Render-Tree도 DOM과 CSSOM 트리를 함께 결합하여 구성된 트리와 같은 구조이다.

렌더트리를 사용하요 브라우저에 보이는 레이아웃을 계산하고 페인팅한다.

최종적으로 화면에 보여질 항목들에 대한 것들로

픽셀 매트릭스 영역에 포함되지 않는 노드는 포함되지 않는다. display:none, 0px 등


이렇게 렌더 트리를 형성하면 브라우저가 이제 화면에 각 요소를 출력하게 된다.

그 과정을 알아보자


Layout operation

각 개별 Render-Tree 노드의 레이아웃을 만든다.

브라우저가 각 노드의 레이아웃 정보를 계산하게 되고

레이아웃은 픽셀 단위의 각 노드 크기와 화면에 인쇄될 위치로 구성된다.

사용자 이벤트 등으로 새로운 HTML요소가 변경되거나하여 렌더 트리가 다시 만들어지고

레이아웃 동작을 다시 수행할 때 이런 과정을 reflow 라고 함

position, width, height, margin, padding, border, border-width, font-size, font-weight, line-height, text-align, overflow, visibility


Painting operation

요소들의 위치와 크기, 스타일 계산이 완료된 Render Tree 를 이용해, 픽셀 값을 채워넣게 된다.

마찬가지로 렌더 트리가 변경되었을 때 다시 그리는 것을 repaint라고 함

단 레이아웃에 변경이 없는 단순 색상 같은 변화에 대해서는 reflow없이도 repaint가 일어난다.

background, color, text-decoration, border-style, border-radius

reflow의 발생은 반드시 repaint가 일어난다

따라서 repaint만 일어나도록 최적화 하는 것이 적절할 것이다.

예를 들어 visibility는 레이아웃 공간이라 reflow의 대상이지만

display는 레이아웃 공간이 아니라 reflow가 일어나지 않는다던가

transform, opacity 같은 경우는 repaint도 발생하지 않는다고 한다.



Parser-Blocking Resources

HTML구문 분석 도중 자바스크립트 파일/코드 같은 파서 차단 자원들을 만나면

먼저 실행한 후 HTML 구문 분석을 다시 진행하는 것이다.

심지어 외부 자바스크립트 파일을 만나면 다운로드 하면서까지 기존 구문 분석을 중지시킨다.

메인 스레드 하나가지고 저러는데 같이 진행하면 안되나?


왜 자바스크립트를 먼저?

브라우저는 자바스크립트 런타임 시점에 DOM을 노출하여 접근할 수 있게 해준다.

React 같은 것들의 방식이 이런 것이다.

멀티스레드로 자바스크립트 읽기와 DOM 형성을 동시에 하게 되면

뭘 먼저 읽어서 처리해야 할 지 모르는 race condition이 발생할 수 있어 메인 스레드 하나로 순차적으로 돌린다고 한다.

하긴 읽는 순서가 보장이 안되어있으니 어쩔 땐 스크립트에서 특정 돔을 읽고 어쩔 땐 못 읽고 하는 더러운 상황이 나올 것이다.


굳이 동기적일 필요가 없다면??

자바스크립트 파싱으로 인한 DOM tree 형성 중단 문제를 해결하기 위한

HTML5에서 script 태그에 제공하는 defer async 옵션 사용

단 외부 자바스크립트 파일을 로드할 떄만 사용 가능

//예
<script async src="extern.js"></script>

async 같은 경우는 자바스크립트 로드하면서 DOM 만들지만 로드 다되면 DOM parsing을 중단 한다.

defer 같은 경우는 DOM 형성 완료된 직후 스크립트를 파싱해 실행한다.


style 태그도 파서 차단의 대상??

<style> 태그를 만나면 DOM 업데이트를 중단하고 CSSOM 트리를 먼저 업데이트한다고 한다.


외부 css는 아니다

외부 스타일 파일은 파서 차단의 대상이 아니라고 한다.

따라서 DOM 파싱 도중 외부 스타일 파일을 만나도 블로킹 되지 않고 계속 파싱한다.


하지만 css는 렌더링 차단 리소스는 맞다

이 부분은 솔직히 너무 어려워서 완전 이해하지는 못했다.

간단하게 이해한 만큼 작성해보면

내부 인라인 스타일이나 스타일 태그 같은 경우는 진행을 멈추고 읽는다니까 괜찮은데

외부 css를 만났을 때 백그라운드에서 DOM 트리 구성은 계속 진행한다.

하지만 화면에는 보여주지 않는 것이다

왜냐하면 외부 CSS파일을 읽어 CSSOM을 형성하고

그게 다 업데이트 되어야 render-tree를 구성할 수 있기 때문이다.

한 번에 업데이트 시키는 이유가 솔직히 잘 이해가 안된다.

참고자료의 말로는 다중 렌더링, 스타일링 순차적용 문제 방지, 사용자에게 스타일의 변화를 페이지에 보여줄 때 불쾌함? 이런식으로 설명한 것 같다.

영어라 해석이 너무 오래걸린다.


결론은 어떤 방식으로 스타일을 적용해도 모두 CSSDOM에 쌓여야 render-tree를 형성해 렌더링 해준다는 것이다 결국은 렌더링이라는 것은 스타일을 기다린다


그 외 css도 렌더링을 블로킹하지 않는 방법이 있어 상황에 맞게 로드한다거나

스크립트에서도 css에 접근할 수 있기 때문에 발생하는 비동기적 문제 때문에 대부분의 브라우저가 css가 모두 적용되어야 스크립트가 실행될 수 있다는 내용도 있다.


주의점

브라우저는 딱히 표준이라고 하나 정해져있지 않다.

어떤 브라우저를 사용하냐에 따라 동작 방식이 조금씩 다를 수 있다는 것이다.

추후 많이쓰는 브라우저들 간 동작의 차이를 알아보아야 겠다.



Reference

profile
강해지고 싶은 주니어 프론트엔드 개발자

0개의 댓글