웹 브라우저는 원래 웹서핑 전용 애플리케이션에 불과했다. 그러나 HTML5 등이 발달하면서 웹 브라우저는 점차 기능이 확대되었고, 2020년대 들어서는 거의 모든 프로그램의 기능을 잡아먹고 있다. - 나무위키
나무위키에서 나온 것처럼, 책 [커리어 스킬]에서는 모바일 웹앱이 미래라고 하기도 한다. 나중에는 브라우저에 대해 더 깊게 파서 공부해야겠다는 생각이 들었다.
먼저 브라우저를 구성하는 요소들을 살펴보려한다.
User Interface
: 웹 페이지를 제외한 영역 (ex: 북마크, 주소 표시줄)
Browser Engine
: UI, Rendering Engine 사이의 동작을 제어
Rendering Engine
: html, css를 이용해서 화면을 보여주는 영역
NetWorking
: HTTP 요청
Javascript Interpreter
: 코드를 해석하고 실행
UI Backend
: 기본적인 위젯을 그리는 인터페이스 (ex: input)
Data Storage
: 데이터를 저장하는 계층 (ex: cookie, local storage)
브라우저는 아래의 과정을 거치면서 우리가 볼 수 있게 화면을 만들어준다.
DOM tree가 생성되고 CSSOM tree가 생성되면, 렌더 트리
가 그려지고,
렌더 트리
를 기반으로 layout과 paint 과정을 거쳐 화면에 렌더링한다.
서버가 어떤 요청을 받으면, 서버는 브라우저의 렌더링 엔진에게 html 문서
를 준다.
렌더링 엔진은 html 문서를 파싱
해서 DOM(Document Object Model)을 만든다.
렌더링 엔진은 DOM을 생성하다가 link 태그
를 만나면 DOM 생성을 일시중단한다.
<head>
...
<link rel="stylesheet" href="style.css">
</head>
그리고 html 문서를 파싱하듯, css를 파싱
하고, CSSOM(CSS Oject Model)을 만든다.
이렇게 만들어진 DOM과 CSSOM은 렌더 트리
로 결합된다.
단, 모든 CSS 속성이 렌더 트리에 포함되는 것은 아니다.
p { display: none; } // 공간 차지하지 않아서 포함X
p { visibility: hidden; } // 가리기만하고 공간을 차지해서 포함O
지금까지는 표시할 노드(DOM)와 해당 노드의 계산된 스타일(CSSOM)을 계산했다. 하지만 기기의 뷰포트(viewport) 내에서 노드의 정확한 위치와 크기를 계산하지는 않았다.
뷰포트(Viewport)란 그래픽이 표시되는 브라우저의 영역, 크기를 말합니다. 뷰포트는 모바일의 경우 디스플레이의 크기, PC의 경우 브라우저 창의 크기에 따라 달라집니다.
이렇게 뷰포트 내에서 위치와 크기를 계산하는 것을 layout 단계에서 한다. 대표적으로 width: 50%
, left: 20%
, height: 100vh
이런 속성들을 계산해서 px단위로 변환한다.
layout 단계가 끝나면 실제로 화면을 그리게 되고, 최초 렌더링은 끝난다.
앞에서 봤던 사진처럼 각 단계를 거쳐서 브라우저에 화면을 그리게 되는데,
DOM을 조작하게 될 경우 Reflow나 Repaint 과정이 다시 일어난다.
Reflow가 일어난다
는 말은 레이아웃 계산과 페인팅을 다시 한다는 의미다.
Repaint가 일어난다
는 말은 페인팅만 다시 한다는 의미다.
위에서 살펴본 바와 같이, Reflow가 일어난다
면 브라우저의 성능에 좋지 않다. 성능을 위해서 되도록이면 Reflow가 일어나게 DOM조작을 하지 않아야한다. Reflow가 일어나는 경우는 대표적으로 다음과 같다.
3번의 속성 부분은 종종 javascript로 DOM을 조작할때 아래처럼 사용한다.
건드린 속성 | 사용 예시 | 대안 |
---|---|---|
top | elem.style.top = '20%' | transform: translateY(20px) 사용 |
right | elem.style.height = '100vh' | 처음 작업시부터 100vh |
width | elem.style.width = '80%' | transform: scale(0.8), transform-origin: center 사용 |
position | elem.style.position = 'absolute' | 처음 작업시부터 absolute |
display | elem.style.display = 'none' | opacity: 0 사용 |
Refolow가 되는 작업은 되도록 줄이고, Repaint가 되는 작업으로 대체하도록 하자.
Reflow와 Repaint의 구분은 아래 사이트에서 참고할 수 있다.
https://csstriggers.com/ 👈
직접 DOM을 조작해야 하는 전통적인 웹 개발 방식은 많은 리렌더링을 초래한다.
SPA는 Single Page Application의 약자로, 데이터가 변경된 부분만 업데이트 되는 어플리케이션을 말한다.
SPA는 가상 DOM(virtual DOM
)을 이용해서 렌더링 횟수
를 줄인다. 실제 DOM이 조작되기 전에 virtual DOM에서 비교를 통해 바뀐 부분만 업데이트 한다.
결국 React
를 사용한다면, DOM을 직접 조작하는 방식은 하지 않아야한다.
DOM조작을 위해 ref
를 이용할 수 있지만, 그냥 javascript 하듯이 직접 style을 수정하면 안된다는 말이다. React가 알아서 virtual DOM을 이용해 비교한뒤 렌더링해주기 때문이다.
네이버D2, "브라우저는 어떻게 동작하는가?", https://d2.naver.com/helloworld/59361
구글, "렌더링 트리 생성과 레이아웃 및 페인트", https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=ko
boxfoxs, "브라우저의 렌더링 과정", https://boxfoxs.tistory.com/408
이응모, [Javascript Deep Dive], 브라우저 렌더링 과정, 660p
velopert, "virtual DOM", https://velopert.com/3236
sbinha, "virtual DOM", https://velog.io/@sbinha/React%EC%97%90%EC%84%9C-Virtual-DOM#how-does-virtual-dom-work