브라우저의 동작 방식(1)

이 글은 네이버 D2의 ‘브라우저는 어떻게 동작하는가?’ 글을 보며 정리한 내용을 포스팅한 것이다. 기본적으로 프론트엔드 웹 개발을 한다고 하면, 브라우저는 기본 중에 기본이라고 할 수 있는데, 이러한 브라우저의 동작 방식에 대해서 확실히 정리하고 알 필요가 있을 것 같아서 정리하게 되었다. 여기서 말하는 브라우저는 다들 사용하고 있는 크롬, 파이어폭스, 사파리와 같은 오픈소스 브라우저이다.

브라우저의 주요 기능

브라우저의 주요 기능은 사용자가 요청한 것을 서버에 요청해주고 해당 결과를 받아서 보여주는 것이다. 해당 자원은 일반적으로 보는 웹페이지처럼 HTML일 수도 있고, 아니면 이미지 파일이나 PDF 파일일 수도 있다. 이러한 자원의 주소는 URI(Uniform Resource Identifier)에 의해 정해지며, HTML 파일을 해석할 때는 W3C에서 정한 표준을 따른다.

브라우저의 기본 구조

브라우저는 주로 아래 그림과 같은 구조로 되어있다.

브라우저의 기본구조

  1. 사용자 인터페이스 - 브라우저에서 보이는 주소표시줄과 이전/다음 버튼, 북마크 메뉴 등 기능 버튼들에 해당한다.
  2. 브라우저 엔진 - 사용자 인터페이스와 렌더링 엔진 사이 동작을 제어한다.
  3. 렌더링 엔진 - 요청한 컨텐츠를 표시한다. (HTML을 요청할 경우 HTML과 CSS를 파싱하여 표시하는 역할을 한다.)
  4. 통신 - HTTP 요청과 같은 네트워크 호출에 사용된다.
  5. 자바스크립트 해석기 - 자바스크립트 코드를 해석하고 실행한다.
  6. UI 백엔드 - 콤보 박스와 같은 기본적인 장치들을 그리고 OS 사용자 인터페이스 체계를 사용한다.
  7. 자료 저장소 - 쿠키 뿐만 아니라 모든 종류의 자원을 저장하는 계층이다. (웹 데이터 베이스)

크롬을 예로 들면 탭마다 별도의 렌더링 엔진 인스턴스가 유지되고, 각 탭마다 독립된 프로세스 이다.

렌더링 엔진

렌더링 엔진은 요청받은 내용을 화면에 표시하기 때문에 중요한 역할을 담당한다. 파이어폭스는 게코(Gecko)라는 엔진을 사용하고, 크롬과 사파리는 웹킷(Webkit)엔진을 사용한다.

렌더링 엔진의 동작과정은 다음과 같다. 렌더링엔진 동작과정

렌더링엔진은 먼저 전달받은 HTML을 파싱해서 태그들을 DOM 노드로 변경한다. 그리고 외부 CSS 파일과 스타일 요소도 파싱하여 렌더 트리를 생성한다. 그리고나서 렌더 트리를 배치하는데 이 과정이 지난 포스트에서 다룬 Reflow와 관련된 과정이고, 배치가 끝나고 나면 마지막에 UI 백엔드에서 렌더 트리를 그리는 과정으로 마무리된다. 여기서 기억할 것은 렌더링 엔진은 가능한 빠르게 표시하기 위해서 HTML 파싱이 끝나기 전에 배치와 그리기 과정을 진행한다. 표시가능한 것부터 그리고 네트워크로부터 나머지 내용이 전송된 후에 마저 표시한다.

웹킷 엔진의 동작 과정은 아래와 같다. 웹킷엔진 동작 과정

파싱과 DOM 트리 구축

파싱은 렌더링 엔진에서 매우 중요한 과정이다. 파싱은 브라우저가 코드를 이해할 수 있도록 구조 변환하는 가정이다. 보통 노드 트리로 나타내고, 파싱 트리라고도 한다.

파싱은 어휘 분석과 구문 분석, 두 가지로 구분되는데, 어휘 분석은 자료를 토큰으로 분해하는 것이고, 구문 분석은 구문 규칙을 적용하는 과정이다. 파서는 어휘 분석기로 부터 토큰을 전달받고 해당 토큰을 구문 규칙과 일치하는지 구문 분석하여 규칙에 일치하면 파싱 트리에 추가하고 또 새로운 토큰을 받아 처리하는 것을 반복한다.

HTML파서는 HTML 마크업을 파싱 트리로 변환하고, 파싱 트리는 DOM 요소와 속성 노드의 트리로 출력 트리가 된다. DOM은 Document Object Model의 약자로 이것은 HTML 문서의 객체 표현이라고 할 수 있다. DOM은 마크업과 1:1 관계를 맺는다.

<html>
  <body>
    <p>Hello World</p>
    <div><img src="example.png" /></div>
  </body>
</html>

위와 같은 구조가 DOM 트리로 변환 되면 아래와 같이 된다.

DOM트리

스크립트와 스타일 시트 진행 순서

스크립트

웹은 파싱과 실행이 동시에 수행되는 동기화 모델이다. 하지만 파서가 <script>를 만나면 문서의 파싱이 중단된다. 만약 html 태그 내부가 아닌 외부에 있다고하더라도, 실시간으로 처리되고 자원을 받을 때까지 파싱이 중단된다. 만약 스크립트를 지연(defer) 표시하면 파싱이 전부 완료된 이후 스크립트가 실행될 수 있다. 웹킷과 파이어폭스는 예측 파싱을 지원하는데 스크립트를 실행하는 동안 다른 스레드가 문서의 나머지 부분을 파싱할 수 있다. 이런 방식은 전체적인 성능을 개선 할 수 있다. 예측 파서는 DOM트리를 수정하지 않고 메인 파서의 일로 넘긴다. 예측 파서의 역할은 외부 스크립트, 외부 스타일시트, 외부 이미지와 같이 외부 자원 파싱에 국한되어 있다.

스타일 시트

스타일 시트의 경우에는 다른 모델을 사용하고 DOM트리를 변경하지 않기 때문에 문서 파싱을 기다리거나 중단할 이유가 없다. 하시만 스크립트에서 문서를 파싱하는 동안 스타일 정보를 호출할 수 있기 때문에 스타일이 파싱되지 않은 상태에서 스크립트는 잘못된 결과를 반환할 수 있다. 그렇기 때문에 스타일 시트는 스트립트 실행전에 완료되어야 하고, 스크립트는 스타일 시트가 로드 된 후 실행되어야 한다.

다음 포스트에 이어서 렌더 트리 부분 부터 포스팅하려고 한다.


참고

  1. 브라우저는 어떻게 동작하는가?’

Written by@[Ykss]
고이게 두지 않고 흘려보내는 개발자가 되자.

GitHubInstagramLinkedIn