브라우저의 동작 과정과 기능들
제목 : 브라우저의 동작 과정과 기능들
이 주제로 포스팅, 및 공부를 하는 이유
웹 사이트를 제작한다는 의미는, 현재 그 의미가 많이 다르다고 생각한다.
정적인 HTML 만을 보여주던 웹 사이트 라는 의미가 무색하게,
현재는 애니메이션 CSS, 웹 3D 렌더링, 웹 사이트 Code Editor, 실시간 채팅 및 그래프 표시 등등,
웹의 다양성은 상상을 초월한다.
단순히 웹 사이트를 개발한다는 것은, HTML 파일과 CSS 스타일링, 반응형 JS 를 제작한다는 것 뿐 만이 아니라,
위의 파일들을 이용하여 클라이언트에게 화면을 보여주는 브라우저의 역할 또한 알아야 한다는 의미이다.
나는 이전에 React 를 공부 할 때, 전역 변수 지정과 로컬, 세션 Storage 및 Cookie 를 공부 할 때
매우 난감했다. 이러한 정보를 사용하여 클라이언트와 개발자에게 편의성을 제공해 준다는 것은 알겠다.
하지만, 이러한 정보는 어디에 저장되는가? 에 대한 의문이 해소되지는 않았다.
그 때 당시는 JS 에 대한 이해가 부족 할 뿐더러, 브라우저의 기능이라는 것을 이해하지도 못했으니,
결국 의미없는 코드를 작성하고 실행 해 볼 뿐이었다.
나는 다시 React 를 활용하여 웹을 개발하는 과정에서 이해 없이 개발하지 않기로 결심했다.
React 는 너무 훌륭한 라이브러리이며 다른 다양한 JS 모듈과 결합 할 수 있지만,
다른 방법론들을 웹 개발이라고 단순히 치부하고 싶지는 않았다.
브라우저에서는 클라이언트를 위한 보안, 웹 렌더링 및 서버 커넥션, 개발자를 위한 편의성 등등
나열하지 않은 수 많은 기능들을 가지고 있다.
우리가 작성한 웹 페이지는 결국 Node.js 환경이 아닌, 클라이언트의 브라우저 환경에서 구동되므로
Node.js 를 공부하듯, 브라우저를 다가가 보기로 했다.
웹 브라우저란?
먼저, 위키피디아의 웹 브라우저에 대한 정의를 훑고 지나가보자.
브라우저란, 웹 사이트에 접근하기 위한 "어플리케이션" 이다.
유저가 특정 웹사이트로부터 웹 페이지를 요청할 때,
브라우저는 웹 서버로부터 이에 대한 파일을 탐색하고, 유저의 화면에 페이지를 표시한다.
또한, 브라우저는 유저의 기기에 저장되어 있는 컨텐츠를 표시 할 수도 있다.
브라우저는 데스크탑, 랩탑, 태블릿, 스마트폰, 스마트워치를 포함하는 다양한 기기에서 사용된다.
웹 브라우저는 어떻게 동작할까?
웹 브라우저를 킨 뒤, 유저가 하는 1 번째 행위는 바로 "탐색 (Retrieve)" 일 것이다.
웹 페이지를 가져오기 위해서는, 검색(탐색) 해야 하기 때문이다.
그런데, 이 탐색 과정에서 배울 것이 많다.
1. 우리는 검색 할 때 URL 을 사용한다.
우리가 웹 사이트의 주소, 예로 들면 https://naver.com
을 검색한다면,
naver.com
를 통해 곧장 웹 페이지를 가져오지 않는다.
모든 서버는 고유의 IP 주소를 가지고 있다. (xxx.xxx.xxx.xxx
) 와 같이 가지고 있다.
브라우저는 먼저, 유저의 기기에 naver.com
이라는 도메인 정보, IP 를 가지고 있는지 확인한다.
만약에 기기에 naver.com
이라는 IP 정보가 없다면, 도메인 정보를 관리하는 서버에 이를 전달한다.
(도메인 관리 서버 == DNS - (Domain Namespace Server)
)
먼저, .com
에 해당하는 com
도메인 이름을 관리하는 서버에 요청을 날리고,
com
을 관리하는 서버는 naver
에 대한 정보를 가지고 있는 서버에 요청을 날린다.
최종적으로 naver.com
이라는 IP 주소 xxx.xxx.xxx.xxx
정보를 Resolve 하게 되면,
네임스페이스 서버(도메인 정보 관리하는 서버들 - 전세계) 는 이를 다시 유저 기기에 전달 해 주게 된다.
받게 된 xxx.xxx.xxx.xxx
IP 주소를 검색하고, 그 결과 https://naver.com
의 웹 사이트를 보게 된다.
위와 같은 과정을 DNS Loopkup (DNS 조회)
라고 부른다.
이를 통해 우리는 드디어 웹 페이지와 정적 리소스를 제공하는 웹 서버의 진짜 주소를 얻게 되는 것이다.
만약에 우리가 입력한 Full URL 이 https://naver.com/api/v1/login
이었다면,
우리가 얻은 IP 주소의 웹 서버에서 api/v1/login
에 해당하는 리소스를 전달 해 주게 된다.
2. 브라우저는 보안된 환경을 제공해 준다.
먼저, 1 번 URL 예시에 빠진 것이 있는데, 바로 보안 환경 구축 과정이다.
대부분의 현대적인 사이트에서는 http
를 사용하지 않는다.
클라이언트와 웹 서버 사이에서 오가는 정보가 Plain Text (일반 텍스트) 로 전달된다고 가정해 보자 - http
로그인 과정만 생각 해 보더라도, 비밀번호가 노출되는 상황이 벌어진다.
이러한 대참사를 막기 위해 2 가지 행동을 수행한다.
첫 번째는 TCP Handshake 이고, 두 번째는 TLS Negotiation 이다.
TCP Handshake 를 통해 서로의 통신 연결 상태를 확인하고, "연결" 을 수립한다.
sequenceDiagram
Client ->> Server: SYN 패킷
Server ->> Client: SYN + ACK 패킷
Client ->> Server: ACK 패킷
이는 두 컴퓨터 간의 TCP 세션을 시작하기 위해 3 개의 메세지를 전달하는 과정이다.
TLS Negotiation
TCP 핸드셰이크 이후, 우리는 각 서버의 연결 상태를 수립했다.
이후, 우리는 웹 서버에 요청 및 응답을 수행하기 위해 "암호화" 를 해야 한다.
암호화 단계가 바로 TLS Negotiation (TLS 협상) 이다.
먼저 과정을 보자 :
sequenceDiagram
Client ->> Server: ClientHello
Server ->> Client: ServerHello & Certificate(인증서)
Client ->> Server: ClientKey
Server ->> Client: Finished
Client ->> Server: Finished
Cloudflare 에서 TLS 핸드셰이크에 대한 정확한 설명을 가지고 있다.
TLS 핸드셰이크(협상) 을 통해, 양 측은 암호화 된 정보를 주고 받을 수 있게 되었다.
이 과정 이후 감청자는 메세지를 변환할 수 없으며, 해독 할 수 없다.
그리고 마침내, HTML 페이지를 가져온다.
3. 브라우저는 구문 분석(Parsing) 을 통해 페이지를 렌더링한다.
HTML 은 마치 이미 기계어처럼 바로 실행하거나, 곧바로 렌더링 할 수 있는 구문이 아니다.
HTML 은 브라우저가 분석하여
DOM
(Document Object Model), CSSOM
(Cascade Style Sheet Object Model) 로 바꾼다.
웹 사이트는 컴포넌트 렌더링을 통해 화면을 송출한다.
그러나, 렌더링이라는 것이 이미지처럼 렌더링 된다는 의미가 아니고,
먼저 컴포넌트의 연결과 부모 자식 관계를 형성하고, 이를 통해 컴포넌트를 화면에 붙이는 것이다.
그리고, 컴포넌트의 특성과 해당 컴포넌트에 정의된 css 특성을 통해 스타일링 된다.
DOM 은 Tree 의 형태를 가지고 있으며, CSSOM 도 마찬가지로 Tree 의 형태를 가진다.
실제로, 우리는 HTML 에 들어가는 JavaScript 에서 document
객체를 사용 할 수 있다.
Node.js 는 어플리케이션을 전제로 만들어진 엔진이라서 document
선언 시 오류가 나지만,
기본적으로 브라우저 환경의 JavaScript 에서는 window
, document
, ... 등등이 전역 객체로 선언된다.
이 때, 우리는 document
객체에서 제공하는 수 많은 메서드로 DOM 의 특정 컴포넌트를 추출하고,
이를 다룰 수 있다.
브라우저에서 DOM 을 변화하는 순간, 브라우저도 이에 맞춰 동적으로 렌더링된다.
DOM 예시
flowchart TB
html
head
body
html --> head & body
subgraph InnerHead ["InnerHead"]
meta
title
link
script1
end
head --> InnerHead
subgraph InnerBody ["InnerBody"]
direction LR
h1
p --> a
div
div --> img
script2
end
body --> InnerBody
그렇다면, CSSOM 은 무엇인가?
CSSOM 은 문서의 스타일 관련 (CSS) 정보를 읽고, 이를 수정하기 위한 API 세트이다.
위에서 JS + DOM 으로 문서 구조와 내용을 읽고 수정하는 것 처럼,
CSSOM 을 이용하여 JS 에서 문서의 스타일을 읽고 수정 할 수 있다.
CSS 를 수정하는 방법은 다양한데,
- CSSOM 배열 혹은 객체를 변경하는 방법
- DOM 내의
.style.background
을 이용하여 색상을 바꾸는 방법 (인라인 스타일 변경 ) - ... 이 있다.
CSSOM 자체가 DOM 과 비슷하게 동작하지만, 따로 Rule 이 존재한다.
CSSOM 을 깊이 이해하고 싶다면, 아래의 링크를 보길 바란다
CSSOM 은 style sheet 를 따라 구성하는데,
이는 태그, 클래스, id 등등에 따라 매칭되는 DOM 을 스타일링한다.
4. (Preload Scanner) : 브라우저는 DOM 을 파싱하며, 필요한 리소스들을 동시에 요청한다.
브라우저는 html 파일을 DOM 으로 파싱하는 와중에, 필요한 리소스들을 동시에 요청한다.
브라우저의 메인 스레드는 DOM 트리를 구성하는 데 집중한다.
그 와중에 프리로드 스캐너는 DOM 을 스타일링 하는 데 필요한 css 파일이나,
이미지 구성을 위한 파일이나, JavaScript 파일을 요청한다.
이미지나 css 파일은 DOM 을 구성하는 데 있어 영향을 미치지는 않는다.
하지만, JavaScript 는 종종 DOM 을 실제로 건드리는 경향이 있어 동기적으로 가져온다.
따라서, DOM 에 영향을 미치지 않는 JavaScript 파일의 경우 async
나 defer
키워드로 가져와야 한다.
웹 브라우저의 저장소 각종 Storage 들
웹 브라우저에는 크게 알려진 저장소가 있다.
- 로컬저장소
- 세션저장소
- 쿠키
- IndexedDB - 새로 배움
- Web Storage - 새로 배움
각각의 사용법을 완벽히 알지도 못하고, 내가 알지 못하는 저장소 또한 존재한다고 판별하여 이를 조사한다.
위와 같은 저장소는 JavaScript API 로 접근이 가능하다. (쿠키는 서버 측에서 httpOnly
가 아닐 때에만 가능하지 않을까?)
유저의 브라우저 기기에 저장되는 저장소들은, 서버가 판단하여 각종 목적으로 사용 할 수 있다.
- 유저가 어떤 형태로 로그인 했었는지
- 유저가 아직 로그인 세션을 잃지 않았는지
- 커머스 사이트의 장바구니
- 유저의 사이트 설정 기억하기 (Ex - 다크모드, 라이트모드 등)
- 사이트 내에서의 활동 기록
Cookies
MDN 피셜 Old School 이라고 한다. 그 만큼 오래된 역사를 지닌 저장소라는 것이다.
바로 밑에 Web Storage, IndexedDB 를 말하는 것을 보면, 두 기능을 잘 보여주기 위해 올드스쿨이라고 한 것 같다.
로컬과 세션과 달리, 쿠키 정보는 요청 시 항상 같이 전달된다.
웹 서버를 개발할 때 요청 Agent 개발 시, 쿠키의 값을 추출하여 전달 할 필요 없이,
그냥 요청만 해도 서버에서는 쿠키 정보를 전달받는다.
현재 웹사이트에서는 세션 ID, 액세스 토큰 및 리프레쉬 토큰에 자주 사용된다.
쿠키는 도메인을 중심으로 저장하고, EX - naver.com
해당 도메인에 요청을 보낼 때 마다 쿠키 정보를 자동으로 보내준다.
서버는 내 도메인에 할당된 쿠키 정보를 수정, 혹은 추가하거나, 삭제하기 위해 이러한 헤더를 설정한다.
Set-Cookie: <쿠키-key>=<쿠키-value>
이러한 헤더는 서버 측에서 1 번이 아니라, 여러번 선언하여 설정 할 수도 있다.
Web Storage
MDN 에서 새로운 기능으로서 말하는 기능이다.
Web Storage 라는 새로운 기능이 생겼나? 했는데,
localStorage
, sessionStorage
라고 한다. (위에서 말한 저장소)
localStorage, sessionStorage
로컬과 세션의 차이는 "브라우저, 탭이 닫혔을 때, 정보를 저장하는가?" 이다.
그리로 쿠키와 차이가 있다면, 저장 공간이 쿠키보다는 크며,
쿠키처럼 자동으로 요청에 첨가하지 않고 선택적으로 첨가 할 수 있다.
웹 개발 시,
Window.sessionStorage
혹은 Window.localStorage
로 접근 할 수 있다.
한번, localStorage
로 예시를 들어 보자 :
// Web Storage 의 local 에
// Key 는 "myname", Value 는 "공담형" 이 설정된다.
localStorage.setItem("myname", "공담형");
// local 저장소에서 Key 인 "myname" 인 Value 를 가져온다.
console.log(localStorage.getItem("myname"));
// 공담형
// local 저장소에서 Key "myname" 을 삭제한다.
localStorage.removeItem("myname")
IndexedDB (색인 DB)
IndexedDB 는 복잡한 데이터(큰 데이터) 를 브라우저에 영구적으로 저장 할 수 있는 방법 중 하나라고 한다.
공식문서를 보니까, 정말 파일 시스템 DB 를 JavaScript 로 접근 할 수 있는 API 를 제공하고 있다.
이러한 특성 덕분에, 온라인과 오프라인 환경에서 모두 동작 가능한 웹 어플리케이션을 제작 할 수 있다고 한다.
IndexedDB 는 브라우저 기기의 데이터베이스에 접근하기 위한 API 를 제공한다.
실제 트랜잭션을 생성하고, 쿼리를 통해 데이터를 가져올 수 있는 예제가 존재한다.
이 글을 작성하며 배운 것.
웹 사이트를 개발하기 위해서 필연적으로 배워야 하는 것은 웹 사이트가 가진 고유의 기능이다.
최근 개발 환경의 편의성이 많이 올라가고, 반응형 웹 사이트라는 제목에 많이 이끌렸지만,
결국 웹 사이트는 단순히 JavaScript 파일에 의해 동작하는 것이 아니라,
브라우저가 제공하는 API 와 JavaScript 파일과 융합하여 동작하기 때문이다.
나는 브라우저의 기능과 JavaScript 의 본래 모습 (EX- es5 버전) 을 보기 전에,
먼저 최신 JS 버전의 React 를 공부했었다.
하지만, 후반에 가서야 특정 API 들을 "왜" 사용하는지 전혀 알 수 없었다.
왜 WAS 와 상호작용 하기 위해 특정 설정을 해야 하는지, CORS 에러가 무엇인지,
웹 페이지에 진입 시 어디서 사용자의 정보를 가져오는 건지,
모르는 것이 정말 많았지만, 코드를 따라 치기만 할 뿐이었다.
하지만 나는 이러한 배움의 실수를 다시 하고 싶지 않다.
다시 기초로 내려 온 것도 3번째 인 것 같다.
3 번 같은 이유로 실수했다면, 그것은 실수가 아니고 실력이라고 생각하기 때문이다.
브라우저는 HTML, CSS, JS 를 인식한다.
우리가 React 를 배울 때 사용하는 TypeScript, JSX, TSX 와 같은 형식은 사용되지 않는다.
브라우저의 실행 환경을 고려하여 Webpack 을 사용하여 번들링(Bundlering) 하게 되는데,
이 다음 주제로 번들링을 공부하기로 결정했다.
참고 사이트
MDN (브라우저는 어떻게 동작하는가)
https://developer.mozilla.org/ko/docs/Web/Performance/Guides/How_browsers_work
MDN (DOM 소개)
https://developer.mozilla.org/ko/docs/Web/API/Document_Object_Model/Introduction
MDN (CSS 객체 모델 - CSSOM)
https://developer.mozilla.org/ko/docs/Web/API/CSS_Object_Model
위키피디아 (Web Browser)
https://en.wikipedia.org/wiki/Web_browser
MDN (TCP 핸드셰이크)
https://developer.mozilla.org/ko/docs/Glossary/TCP_handshake
Cloudflare 문서 (TLS 핸드셰이크란 무엇일까요?)
https://www.cloudflare.com/ko-kr/learning/ssl/what-happens-in-a-tls-handshake/
MDN (Client-side Storage)
MDN (HTTP 쿠키)
https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/Cookies