브라우저는 어떻게 동작하나요?

Hailey Choi
6 min readNov 28, 2020

--

이 글은 브라우저의 구성요소, 렌더링 순서/과정을 중심으로 브라우저의 동작원리를 이해하기 쉽게 설명합니다.

브라우저의 주요 구성요소

브라우저의 구성요소

브라우저는 사용자가 원하는 페이지를 서버에 요청하고 서버로부터 HTML, CSS, JavaScript, 이미지 파일 등을 응답 받습니다. 그리고 이 결과를 화면에 표시해주죠. 이 일련의 과정을 브라우저의 구성요소들이 담당합니다. (지금 이 단계에서 각 구성요소의 역할을 완벽히 이해하고 넘어갈 필요는 없습니다. 소개 정도로 이해해주세요.)

사용자 인터페이스(User Interface) : 주소 표시줄, 이전 / 다음 / 새로고침 버튼, 북마크 등 브라우저에서 랜더링되는 화면을 제외한 부분을 말합니다.

브라우저 엔진(Browser Engine) : 사용자 인터페이스와 연동되어 렌더링 엔진과 통신하는 중심역할을 담당합니다.

렌더링 엔진(Rendering Engine) : HTML과 CSS 파일의 랜더링을 담당합니다.

JS 해석기(JavaScript Interpreter) : 기본적으로 브라우저는 자바스크립트를 이해할 수 없기 때문에 JS 해석기가 자바스크립트 코드를 해석합니다.

UI 백엔드(UI Backend) : windows/combo boxes 같은 베이직한 위젯 컴포넌트를 그리는 역할을 합니다.

통신(Networking) : HTTP 요청과 관련된 네트워킹 기능을 담당합니다.

데이터 저장소(Data Persistence) : 데이터를 저장하는 역할을 하며 로컬 스토리지 타입과 쿠키 타입으로 나눌 수 있습니다.

브라우저 동작 과정

각 구성요소를 바탕으로 한 브라우저의 동작 과정을 순서에 따라 세 문장으로 요약할 수 있습니다.

  1. 사용자가 주소 창(사용자 인터페이스)에 URL을 입력합니다.
  2. 렌더링 엔진이 HTML과 CSS 파일을 파싱하여 화면에 나타냅니다.
  3. JS 해석기가 JavaScript 코드를 해석하고 실행합니다.

브라우저의 렌더링 과정의 핵심은 렌더링 엔진입니다. 렌더링 엔진에 대해서 더 자세히 알아보겠습니다.

렌더링 엔진

렌더링엔진은 HTML과 CSS의 파싱을 담당하고, 파싱한 결과를 화면에 그려냅니다.

웹킷 (webkit) 렌더링 엔진

렌더링 엔진은 브라우저의 제조사마다 상이합니다. 대표적으로 Firefox는 모질라에서 만든 게코(Gecko) 엔진을 사용하고, Safari는 애플에서 시작된 웹킷(Webkit), Chrome은 애플에서 시작된 블링크(Blink) 엔진을 사용합니다.

렌더링엔진에는 HTML 파서와 CSS파서가 있습니다 .

  1. 먼저 HTML 파일이 로드 되면 HTML 파서는 HTML의 태그를 노드(node)로 변환하여 Dom tree를 만듭니다.
  2. 이 과정 중에 HTML 파서가 CSS 파일이 연결되어 있는 <link />태그를 만나게 되면, CSS 파서가 CSS파일을 파싱하여 CSSOM tree를 구성합니다.
  3. 화면에 그리기 직전에 Dom tree와 CSSOM tree를 결합하여 Render tree를 생성합니다.
  4. Render tree의 각 노드(node)마다 화면의 정확한 위치에 배치(layout)가 됩니다.
  5. UI 백엔드에서 배치된 Render tree의 각 노드를 화면에 그리는 것을 도와줍니다.
CSS가 적용된 UI Component 렌더링 과정

렌더링엔진은 이 과정을 빠르게 실행하기 위해서 모든 HTML을 파싱할 때까지 기다리지 않습니다. <link>서버로부터 받은 내용의 일부를 먼저 화면에 그려내면서 나머지 내용도 도착하기를 기다립니다.

이제 브라우저에서 자바스크립트 실행을 담당하는 JS 해석기에 대해서 알아보겠습니다.

JS 해석기

브라우저는 기본적으로 자바스크립트를 이해하지 못하기 때문에 JS 해석기가 필요합니다.

렌더링 엔진의 HTML 파서가 <script>태그를 만나면 하던 일을 중단하고 제어 권한을 자바스크립트 엔진으로 넘겨주는데요. 자바스크립트 엔진은 javascript 파일을 로드하고 파싱하여 실행합니다. 실행이 완료되면 다시 HTML 파서에게 제어권한이 넘어가고 중지되었던 Dom tree 생성이 재개됩니다.

브라우저는 HTML, CSS 와 JavaScript 를 처리하는 데 있어서 동기적으로 작동한다는 것을 알 수 있습니다. 이는 렌더링 지연과도 관련이 있는데요.

동기적이란 어떤 작업을 요청했을 때 그 작업이 종료될때 까지 기다린 후 다음 작업을 수행하는 방식을 말합니다.

렌더링 지연 이슈

위에서 HTML 파서가 <script>태그를 만나면 하던 일을 중단하고 자바스크립트가 실행된다고 했었죠? 자바스크립트가 실행되는 동안 Dom 생성이 그만큼 지연되는것이죠.

그래서 우리는 <script>태그의 위치를 적절한 곳에 배치함으로써 랜더링 지연 시간을 단축할 수 있습니다. 바로 <body> 요소의 가장 아래에 자바스크립트를 위치시키는 것이죠.

<body>
...
<script><script />
</body>

이 배치는 Dom이 완성되지 않은 상태에서, 자바스크립트 실행 중 Dom에 접근하려고 하는 코드가 있는 경우 발생하는 에러를 방지할 수도 있습니다.

더 나아가 스크립트를 참조할 때 외부의 파일을 서버에서 가져오는 경우( = src 속성를 통해 파일을 로드 받아야하는 경우)라면 브라우저가 일시 중지 될 뿐만 아니라, 파일을 로딩하는데 추가적인 시간이 발생합니다.

이 경우 <script> 태그를 async로 표시하는 방법을 통해서 성능 최적화를 할 수 있는데요.

<script src="app.js" async></script>

async로 표시하게 되면 서버에서 자바스크립트 파일을 가져오는 동안 Dom 생성을 지속하라고 브라우저에게 알려주는 것입니다. <script> 태그를 만나면 바로 Dom 생성을 중단하는 것이 아니라, 자바스크립트가 로드 되고 실행 될 준비가 되었을 때 Dom 생성을 중단하는 것입니다.

지금까지 브라우저의 구성요소, 렌더링 순서와 과정, 나아가 렌더링 지연 이슈와 이에 따른 성능 최적화에 대해서 알아보았습니다.

참조

브라우저는 어떻게 동작하는가? | NAER D2

--

--