안녕하세요
하나의 웹페이지를 보여주기 위해서 브라우저를 우리 생각보다 꽤 많은 일을 하고있습니다.
구성 요소
브라우저의 주요 구성 요소는 아래와 같습니다.
1. 사용자 인터페이스
주소 표시줄, 이전/다음/새로고침 등 웹페이지를 제외한 나머지 모든 부분입니다.
2. 브라우저 엔진
사용자 인터페이스(1번)와 렌더링 엔진(3번)을 연결합니다.
3. 렌더링 엔진
HTML과 CSS를 파싱하여 요청한 웹페이지를 화면에 표시합니다.
4. 통신
HTTP 요청과 같은 네트워크 요청을 수행합니다.
5. UI 백엔드
체크박스나 버튼 같은 기본적인 위젯을 그려줍니다. OS 사용자 인터페이스 체계를 사용합니다.
6. 자바스크립트 해석기
자바스크립트 코드를 실행하는 인터프리터입니다. (ex. chrome - V8)
7. 자료 저장소
로컬스토리지나 쿠키와 같이 모든 종류의 데이터를 저장합니다.
렌더링 엔진
렌더링 엔진은 통신으로부터 요청한 문서의 내용을 얻는 것으로 시작합니다.
1. DOM Tree 생성, CSSOM Tree 생성
2. Render Tree 생성
3. Render Tree 배치 -> Layout(Reflow)
4. Render Tree 그리기 -> Paint (Repaint)
요청한 문서 (html, css, javascript, image 등)를 토대로 위와 같은 순서대로 작업이 일어나게 됩니다.
하나씩 살펴보겠습니다.
1. DOM Tree 생성, CSSOM Tree 생성
html, css 코드만으로는 사용자에게 정보를 전달할 수 없습니다.
먼저 브라우저가 코드를 이해하고 사용할 수 있는 구조로 변환(문서 파싱)해야합니다. 파싱 결과는 보통 문서 구조를 나타내는 노드 트리입니다. "파싱 트리" 또는 "문법 트리"라고 부릅니다.
html문서는 토큰으로 변환됩니다.
<html>
<head>
</head>
<body>
<p>Hello world</p>
</body>
</html>
토큰은 시작 태그, 종료 태그, 속성 이름, 속성 값입니다.
위 코드에서는 토큰화를 이렇게 할 수 있습니다.
html시작태그
head시작태그
head종료태그
body시작태그
p시작태그
텍스트
p종료태그
body종료태그
html종료태그
토큰은 노드 객체로 변환됩니다.
그리고 각 노드 객체간 연관성을 가질 수 있도록 트리를 생성합니다. 이것이 바로 Dom Tree입니다.
CSS를 Dom tree와 동일하게 트리 형태로 이루어져 있으며 이는 CSSOM Tree라고 부릅니다.
CSSOM은 DOM과 유사하지만 다릅니다. CSS는 규칙을 덮어쓸 수 있기 때문에 모든 CSS를 처리하고 수신할 때까지 렌더링을 막습니다.
2. Render Tree 생성
만들어진 DOM Tree와 CSSOM Tree로 Render Tree를 생성합니다.
렌더 트리는 Dom트리의 root에서 시작해 모든 노드를 확인하며 어떤 CSS를 첨부할지 결정합니다.
모든 트리를 렌더 트리에 추가하지는 않습니다. meta 태그, head 태그와 같은 비시각적 DOM 요소는 렌더 트리에 추가되지 않습니다.
display 속성이 "none"인 요소 또한 트리에 추가되지 않습니다.
3. Render Tree 배치 -> Layout(Reflow)
렌더 트리를 생성하였으면 이제 배치를 해야 합니다.
뷰표트 즉 보이는 기기 화면에 따라서 사이즈가 다르기 때문에 그 값을 측정해야 합니다.
(css - %, em, rem 같은 상대적인 단위는 px 단위로 계산되어 보여줍니다.)
4. Render Tree 그리기 -> Paint (Repaint)
모든 준비가 끝났으면 그려주어야 합니다.
글 하단에 링크를 통해 들어가시면 보다 더 자세한 과정을 보실 수 있습니다.
동적 변경
스크립트로 UI가 변경될 때가 있습니다. 브라우저는 변경에 대해 가능한 최소한의 동작으로 반응하려고 합니다.
요소의 크기나 위치, 브라우저 창의 크기가 바뀌면 사이즈를 다시 측정해야 하기 때문에 Layout 부터 다시 발생합니다.
레이아웃의 수치를 변화시키지 않고 배경 이미지, 색상 등 스타일이 변경되면 Paint 부터 다시 발생합니다.
layout 과정 이후에 정해진 기준에 따라 트리 형태의 레이어가 만들어지고, paint 과정에서 그려줍니다.
레이어가 합성되는 경우에는 layout, paint 과정이 일어나지 않기 때문에 성능상으로 큰 이점을 가집니다.
요소가 바뀌면 요소와 자식, 형제의 리페인팅과 재배치가 발생되지만,
html의 글꼴 크기를 변경하는것과 같은 큰 변경은 캐시를 무효화하고 트리 전체의 배치와 리페인팅이 발생합니다.
Optimizing for CRP
총 4단계의 과정을 알아보았습니다.
이를 CPR(Critical Rendering Path) 이라고합니다.
CRP를 최적화하면 페이지 로드 시간을 단축시킬 수 있습니다.
* 자원 다운로드를 연기함으로써 중요 자원들의 수를 최소화합니다.
* 각 파일 사이즈에 따라 필수적인 요청 횟수를 최적화합니다.
* 다운받을 중요 에셋의 우선순위를 정함으로써 중요 자원 불러오는 순서를 최적화하고, 중요 경로 길이를 최소화합니다.
여기서 말하는 자원은 자바스크립트 파일 등을 뜻한다고 생각합니다.
파싱 하는 하는 과정에서 <script>를 만나면 스크립트가 실행되는 동안 파싱은 중단됩니다.
따라서 "defer(지연)" 속성을 추가합니다. 지연으로 표시하게 되면 문서 파싱은 중단되지 않고 파싱이 완료된 후에 스크립트가 실행됩니다. body의 맨 마지막에 script 태그를 추가하는 것도 이러한 이유 때문입니다.
마치며
최근 기본기를 다지고 있습니다.
처음에 이 글을 쓸 때는 무슨 말인지 잘 이해를 하지 못했지만 글을 작성하면서 점차 이해를 하기 시작했습니다.
지난 경험들을 생각하며 그 당시의 문제점을 곱씹을 수 있었고 하나씩 실마리가 풀리는 느낌이었습니다.
기초가 탄탄해야 올라갈수록 흔들리지 않는다고 생각합니다.
글을 작성하는데 오랜 시간이 걸렸지만 아깝지 않은 시간이었습니다.
읽어주셔서 감사합니다.
참고 :
https://www.youtube.com/watch?v=sJ14cWjrNis
https://d2.naver.com/helloworld/59361
https://developer.mozilla.org/ko/docs/Web/Performance/Critical_rendering_path
'Front-end > 깊게 파고들기' 카테고리의 다른 글
Javascript 클로저(Closure) 정리 (0) | 2022.04.05 |
---|---|
Virtual DOM 이란? (0) | 2022.03.21 |
var, let, const 차이점 (호이스팅, 스코프) (0) | 2022.03.19 |
클린 코드란 무엇일까 (0) | 2022.03.02 |
React-Reudx 정리 (0) | 2022.01.27 |