웹 브라우저 또는 브라우저는 웹에서 페이지를 찾아서 보여주고, 사용자가 하이퍼링크를 통해 다른 페이지로 이동할 수 있도록 하는 프로그램이다. 브라우저는 가장 익숙한 타입의 사용자 에이전트이다.
브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 브라우저에 표시하는 것이다. 자원은 보통 HTML 문서지만 PDF나 이미지 또는 다른 형태일 수도 있다. 자원의 주소는 URI(Uniform Resource Identifier)에 의해 정해진다.
브라우저는 HTML과 CSS 명세에 따라 HTML 파일을 해석해서 표시하는데 이 명세는 웹 표준화 기구인 W3C(World Wide Web Consortium)에서 정한다. 현재 대부분의 브라우저가 표준 명세를 따른다.
: 렌더링 엔진의 역할은 요청받은 내용을 브라우저가 화면에 표시할 수 있도록 변환하여 픽셀 단위로 나타내는 것이다.
HTML, CSS, JavaScript 등의 파일과 이미지를 표시할 수 있다. 물론 플러그인이나 브라우저 확장 기능을 이용해 PDF와 같은 다른 유형도 표시할 수 있다.
브라우저 | 렌더링 엔진 |
---|---|
IE | Trident |
Edge | EdgeHTML, Blink |
Chrome | Webkit, Blink(버전 28 이후) |
Safari | Webkit |
FireFox | Gecko |
❗ 참고
렌더링 엔진이 브라우저마다 다르기 때문에, 같은 소스가 브라우저마다 다르게 그려지는 크로스 브라우징 이슈가 발생하게 됩니다.(자바스크립트 엔진이 달라 발생하기도 합니다.)
렌더링 엔진은 통신으로부터 요청한 문서의 내용을 얻는 것으로 시작하는데 문서의 내용은 보통 8KB 단위로 전송된다.
다음은 렌더링 엔진의 기본적인 동작 과정이다.
렌더링 엔진은 HTML 문서를 Parsing하여 DOM 트리를 만들고, CSS 문서를 Parsing하여 CSSOM 트리를 만든다. DOM과 CSSOM을 이용하여 Render 트리를 만든다.
Render 트리 생성이 끝나면 " Layout → Paint → Composition " 순으로 진행된다.
Layout (reflow) : 각 Node가 화면의 정확한 위치에 표시하기 위해 위치와 크기를 계산하는 과정을 말한다. → 레이아웃 구상
Paint (rasterizing) : 계산된 위치과 크기 등의 스타일들이 레이어별로 실제 픽셀로 표현하는 과정이 시작된다.
Composition : 레이어를 순서대로 브라우저 위에 차곡차곡 표기하고 레이어를 병합한다.
위의 그림은 Webkit의 렌더링 동작 과정입니다. 위의 렌더링 동작 과정을 간략히 이야기하면,
위의 5가지 과정을 통해 브라우저는 렌더링을 한다. (색깔 별로 위의 그림의 과정을 표시했다.)
: 서버로부터 전송받은 문서의 문자열을 브라우저가 이해할 수 있는 구조로 변환하는 과정을 말한다. 파싱 결과는 문서 구조를 나타내는 노드 트리(node tree)인데, 파싱 트리(parse tree) 또는 문법 트리(syntax tree)라고 한다.
위의 그림은 동작 과정 상세에서 이야기한 DOM을 파싱하는 과정이다. 이 과정에 대해 좀 더 자세히 이야기해보도록 하자.
변환(Conversion) : HTML의 원시 바이트(raw bytes)를 읽어와 해당 파일에 지정된 인코딩(UTF-8 등…)에 따라 문자열로 변환하는 과정이다.
토큰화(Tokenizing) : 문자열을 W3C HTML5 표준에 따라 고유 토큰(<html>
, <body>
등, 꺽쇠괄호로 묶인 문자열)으로 변환하며, 각 토큰은 특별한 의미와 고유한 규칙을 가진다.
렉싱(Lexing) : 토큰을 해당 속성 및 규칙을 정의한 객체(Nodes)로 변환한다.
DOM 생성(Dom construction) : HTML은 상위-하위 관계로 정의할 수 있어, 트리 구조로 나타낼 수 있다. 렉싱 과정을 거쳐 생성된 노드들을 트리 구조로 변환한다.
위에서 이야기한 4가지 과정을 모두 거치면 위의 그림과 같은 트리 형태의 DOM이 만들어진다. 브라우저는 이후 모든 페이지 처리를 이 DOM을 사용한다.
이번에는 위의 그림과 같이 CSS를 파싱하는 과정을 살펴보자.
보다시피 DOM을 생성하는 과정 그대로 CSSOM을 생성한다.
브라우저는 DOM을 생성하는 동안 외부 CSS를 참조하는 <link>
태그를 만나게 되면 브라우저에 리소스를 요청한다. CSS의 원시 바이트(raw bytes)가 문자열로 변환된 후 차례로 토큰과 노드로 변환되고 마지막으로 CSSOM(CSS Object Model)이라는 트리 구조를 만든다.
CSSOM은 하향식으로 규칙을 적용하기 때문에 트리 구조를 가진다. 최종 스타일을 계산할 때 브라우저는 해당 노드에 적용 가능한 가장 일반적인 규칙으로 시작해 더 구체적인 규칙을 적용하는 방식이다.
<style> ... </style>
<p style="color:green">This is a paragraph.</p>
즉, 위와 같은 스타일에 관련된 모든 정보들을 Cascading Role에 따라 합해서 정의한다. → 이를 computed styles 라고 부른다.
CSSOM 트리와 DOM 트리를 결합하여, 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 형성한다. 이 과정을 웹킷에서는 Attachment라고 한다.
렌더 트리는 화면에 표시되는 각 노드의 위치를 계산하는 레이아웃에 사용되고 픽셀을 화면에 그리는 페인트 과정에도 사용된다.
브라우저가 DOM 및 CSSOM을 렌더 트리에 결합한다. 렌더 트리는 아래와 같이 페이지에 표시되는 모든 DOM 콘텐츠와 각 노드에 대한 모든 CSSOM 스타일 정보를 가진다.
렌더 트리를 생성하려면 브라우저는 대략 3가지 작업을 수행한다.
DOM 트리의 루트에서 시작하여 화면에 표시되는 노드 각각을 탐색한다.
화면에 표시되지 않는 일부 노드들(script
, meta
태그 등..)은 렌더 트리에 반영되지 않는다.
CSS에 의해 화면에서 숨겨지는 노드들은 렌더 트리에 반영되지 않는다. 위의 예시에서 span
노드의 경우 display:none
이 설정되기 때문에 렌더 트리에 반영되지 않는다.
화면에 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용한다.
화면에 표시되는 노드를 콘텐츠 및 계산된 스타일과 함께 내보낸다.
❗ 참고
visibility:hidden
은 화면에 공간을 차지하기 때문에 렌더 트리에 포함된다.
렌더 트리가 생성되고, 기기의 뷰포트 내에서 렌더 트리의 노드가 정확한 위치와 크기를 계산하는 과정을 Layout(혹은 Reflow)라고 한다. 모든 상대적인 측정값(e.g. %)은 화면에서 절대적인 픽셀로 변환된다.
렌더 트리의 각 노드를 화면의 실제 픽셀로 나타내는 과정을 Painting(혹은 rasterizing)라고 한다. Painting 과정 후 브라우저 화면에 UI가 나타나게 된다.
지금까지 이야기했던 내용들을 핵심만 요약하여 5가지로 정리해 보면,
위의 5단계를 걸쳐 브라우저는 화면에 렌더링 하게 됩니다.
❗ 참고자료
https://developer.mozilla.org/ko/docs/Glossary/Browser
https://d2.naver.com/helloworld/59361
https://beomy.github.io/tech/browser/browser-rendering/#parser