브라우저 동작 원리
우리가 평소에 접하는 이 화면은 도대체 어떻게 나타나게 되는 것일까?
우리는 평소처럼 당연하게 인터넷 주소창에 주소를 입력하고 거기에 해당되는 홈페이지 화면에 접속하며 사이트를 돌아다니기만 했지, 이렇게 화면이 보여지는 과정이 어떻게 동작하는지는 생각해보기는 쉽지 않다.
또한 프론트엔드 개발자 역시, HTML과 CSS 문서를 작성하고 Javascript 코드를 짜면서 기대하던 동작을 확인하며 웹 개발을 했을 것이고, 실제로 이 HTML문서가 어떻게 자리를 잡아서 웹 페이지에 각자 자리에 DOM 요소들이 세팅이 되고 CSS 스타일이 적용돼서 그려지는지 맘 잡고 학습해보지 않는 이상 생각해보는 경우가 없을 것이다.
그래서 이참에 맘 잡고 한번 자세히 알아보자.
브라우저의 주요 기능
브라우저의 주요 기능은, '선택한 자원을 서버에게 요청하고, 전송받은 자원을 브라우저 화면에 표시' 하는 것이다.
자원의 종류는 아래와 같은 요소들이 될 수 있다.
- HTML
- CSS
- JavaScript
- Image
- 기타 등등
그러면 이러한 자원은 브라우저가 어떻게 서버에게 요청을 할 수 있는 것일까?
여기서 우리는 URI(Uniform Resource Identifier) 라는 개념을 알아야 한다.
URI는 각 자원의 서버 주소를 말한다. 이 주소는 서버 어딘가에 명시되어 있고, 명시된 주소를 통해 서버에게 해당 주소의 자원을 요청하여 받아오게 된다.
URI를 통한 자원 요청 방법은 브라우저에 있는 주소 입력 창이 될 수도 있고, 데이터 요청을 위한 API 주소가 될 수도 있다.
※ 참고
우리가 브라우저 주소입력 창에 www.naver.com을 입력했다.
그러면 해당 주소에 맞는 페이지를 브라우저 화면에 보여주기 위해 HTML, CSS, Javascript 파일을 포함하여 해당 페이지에 관련된 모든 리소스 파일(이미지, 동영상 파일 등)들을 네이버 서버에게 요청을 하고 받아올 것이다.
그러면 여기서 'www.naver.com'은 URI가 되고, 페이지를 보여주기 위해 요청해서 받아온 모든 파일들이 자원이 되는 것이다.
브라우저의 기본 구조
- 사용자 인터페이스 - 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등. 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분
- 브라우저 엔진 - 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어.
- 렌더링 엔진 - 요청한 콘텐츠를 표시. 예를 들어 HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 표시함.
- 네트워킹 - HTTP 요청과 같은 네트워크 호출에 사용됨. 이것은 플랫폼 독립적인 인터페이스이고 각 플랫폼 하부에서 실행됨.
- UI 백엔드 - select / input 등 기본적인 위젯을 그림. 플랫폼에서 명시하지 않은 일반적인 인터페이스로서, OS 사용자 인터페이스 체계를 사용.
- 자바스크립트 파서 - 자바스크립트 코드를 해석하고 실행.
- 자료 저장소 - Cookie, Local storage등 local에 data를 저장하는 영역.
렌더링 엔진
렌더링 엔진은 요청받은 자원을 브라우저 화면에 표시하는 작업을 한다.
위에서 설명한 것처럼 자원의 종류는 페이지 렌더에 필요한 HTML, CSS, JavaScript 뿐 아니라 PDF, JPG 등 서버에 요청하여 가져올 수 있는 모든 것이 될 수 있다.
렌더링 엔진의 종류는 여러 가지가 있지만, 그중 대표적인 엔진 두 가지를 소개한다면 웹킷(Webkit)과 게코(Gecko)가 있는데, 웹킷은 크롬과 사파리, 게코는 파이어폭스에서 사용되는 엔진 이다.
렌더링 엔진 동작 과정
렌더링 엔진은 웹 서버로부터 전달받은 HTML 문서를 맨 처음 네트워크 레이어에서 불러온다.
그리고 아래와 같은 기본적인 Flow 를 거친다.
(세부적인 플로우 및 각 개념을 어떤 이름을 붙이는지는 브라우저별로 다를 수 있지만 우선 기본적인 단계는 아래와 같다.)
1) HTML 파싱 후 DOM 트리 만들기
2) 렌더 트리(Render Tree) 만들기
3) 렌더 트리(Render Tree) 레이아웃 만들기
4) 렌더 트리 페인팅 (Renter Tree Painting)
HTML 파싱후 DOM 트리 만들기
HTML 파싱 과정에 대해 설명하기 전에, 기본적인 컴파일 동작 과정을 보면,
렌더링 엔진은 우선 네트워크 레이어를 통해 전달받은 HTML 문서(Source code)를 파싱(Parsing) 하여 각 요소들을 DOM Tree(Contents Tree)의 각 DOM 노드 들로 전환한다.
DOM이란 Document object model 의 준말로 마크업 형태의 HTML 문서를 오브젝트 모델의 형태로 바꿔놓은 것이다.
당연히 HTML 문서의 각 마크업과 DOM의 각 요소는 1:1 매칭된다.
<html>
<body>
<p>
Hello World
</p>
<div> <img src="example.png"/></div>
</body>
</html>Copy
위 코드를 DOM Tree로 전환할 때 아래와 같이 구성된다.
렌더 트리(Render Tree) 만들기
HTML 문서들을 파싱하여 DOM Tree를 구성한 후, 렌더링 엔진은 CSS/Style 데이터를 파싱하고 그 스타일 데이터들로 렌더 트리(Render Tree)를 만든다.
DOM 트리가 웹 상에 나타날 내용(Contents)를 구성한다면 렌더 트리는 시각적 요소, 어떻게 나타날지 그 스타일을 지정한다.
렌더 트리는 색상, 차원 등 시각적 지침들을 담은 정사각형들로 구성된다.그리고 그 정사각형들은 스크린에 맞는 순서대로 정렬된어야 한다.
렌더 트리 각각의 정사각형에 해당하는 Renderer 렌더러 들은 DOM 트리 요소(element)들에 적용되지만 1:1 관계가 성립되는 것은 아니다. 시각적이지 않은 DOM 요소들은 렌더 트리에 삽입될 수 없다.
<head> 태그 안의 요소들은 화면에 나타나는 값들을 포함하지 않는다. 따라서 그 어떤 Renderer도 적용될 수 없다.
어떤 렌더러들은 DOM 노드에 적용될 수 있으나 꼭 트리의 같은 위계에 속할 필요는 없다.
렌더 트리(Render Tree) 레이아웃 만들기
레이아웃을 만든다는 것은 각 노드들에게 스크린의 어느 공간에 위치해야 할지 각각의 값(Positionm, Size)을 부여하는 것을 의미한다.
렌더 트리 페인팅 (Renter Tree Painting)
렌더 트리가 만들어져 레이아웃이 구성되었다면, UI 벡엔드가 동작하여 각 노드들을 정해진 스타일 및 위치값대로 화면에 배치한다.
더 나은 UX(User experience)를 위해, 렌더링 엔진은 각 콘텐츠를 가능한 한 빨리 스크린에 띄워야 한다.
따라서 모든 HTML 요소들을 렌더링 엔진으로 넣어서 한번에 출력하는 것이 아니라, 일부 콘텐츠는 먼저 트리 과정을 거쳐 스크린에 나타나고, 그 와중에 웹의 다른 요소들은 네트워크를 통해 렌더링 엔진으로 읽어들어 오는 순차적인 방식으로 입출력이 진행된다.