개발자가 내팔자

브라우저 동작 원리를 알아보자 본문

WEB

브라우저 동작 원리를 알아보자

야생의 개발자 2022. 8. 2. 04:51

 

( 이 글은 2021년 8월에 올렸던 글입니다.)

 

후후… 프리온보딩 코스에서 두가지 주제로 블로그에 글을 쓰라는 과제를 받았는데 마침 둘 다 내가 바닐라JS 스터디에서 발표했던 주제라 굉장히 반갑다! 그 당시에 내가 발표했던 것과 비슷한 흐름으로 전개해보겠다. 프로그래밍은 추상화가 잘 되어있어서, 글로만 설명하는 것보다 그림과 말로 설명하는 것이 좀 더 편하게 느껴질 때가 많다. 사실은 영상으로 올리고 싶은데, 자막을 추가하는 작업이 따로 필요해서 그건 추후에 올리도록 하겠다. 아쉽지만 이 곳에서도 최선을 다해 재미있고 쉽게 이해할 수 있도록 적어보겠다.



저번 포스팅에서도 말했듯이, 프로그래밍 세계는 새로운 지식을 이해하고자 할 때, 그것과 고구마줄기처럼 엮여있는 기반 지식을 알고 나면 조금 더 수월해진다. 이번 주제도 마찬가지다. 브라우저 작동 원리를 이해하기 위해서는 몇가지 기반 지식들이 필요하다.



1. 자료구조 Tree
2. HTML, CSS

3. 컴파일러와 인터프리터
4. DOM, CSSOM
5. HTTP와 RESTful API
6. SSR CSR

아니 세상에 브라우저 동작 원리 하나를 이해하려면 이걸 다 알아야 한다고?

Don't Panic ! 걱정은 잠시 내려놓자. 생각보다 별 거 아니다.

"빨리 가는 유일한 방법은 제대로 가는 것이다." 라는 말이 있다.

쉽게 얻어진 지식보다 겹겹이 쌓아올린 탑이 더욱 견고하다.

이미 다 알고 있는 내용이라면 가벼운 마음으로 읽으면 되겠다.

자, 그럼 브라우저의 동작 원리를 이해하기 위한 여정을 함께 떠나보도록 하자!

 

 

1. Data Structure , List , Tree

이거 말고 Abstract Data Type

42서울에서 라피씬이 끝나갈 무렵, 나는 본과정에 붙을거라 생각하지 않았지만 개발은 계속 하고 싶어 동료에게 물어봤다. 이제부터 무엇을 공부하는 게 좋을까요? 바보같은 질문이지만 동료는 친절하게도 내게 '자료구조'를 공부하라고 일러줬다. Data Structure라는 거창한 이름을 한 책들이 그 당시엔 무시무시해보였지만 공부해보면 늘 느끼는 것처럼 얘 또한 생각보다 별 거 아니다. 스택, 큐, 배열, 리스트... 이런 추상 자료형을 ADT(Abstract Data Type)로 줄여부르고(여담이지만 개발자들은 줄임말을 굉!장!히! 선호하는 것 같다. 별다줄(별걸 다 줄여말한다)) 이를 공부하는 CS과목의 이름이 자료구조다.

 

전에 패스트캠퍼스에서 온라인으로 자료구조 강의를 보는데 강사님이 리스트를 가르치면서 여기서 많이들 탈주한다고, 조금만 더 힘내라며 격려하셨다. 그리고 리스트를 지나 트리를 배우게 되면 이젠 강사님도 어려워서 화가 난다고 한다. 우스갯소리로 하신 말씀이지만 확실히 난이도는 조금씩 올라간다. 그러나 조금이다. 리스트를 이해하고 나면 트리는 좀 더 이해하기 수월해진다. 거기서 한 단계 더 살을 붙인 것일 뿐이니까. 그래서 리스트를 먼저 알아보도록 하자.

 

 

Once upon a time . . .

슬픈 이야기를 들려줄테니 손수건을 준비해두는 것이 좋겠다. 옛날 옛날에, 배열을 쓰며 행복하게 살던 개발자가 있었다. 개발자는 "무조건 많이 만들어주면 되겠지!"하고 int형의 연속된 자료(data) 1만개를 배열로 선언했다. 그런데 막상 개발을 하다보니 5개 정도만 선언해도 됐었다는 것을 깨달았다. 나머지 9995개의 빈 공간이 메모리를 잡아먹으며 개발자를 슬프게 했다. "나는 메모리를 낭비하는 개발자야.. 흑흑" 개발자는 다시 배열을 5개짜리로 수정했다. "휴, 이제 메모리를 알뜰살뜰하게 쓰는 개발자가 될 수 있겠군!" 그런데 아뿔싸, 다시 보니 1만개의 데이터가 필요해졌다. 5개짜리로는 어림도 없었다. 개발자는 데이터가 얼마나 필요할 지 개발을 하는 도중에는 예측하기 힘들었다. 결국 프로그램은 개발자의 멘탈과 함께 터지고 말았다.

 

여기서 포기하면 그저 새드엔딩이 될 뿐, 좋은 개발자가 될 수 없다. 좋은 개발자는 어려움이 닥쳤을 때 문제 해결 능력이 있어야 한다. 이럴 때, 개발자는 어떻게 했을까? 바로, 리스트를 쓰기로 결정한다. 개발자는 프로그램을 되살려 행복해질 수 있었다. 어떻게 리스트가 이런 문제를 해결할 수 있었을까? 리스트란 도대체 무엇일까?

 

What is List ?

언뜻 보면 기차처럼 연결되어있다.

 저렇게 연결된 형태의 추상 자료형을 리스트, Linked list라고 한다. 저 네모 하나 하나를 저거, 네모 등의 이름으로 부르면 멋이 없기 때문에 앞으로는 고상하게 Node(노드)라고 한다. 노드 안에는 데이터를 담는 데이터 공간과 다음 노드를 가리키는 포인터(또는 레퍼런스)를 갖고 있다. 이는 마치 넓은 공간에 일렬로 띄엄띄엄 서있는 학생(노드)들과 같다. 각자가 가져온 자신의 가방(데이터)을 안고 있으면서 뒤에 학생이 누구인지, 존재하는지 여부(next node를 가리키는 포인터)를 알고 있다. 이처럼 한 방향으로만 기억하는 것을 단일 링크드 리스트(Singly linked list), 앞사람까지 기억하는 것을 양방향 링크드 리스트(Doubly linked list)라고 한다. 따라서 양방향 링크드 리스트는 노드에 데이터, next 뿐 아니라 prev(이전 노드를 가리키는 포인터)까지 포함한다.

 

 선생님은 굳이 소리를 지르지 않아도 맨 앞의 학생한테 이야기를 하면 맨 뒤에 학생에게 앞으로 나와보라고 전달할 수 있다. 단점은 선생님이 맨 뒤에 학생에게 뭔가를 전달하기 위해서는 거쳐가야 할 학생들이 많아서 번호를 직접 부르는 것(배열의 인덱스로 접근하는 것)보다 상대적으로 느리다는 것이다. 뒤늦게 들어온 학생들은 앞에 서거나 맨 뒤로 가거나 중간에 들어간다. 맨 앞에 서면 기존의 맨 앞에 있던 학생은 더이상 맨 앞의 학생이 아니게 된다. 맨 뒤에 학생도 마찬가지. 중간에 들어가는 학생은 아래 그림과 같이 원래 기억하고 있던 연결 고리를 끊고, 자연스럽게 새롭게 연결고리를 생성한다. 삭제는 이것을 반대로 해주면 되겠지. 맨 앞이나 맨 뒤는 그냥 연결을 끊고 나가면 되겠지만 중간에 나가는 학생이 나가기 전에는 앞 뒤 학생을 이어줘야 한다. 따라서 링크드 리스트는 삽입/삭제가 보다 자유롭다. 여기서 보다 자유롭다의 비교 대상은 무엇일까? 앞선 새드엔딩 스토리에서 눈치챘을지 모르겠지만 배열이다. 

죄송합니다! 잠시만~ 들어갈게요~

 

What is Array ?

배열은 칸막이가 정해진 촘촘한 의자에 학생들이 성적순으로 한 명씩 일렬로 앉아있는 것을 떠올리면 되겠다. 배열은 삽입 삭제가 상대적으로 번거롭다. 맨 뒤는 비교적 할만하다. 그러나 중간에 삽입/삭제를 하면 어떻게 될까? 운동장에는 1천개의 의자가 있고, 처음부터 998번 째까지 학생들이 번호 순서대로 빼곡히 앉아있다. 2명의 지각생이 있다. 학생 한 명이 499번에 앉으려고 한다. 뒤에 있는 500명 가까이 되는 학생들의 원성이 쏟아진다. 왜? 한 명씩 일어나 한 칸씩 자리를 뒤로 미뤄 앉아야 하기 때문이다. 어휴 귀찮아! 이 한 명 때문에 도대체 몇 명이 불편함을 감수해야 하는가? 지각생은 연신 죄송해하며 자리에 앉는다. 많은 학생들이 자리를 고쳐 앉느라 잠시 웅성거렸다. 그리고 시간이 조금 지나 또 한 명의 지각생이 왔다. 아뿔싸! 이 지각생은 0번 자리에 앉으려고 한다. (프로그래머는 1이 아니라 0부터 센다.) 전교생의 비난이 빗발친다. 고작 한 명 때문에 999명이 또 번거로움을 느껴야 하다니! 학생들은 또 소란스럽게 자리를 옮겨 앉았다. 그런데 이번엔 한 전학생이 들어왔다. 학생들은 긴장한다. 쟤는 어디에 앉을까. 설마 0번은 아니겠지... 이럴수가! 전학생이 오자마자 시험성적이 1등이니 맨 앞에 앉으란다. 1000명의 학생들은 좌절한다. 게다가 의자도 부족하다. 도대체 누가 이런 방식으로 앉아있게 한거야! 화가 나서 학생들은 폭발해버렸고 학교는 망해버렸다. 개발을 하다 보면 이렇게 화가 날 때가 있다. 도대체 왜 이런 방식으로 코드를 짠거야! 그러니 개발을 하다가 화가 나지 않도록 개발자는 자료구조를 열심히 공부하여 그 때 그 때 알맞는, 가장 효율적인 추상 자료형을 쓰는 것이 정신 건강에 좋겠다.

 

이제 여러분은 리스트가 무엇인지, 배열과의 차이점이 무엇인지, 어떤 장단점이 있는지 이해할 수 있을 것이다. 배열과 리스트의 차이점에 대해 나열한 글은 다른 블로그에도 많아서 굳이 따로 정리하지는 않겠다. 재미있는 이야기를 봤다!로 끝내지 않고 자신의 지식으로 만들고 싶다면 오늘 알게 된 것을 스스로 정리해보길 추천한다. 이해가 안된다면 댓글로 알려달라. 조금 더 보충해서 써보겠다. 리스트에 대해 조금 더 공부해보고 싶다면 배열과 리스트를 자신이 선호하는 언어로 직접 구현해보는 것을 추천한다. 이 때 구현 사항은 노드 하나만 달랑 있다고 될 게 아니라 CRUD, 즉 만들고 읽고 업데이트하고 삭제하는 과정까지를 모두 포함해야 한다.

 

What is Tree ?

지금까지 리스트를 설명한 것은 트리를 설명하기 위함이었다. 리스트를 이해했다면 트리는 조금 더 쉽게 이해할 수 있다. 리스트에서는 노드가 하나의 노드, 또는 앞 뒤의 노드만을 가리켜서 일렬로 구성되어 있었다. 마치 열차처럼! 트리에서는 두 개 이상의 노드를 가리킬 수 있다. 일렬이 아니라 마치 이름 그대로 여러 갈래로 가지를 뻗은 나무처럼 생겼다. 가계도를 생각하면 좀 더 이해하기 쉬워지는데, 우선 맨 위에 나와있는 시작 노드를 루트 노드라고 한다. root는 근본, 뿌리를 뜻하는 영단어로, 뜻을 알고 나니 의미가 좀 더 와닿는다. 루트 노드로부터 가지를 뻗어 나온 노드들을 자식 노드라고 한다. 자식 위로 한 단계 올라가서 자식과 연결되어 있는 것을 부모 노드라고 한다. 그렇다. 트리에서는 노드를 주로 부모-자식 관계로 설명한다. 부모-자식은 아니지만 같은 레벨에 있는 노드를 sibling 이라고 한다. 이는 형제 자매를 뜻하는 영단어다. 따라서 트리의 노드는 자신이 가지는 데이터, 자식을 가리키는 포인터를 여러개 가질 수 있다. 

나무를 거꾸로 뒤집은 것처럼 생겼다. 마음의 눈으로 뒤집어 보세요...

트리를 쓰는 이유가 뭘까? 정렬이 되어 있다는 가정 하에 데이터를 빠르게 찾을 수 있고 분류하기에도 편하다.

BST(Binary Search Tree)는 한국어로 이진 탐색 트리다. 부모 노드가 자식 노드를 최대 두 마리까지 소유한다. 부모를 기준으로 더 작으면 왼쪽 자식으로 보내고 크면 오른쪽 자식으로 보내는 식으로 알고리즘을 짜면 보다 쉽게 정렬할 수 있다. 마치 up-down 게임과도 같다. 지금 글쓴이가 생각하고 있는 숫자를 맞춰봐라. 갑자기 글쓴이는 독자에게 독심술을 요구한다. 초능력이 없는 여러분들은 당황하면서 아무 숫자나 부르게 될 것이다. 내가 만약 불리는 숫자들에 대해서 맞다 아니다 라고만 대답한다면 여러분들은 금새 지쳐버릴 것이다. 그러나 내가 여러분이 부른 숫자를 듣고, 내가 생각한 마음 속 숫자를 기준으로 더 크다/더 작다 라고 하면 여러분들은 보다 더 빠르게 맞출 수 있다. 새로운 노드를 삽입하거나 특정 데이터를 찾을 때, 이런 식으로 노드를 탐색해가며 자리를 찾아간다. 

 

AST(Abstract Syntax Tree)는 한국어로 추상 구문 트리다. 컴파일러 과목에서 배우는데 우리가 쓴 소스코드를 컴파일러가 파싱해서 컴퓨터가 이해할 수 있게 트리 형태로 만든 것을 말한다. 이것은 뒤에도 한 번 더 언급되므로 기억해두는 것이 좋다.

 

트리를 좀 더 공부해보고 싶다면 직접 구현해보면서 장단점이 무엇일지 생각해보면 좋을 것이다. 이미 단점을 극복하기 위한 많은 시도들이 있었고 이를 위해 알아두면 좋을 용어들(완전 이진 트리, 포화 이진 트리 등)이 있지만, 이 글에서는 더 설명하지 않겠다. 세상에는 B트리부터 시작해서 B+트리, 힙트리, 레드블랙트리 등 아주 다양한 트리들이 있으니 궁금하다면 한 번 검색해보는 것을 추천한다. 추후에 기회가 된다면 이 블로그에 자세하게 적어보도록 하겠다. 참고로 이 곳에서 자료구조를 좀 더 시각적으로 보며 이해할 수 있다.

 

 

축하한다! 여기까지 우리는 자료구조에서 리스트와 트리에 대해서 간략하게 알게 됐다. 이제 시작이니 스트레칭 한 번 하고 계속 읽어주길 바란다.

 

 

 

2. HTML CSS - Markup Language

친한 개발자에게 저 살인마가 했던 말을 속삭여보자. 재미있는 반응이 돌아온다.

웹개발, 특히 프론트에 관심있는 사람이라면 누구나 한 번쯤은 들어봤을 것이다. 여기서는 굳이 HTML의 역사같은 것까지는 올라가지 않겠다. HTML과 CSS는 정적 웹 문서를 만들 수 있는 Markup Language다. 즉, 프로그래밍 언어가 아니다. 검색해보면 위키에 "마크업 언어는 태그 등을 이용하여 문서나 데이터의 구조를 명기하는 언어의 한 가지이다" 라고 나온다. 프론트 개발을 하기 위해서 사람들은 HTML, CSS, JS부터 배우게 되는데 HTML은 웹페이지의 구조를 담당하고, CSS는 디자인을 담당하고, JS는 그렇게 만든 웹페이지를 동적으로 만들어준다. 예를 들어, 집을 짓는 과정에서 HTML의 요소는 콘크리트와 철근에 해당한다. HTML로만 되어 있어도 뭐 사이트는 얼마든지 돌아갈 수 있지만, 건물이 있다 정도는 알겠는데 너무 못생겨서 별로 살고 싶지 않다. 나같은 사용자도 마찬가지다. 못생긴 사이트는 별로 가고 싶지 않다. 이제 거기에 인테리어를 하는 게 CSS다. 벽지도 예쁘게 바르고 장판도 깔고 나면 사람이 좀 살만해진다. 하지만 인간의 욕심은 끝이 없다. 수도꼭지를 열면 물이 나오고 스위치를 켜면 전등에 불이 들어오면 좋겠다. 이 때 필요한 것이 JS다.

CSS는 어렵지만 예쁜 집에 살고 싶어요

 

What is HTML ?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="foo">
      <div>haha</div>
      <div>Hello</div>
    </div>
    <script>
      console.log(document.getElementById("foo").firstChild);
    </script>
  </body>
</html>

VS Code에서 !(느낌표)를 치고 엔터를 치면 이런 식의 코드가 펼쳐진다. 저렇게 <> 괄호로 둘러쌓인 것을 태그라고 하는데, HTML에서 태그는 일반적으로 Element, 요소라고도 한다. 이런 요소 하나하나가 모여 웹 페이지의 구조를 만드는 것이다. 태그는 보통 몇 가지 예외 케이스를 제외하면 열고 나서 닫아줘야 하는데, 열고 닫기 전까지 그 안에서 새로운 태그를 얼마든지 열고 닫고 만들 수 있다. 태그 안에 태그를 자식 태그라고 한다. 여기서도 부모-자식 개념이 쓰이는 것이다.

 

태그 안에는 아래와 같이 여러가지 요소를 지정할 수 있다. 김춘수의 꽃이라는 시를 아는가? 태그에 클래스나 id를 지정해주기 전까지 그는 하나의 태그에 불과하다. html 태그가 많아질 수록 관리하고 싶어지는 태그들이 계속 생겨날텐데, 수많은 태그들 중에 내가 찾고 싶은 바로 그 태그! 그 태그의 이름을 부르고 싶다면 미리 class나 id로 지정해줘야 한다. class는 그룹으로 묶을 수 있어서 여러 개여도 좋지만 id는 이름대로 오직 하나여야 한다. HTML은 딱히 에러가 났다고 알려주지 않기 때문에 주의해야 한다. 또한 <div> 태그를 떡칠하는 것보다 sementic tag를 신경쓰면서 하는 편이 좋다.

 


                                   김 춘 수

내가 그의 이름을 불러주기 전에는
그는 다만
하나의 몸짓에 지나지 않았다.

내가 그의 이름을 불러주었을 때,
그는 나에게로 와서
꽃이 되었다.

내가 그의 이름을 불러준 것처럼
나의 이 빛깔과 향기에 알맞은
누가 나의 이름을 불러다오.
그에게로 가서 나도
그의 꽃이 되고 싶다.

우리들은 모두
무엇이 되고 싶다.
너는 나에게 나는 너에게
잊혀지지 않는 하나의 눈짓이 되고 싶다.

 

What is CSS ?

CSS는 지정한 스타일이 폭포수처럼 자식에게까지 영향을 미치기 때문인지, Cascading Style Sheets라는 이름을 갖고 있다. 아까 말했던 대로 꾸며주는 역할을 하는데, 이 때 방법이 세 가지가 있다.

하나는 HTML 파일 안에 있는 <style> 태그 내부에서 꾸며주는 것이다.

<style>
body { /* tag로 지정하는 방법 */
	background-color: white
    }

.class { /* class name으로 지정하는 방법 */
	color: red;
    }

#id { /* id로 지정하는 방법 */
	margin-top: 1px;
    }
</style>

두번째는 HTML 파일 내의 태그 각각에 직접 스타일을 부여하는 것이다.

<p style="color: red">haha!</p>

마지막은 가장 보편적으로 쓰이는데, 외부에 CSS 파일을 만들어놓고 HTML 파일에서는 링크를 걸어 불러오는 방법이다.

<link rel="stylesheet" href="css파일이 존재하는 경로" />

css는 flex나 gird, 우선 순위, 가상 선택자 등의 공부할 요소들이 좀 있어서 내 주변의 대부분의 동료들은 귀찮아하는 것 같았다. 나도 마찬가지이지만 프론트엔드 개발자가 되고 싶다면 CSS는 필수적으로 알아야 한다고 생각한다. 따로 공부해보길 추천한다. 개인적으로 이 글이 flex에 대해 쉽고 재미있게 쓰여 있어서 CSS에 대한 거부감을 덜어줘서 좋았다. 참고로 grid에 대한 설명도 있다.

 

지금까지 HTML과 CSS에 대해 아주 간단하게 알아보았다. 이제 한 번 더 스트레칭을 하고 다음 주제로 넘어가보자. 스트레칭은 자주 해주는 게 좋다. 몸을 움직이지 않으면 굳어버려서 정형외과에 가서 비싼 돈을 주고 치료를 받아야 한다. 병원비로 텅장이 되어 눈물이 흐르기 전에 미리 관리해두자.

 

 

 

3. Compiler vs Interpreter

What is Compiler ?

여러분은 C언어를 써 본적이 있는가? 나는 42서울에서 처음으로 코딩을 시작하며 그 곳에서 C언어를 공부했다. C언어는 아주 저수준 언어이고, 정적 타입 언어이고, 절차지향적이며 컴파일 언어이다. 갑자기 어려운 말들이 쏟아져나온다는 생각이 들면 그냥 지나가도 좋다. 하지만 여기서 컴파일 언어가 무엇인지는 알아야 한다. C언어 개발자는 프로그램을 만들 때 다음과 같은 과정을 거친다. 뭔지 모르겠더라도 개발자가 작성한 소스코드가 담긴 helloworld.c라는 파일이 몇가지 단계를 거쳐서 실행파일이 생긴다는 것 정도는 알아챌 수 있을 것이다. 이처럼 인간이 작성한 코드를 기계가 이해할 수 있는 10101010110 따위의 기계어로 바꾸는 것을 컴파일이라고 한다. 컴파일을 거치면 실행 파일이 생성된다. 컴파일 하는 과정은 아래와 같이 복잡하여 느리겠지만, 한 번 실행파일을 만들어두면 기계가 바로 이해하여 실행할 수 있으므로 빠르다.

C언어 컴파일 과정

 

What is Interpreter ?

여러분은 Python을 써 본적이 있는가? 나는 작년에 C언어로 printf를 한 번 만들고 나서 C에 완전히 질려버렸다. 그러다가 파이썬이라는 언어를 접하게 되면서 굉장히 재미를 느꼈는데, C언어와는 정말정말정말정말 다르다! 파이썬은 스크립트 언어다. 인터프리터에 의해 번역/실행 되므로 인터프리터 언어라고도 한다. 파이썬은 실행파일을 따로 만들지 않는다. 그럼 어떻게 실행하나요? 소스코드를 바로 실행하면 인터프리터가 한 줄 한 줄 기계어로 번역하며 실행해준다. 번역과 실행을 동시에 해야하므로 컴퓨터는 굉장히 바빠질 것이다. 그래서 파이썬은 일반적으로 C에 비해 느리다고 하는 것이다.

JS 컴파일 과정

그렇다면 자바스크립트는 어떨까? 이름만 봐서는 스크립트 언어인 것 같다. 실제로도 인터프리터 언어로 분류된다. 그러나 자바스크립트는 약간의 컴파일 과정을 한 번 거치고 나서 인터프리터가 바이트 코드를 한 줄 한 줄 실행하는 형태로 이루어진다. (블로그 쓰다가 알게 된건데 파이썬도 vm에서 돌아가므로 마찬가지인 것 같다. 추후에 더 알아보고 보충하겠음.) 자바스크립트 엔진에서 토크나이저가 어휘 분석을 통해 소스코드를 토큰화하고, 이를 파서가 구문 분석을 통해 파싱하여 AST를 만든다. AST를 바탕으로 ASM(어셈블리어)처럼 생긴 바이트 코드가 만들어지고, 인터프리터가 이를 해석하여 실행하는 것이다. 이 과정에서 자주 사용되는 코드는 컴파일러가 또 최적화를 해준다고 한다.

 

 

 

4. DOM CSSOM

What is DOM?

DOM(Document Object Model)이란 HTML 문서에 접근하기 위한 인터페이스다. 렌더링 엔진이 HTML문서를 파싱하여 트리 구조를 만든다. 이 때 요소들이 노드에 하나씩 배정된다. 이를 DOM tree라고 한다.

DOM tree + CSSOM tree -> Render tree

그리고 CSS를 파싱하여 CSSOM 트리를 만든다. DOM tree와 CSSOM tree가 만들어지면 이 둘을 합쳐 Render tree를 구성한다. 이를 바탕으로 위치를 연산하여 레이아웃을 잡고, 화면에 그리는 페인팅을 한다. 화면에 픽셀을 뿌리는 것을 말한다. 이것이 랜더링되는 과정이다. 기본적으로 각각의 요소들은 이벤트객체를 상속받고 있다. 따라서 node 또는 element에 이벤트를 걸어서 자유롭게 제어할 수 있다. node와 element에는 미묘한 차이가 있는데 이는 나중에 기회가 된다면 후술하겠다.

 

 

5. HTTP, REST

HTTP(HyperText Transfer Protocol)은 웹에서 정보를 주고 받을 수 있는 통신 규약이다. 이렇게 말하면 하나도 와닿지 않는다. 하지만 위키에는 이렇게 설명이 나온다. HTTP는 쉽게 말해서 약속이다. 글쓴이는 강아지를 키운다. 강아지가 막되먹은 행동을 하면 절대로 간식을 줘선 안된다. 강아지가 떼를 쓰고 징징대는 것을 달래겠다고 간식을 주고 어르고 달래면 강아지는 응석받이가 될 뿐이다. 강아지와 내가 약속된 방법으로 규칙을 지켜가며 말을 잘 들으면 그 때 칭찬과 간식을 아낌없이 준다. 이게 강아지와 나의 소통 방식이다.

 

실제로는 그냥 준다. 왜냐면 강아지는 너무 귀여우니까. 그래서 우리 개가 버릇이 나빠졌다.

컴퓨터와 웹에서 소통하는 방식도 이와 같다고 볼 수 있다. 컴퓨터는 나와는 달리 정이 없기 때문에 약속된 방식이 아니면 시뻘건 에러문구를 마구 쏟아내면서 오만상 화를 낸다. 내가 서버에 어떤 요청을 보내서 특정한 응답을 받고 싶다면, 정해진 양식에 맞게 요청을 보내야 한다. 거의 공무원식 일처리가 아닐 수 없다. 그런데 사람들이 생각보다 지멋대로 살아서 HTTP를 온전히 이용하지 못한다는 것을 알아차린 한 천재가 REST(Representational State Transfer)라는 간소화된 약속을 또 만들어냈다. REST라는 약속을 잘 지킨 api를 RESTful api라고 한다.

 

6. SSR CSR

옛날 옛날에, 웹은 정적페이지로 이루어져 있었다. JS로 일부는 동적으로 만들 수 있었지만 한정적이었다. 서버에 HTTP 요청을 보내면 서버에서 정적 웹 페이지를 보내주는 방식으로 행복하게 살고 있었다. 이러한 방식을 SSR(Server Side Rendering)라고 한다. 하지만 인간의 욕심은 끝이 없고, 아마도 매번 요청을 보내는 것에 불만을 느끼게 된 것 같다. 그리고 마침내 새로운 방식을 찾게 된다. 바로 CSR(Client Side Rendering)이다. 이는 서버가 아니라 클라이언트 측에서 렌더링을 하는 것이다. 매번 HTTP 요청을 보낼 필요가 없기 때문에 네트워크 비용은 감소하지만 SEO(search engine optimization) 적용이 까다로워 검색 결과에서 누락될 수 있다.

 

 

자, 이제 브라우저 동작 원리를 이해하기 위한 여정의 끝에 다다랐다. 즐거운 시간이 되었길 바란다.

여기까지 모두 이해가 됐다면 브라우저의 동작 원리는 어렵지 않게 이해할 수 있을 것이다.

그러므로 간단하게 설명하고 마치도록 하겠다.

 

브라우저 동작 원리

클라이언트에서 서버에 HTTP요청을 보낸다.

서버에서 응답으로 HTML 파일을 보내준다.

브라우저에서 렌더링 엔진이 이를 파싱하여 DOM tree를 구성한다.

HTML 파일 안에는 외부 CSS파일을 참조하고 있었다.

렌더링 엔진이 CSS를 파싱하여 CSSOM tree를 구성한다.

DOM tree와 CSSOM tree를 조합하여 Render tree를 만든다.

Render tree를 바탕으로 레이아웃을 계산한다.

계산된 레이아웃을 바탕으로 페인팅을 한다.

이 때 웹 페이지를 동적으로 만들어주는 JS 코드도 있었는데, (이 코드가 어디에 어떻게 있느냐에 따라 파싱 순서가 조금씩 달라진다. 이는 나중에 알아보도록 하자.) 자바스크립트 엔진이 소스코드를 토큰화한 후 파싱하여 AST로 만든다.

AST를 기반으로 만들어진 바이트 코드를 인터프리터가 한 줄씩 번역 후 실행하여 JS코드가 돌아간다.

JS 코드에 의해 DOM이나 CSSOM을 조작하여 Render tree가 변할 수 있다.

리플로우(레이아웃을 다시 하는 것)나 리페인팅(페인팅을 다시 하는 것)이 일어나면 굉장히 비효율적이므로 이를 최대한 지양해야 한다.

브라우저는 크게 이러한 흐름으로 움직인다.

 

 

 


 

여기까지가 브라우저의 동작원리였다.

짧지 않은 여정을 함께 따라오느라 고생 많았다.

오늘은 재미있는 브라우저의 동작 원리를 알게 되었으니 다른 사람에게 이 주제로 이야기 꽃을 피워봐도 좋을 것 같다.

 

자세히 쓰자니 스크롤 압박이 너무 심하고, 간단히 쓰자니 좀 성의없는 것 같아서

글쓴이는 추후에 이 글을 분할해서 살을 붙인 후 시리즈물로 다시 발행할 생각이다. 여기서도 파일 쪼개기가...

'WEB' 카테고리의 다른 글

이벤트 루프에 대해 알아보자  (0) 2022.08.02
[HTTP] Response에 대해 알아보자  (0) 2022.06.13
[HTTP] 요청과 응답  (0) 2022.05.24
[Tomcat] 설정 파일  (0) 2022.05.24
[Java] HttpServletMethod  (0) 2022.05.23
Comments