😸브라우저란 무엇인가?
웹 개발을 처음 시작할때 (특히 프론트엔드), 이런 말을 많이 들어봤을 것이다.
HTML, CSS, JavaScript 먼저 공부해보세요~
이 세가지 언어는 우리의 웹앱이 동작하게될 장소, 웹 브라우저가 사용하는 언어이기 때문이다. 리액트에서는 JSX 라는 자바스크립트 확장 문법으로 HTML 과 JavaSCript가 합쳐진 코드를 작성하게 되는데, 실제로 웹브라우저에서 동작을 하기 위해서는 바벨 Babel 이라는 변환기로 브라우저가 알아먹을 수 있는 자바스크립트 코드로 번역된다.
우리는 위의 세 가지 브라우저가 이해하는 언어를 가지고 개발을 한다. 작성한 코드들은 최종적으로 브라우저라는 프로그램을 통해서 동작하게 된다. 실제로 코드가 동작하는 장소인 브라우저에 대해서 제대로 알고 있는것이 중요하다.
✅TL;DR
▪️ 웹 페이지가 동작하는 장소
▪️ 웹 서버와 통신을 통해 데이터를 받아오는 역할
▪️ 받아온 데이터를 파싱해 화면에 그려주는 역할
인터넷이라는 거대한 컴퓨터 네트워크 상에서 데이터를 주고받을 수 있는 웹이라는 큰 공간이 있다면, 그 안에서 개별 데이터들을 확인하고 활용할 수 있는 작은 방이 웹페이지라고 할 수 있다.
브라우저는 이런 웹페이지를 보여주고 또 웹 상의 데이터를 실제로 활용할 수 있도록 인터페이스를 제공하는 역할을 한다. 즉 웹 개발자가 작성한 코드가 실제로 동작하는 장소라고 볼 수 있다.
사용자가 요청한 데이터는 브라우저를 통해 서버로 전달되고, 서버에서는 이 요청에 해당하는 데이터를 응답하여 다시 브라우저로 보내준다. 그렇게 되면 사용자는 최종적으로 브라우저 화면상에 예쁘게 표현된 웹페이지를 보고 활용할 수 있다.
서버와 클라이언트가 소통하기 위해서는 HTTP 프로토콜과 TCP/IP 프로토콜같은 여러 절차를 거치게 되는데, 브라우저는 사용자가 google.com 이라는 주소를 입력하면, 이 도메인 이름에 해당하는 IP 주소를 찾아 요청을 하고 응답을 받아서 화면에 띄워주는 모든 역할을 담당한다. 서버 클라이언트 구조에서 클라이언트는 브라우저가 되는 것이다!
아무튼 서버에서 브라우저에 띄워줄 html, css, JavaScript 리소스를 받아오게되면, 이 녀석들을 파싱해서 우리의 의도대로 출력해주는 역할까지 브라우저가 담당하고 있다.
😸브라우저의 구성요소 알아보기
✅TL;DR
▪️ 사용자가 조작하는 인터페이스 부분(뒤로가기, 새로고침 등..)
▪️ 화면에 리소스를 파싱하여 출력해주는 브라우저 엔진 & 렌더링 엔진
▪️ 자바스크립트 소스를 파싱하는 자바스크립트 해석기(자바스크립트 엔진)
▪️ 통신 영역과 UI 백엔드 그리고 브라우저에 데이터를 저장할 수 있는 자료 저장소(웹스토리지)
▪️ 각 파트가 긴밀하게 협업해서 리소스를 화면에 렌더링한다.
그렇다면 도대체 브라우저가 무엇으로 이루어졌길래?! 이런 모든 역할을 담당할 수 있는것인지 같이 알아보자!
브라우저가 하는 일들을 각 부서로 나누어(?) 도식화하면 위 그림과 같다. 사용자가 조작할 수 있는 인터페이스 파트와 리소스를 파싱하고 렌더링하는 엔진부분, 서버와의 통신 레이어와 자바스크립트만을 위한 별도의 해석기가 있다. UI 백엔드란 OS 에 따라서 가지고 있는 기본적인 인터페이스 디자인이 있을텐데, 이런 부분을 그려주는 역할을 담당하고 있다. 자료저장소란 서버에 전송되지 않는 자료를 저장하는 부분, 로컬스토리지와 웹스토리지가 포함된다.
사용자 인터페이스
화면을 제외한 브라우저의 UI를 의미한다. 새로고침, 뒤로가기버튼 등 웹페이지와 별개로 사용자가 조작할 수 있는 인터페이스 부분을 지칭함!
브라우저 엔진 & 렌더링 엔진
보통 브라우저 엔진이라고 함은 리소스를 파싱해서 화면에 출력하는 렌더링 엔진을 포함한 개념이지만, 사용자 인터페이스와 렌더링 엔진 사이에서 동작을 조절하는 부분과, 리소스(HTML, CSS) 코드를 바탕으로 렌더링 트리를 만들어서 화면에 출력하는 렌더링 엔진으로 구분할 수 있다.
브라우저 엔진은 브라우저의 종류만큼이나 다양하고, 각 브라우저별로 내부 동작의 차이는 조금씩 있을 수는 있다.
자바스크립트 해석기
웹페이지에서 인터랙티브를 담당하는 자바스크립트 코드는 별도의 자바스크립트 엔진(해석기, 인터프리터 등으로 부르기도 한다) 에서 처리한다. 이 또한 브라우저 엔진과 마찬가지로 각 브라우저별로 고유의 엔진이 있다! 우리가 많이 사용하는 구글 크롬의 자바스크립트 엔진은 그 유명한 V8 엔진이다.
자바스크립트 엔진에 대한 추가적인 설명은 아래 글로 정리해두었다.
통신 Networking
브라우저와 서버간의 통신을 담당하는 영역이다. 즉 리소스 요청을 위해 HTTP 요청을 보내는 역할을 한다.
UI 백엔드
Select, Input 같은 기본적인 요소를 그려주는데 사용된다. 이 부분은 특별히 스타일링이 되지 않은 경우 OS의 기본 인터페이스 구성을 따라간다.
자료저장소 : 웹 스토리지
브라우저에 데이터를 저장한다?! 라면 쿠키를 떠올릴 수도 있겠지만, 쿠키는 가지고 있으면 http 요청과 함께 서버로 전달되는 데이터를 의미한ㄷ. 보안도 취약하고 용량도 적기 때문에 HTML5 부터는 웹스토리지라는 것을 지원하고 있다.
웹 스토리지에는 로컬 스토리지와 세션 스토리지가 존재하는데, 로컬 스토리지는 브라우저가 종료되어도 데이터가 남아있는 ~ 만료 기간이 없는 저장공간이다.
세션 스토리지는 그와 반대로 한 세션만을 위해 데이터를 저장하게 되는데, 브라우징 되고 있는 컨텍스트 안에서만 데이터가 유지되기 때문에 창이나 탭을 닫으면 정보도 같이 사라진다.
😸브라우저의 렌더링 과정
✅TL;DR
▪️ HTML, CSS 를 파싱해 DOM 과 CSSOM 트리를 만든다.
▪️ DOM + CSSOM 으로 Render Tree를 만든다.
▪️ 레이아웃 과정에서 요소가 화면의 어디에 위치할지 결정한다.
▪️ 페인트 과정에서 렌더 트리를 화면에 실제로 그린다.
렌더링이란 리소스가 구체적으로 화면에 표시가 되는 과정을 의미한다. 브라우저 엔진과 렌더링 엔진이 담당하는 이 과정은 아래의 몇 가지 세부적인 단계로 나뉘게된다.
DOM
DOM 은 HTML 문서의 태그를 하나의 노드로 한 트리 구조의 데이터이다. 서버에서 넘어오는 HTML 데이터가 'utf-8'과 같은 인코딩 형식에 따라 문자열로 변환된다. 그 뒤 토큰이라는 문법적인 의미를 갖는 최소 단위로 변환이 되고, 이 토큰을 기반으로 객체화 된 것이 DOM의 노드이다. 각 HTML 요소의 부모 자식 관계를 반영해 트리가 생성된다.
이런 과정을 거쳐 서버에서 넘어온 바이트코드의 데이터가 실제 활용할 수 있는 데이터로 파싱된다.
CSSOM
CSS 문서도 html과 비슷한 과정을 거쳐 파싱된다. HTML 문서가 한줄 씩 파싱을 하다가 link 태그를 만나면 CSS 파일을 요청하여 파싱을 시작한다. CSSOM 은 CSS 스타일 규칙 정보를 가지고 있고, CSS에서는 하향식 규칙 및 상위에 적용되는 스타일이 하위에 상속이 되는데 이 형태를 트리 구조로 옮기면 아래와 같이 CSSOM이 된다.
AST
HTML 과 CSS가 각각 DOM과 CSSOM으로 파싱이 되듯, 자바스크립트 코드도 별도의 파싱 과정을 거쳐야 활용할 수 있는 데이터가 된다. HTML 파싱 과정에서 scripts 태그를 만나게 되면, 제어권이 렌더링 엔진에서 자바스크립트 엔진으로 넘어가면서 자바스크립트 파싱이 시작된다. 이 때 자바스크립트 엔진은 AST(Abstract Syntax Tree) - 추상 구문 트리라는 자료구조로 소스코드를 파싱하고 실제로 실행될 수 있는 머신코드로 변환되는 과정을 거친다.
자바스크립트가 파싱이 되는 동안 html 은 의미없는(?) 기다림을 계속해야 하기 때문에, scripts 태그를 body의 최하단에 두거나 async, defer 같은 속성을 추가하여 병렬적으로 처리하는 것이다.
DOM + CSSOM = Render Tree
화면에 보여질 부분에 대해서만 렌더링 트리를 생성한다. 렌더링 트리는 DOM 요소와 CSSOM이 합쳐진 데이터로, 이 과정에서 head 처럼 화면에 보여지지 않는 노드는 렌더 트리에 추가되지 않는다. 화면에 렌더링 될 정보들을 담고있는 최종적인 데이터라고 생각하면 된다.
Layout
렌더 트리의 요소들을 가지고, 실제로 화면의 어디에 위치시킬 것인지 계산되는 과정이다. css 에서 사용했던 rem, %, vh, vw 같은 상대 단위들이 이 과정에서 실제 px 로 변환이 된다.
따라서 뷰포트 크기가 달라질때마다 크기가 변하는 상대적인 요소들의 경우에는 크기가 변하는 이벤트가 발생할 때마다 매번 계산을 다시 해야한다.
이렇게 위치에 대한 변화가 생길 때 레이아웃 과정을 다시 수행하는 것을 '리플로우 Reflow' 라고 한다. 리플로우가 너무 빈번하게 발생하면 당연하게도 성능에 좋지 않다.
Paint
화면에 실제로 그려지는 단계이다. 계산이 완료된 위치와 크기에 대해서 픽셀 값을 채워 화면에 표시하는 단계로, 색상이나 그라데이션 그림자 텍스트 컬러 등등 우리가 css 로 구현한 모든 내용이 이 단계를 거쳐서 화면에 그려진다.
화면에 위치 계산이 다시 필요한 경우 발생하는 리플로우처럼, 새로운 위치에 화면을 그려주기 위해서 일어나는 페인트 과정을 리페인트라고 한다.
✔️Summary : 프론트 엔드에서의 성능 최적화?
지금까지 우리의 코드가 동작하는 브라우저가 무엇인지 그리고 브라우저가 화면에 코드를 그려주는 렌더링 과정을 알아보았다. 브라우저의 렌더링 과정에 대한 이해가 있다면 성능 최적화에 도움이 된다. 리플로우와 리페인트가 빈번하게 발생하는 코드가 성능에 좋은 영향을 줄 리가 없다. 따라서 DOM/CSSOM 의 파싱 과정부터 렌더링 트리의 생성, 레이아웃, 페인트와 같은 크리티컬 렌더링 패스를 최적화해서 빈번한 변경이 발생하지 않도록 하고, 되도록 잦은 리플로우 + 리페인트 보다는 리페인트만 발생하도록 하는 것이 좋다.
추가로 리액트의 가상 돔은 사용자와의 상호작용이 많은 SPA (싱글페이지 애플리케이션) 에서 렌더링에 필요한 연산 횟수를 줄여 성능에 도움이 될 수 있도록 하기 위해 사용된다. DOM 자체가 느린 것은 아니지만 하나의 변경사항에 대해서 일일이 실제 DOM에 반복해서 렌더링 과정을 적용시킨다면 성능이 저하될 것이다. 리액트에서는 여러 변경 사항을 가상 돔에 적용시킨 뒤 실제 DOM 의 변경은 한 번만 이루어지도록 함으로써 좀 더 쾌적한 SPA 를 만들 수 있도록 도움을 주고 있다.
👀참고자료
https://www.geekboots.com/story/what-is-browser-engine-and-how-does-it-work
https://medium.com/@monica1109/how-does-web-browsers-work-c95ad628a509
https://web.dev/howbrowserswork/
'WEB' 카테고리의 다른 글
CSR 과 SSR 알아보기! 부제 : 브라우저 렌더링은 서로 다르게 일어나는가? (1) | 2022.10.04 |
---|---|
Webpack 으로 번들링을 해보자! (0) | 2022.09.26 |
[UI/ UX] 사용자 인터페이스(UI) , 사용자 경험(UX) 를 이해해보자 (0) | 2022.08.23 |
[WEB] Postman - Weather API 사용해보기 (0) | 2022.08.08 |
[WEB] REST API를 알아보자! (0) | 2022.08.05 |