Web/[JS] FrontEnd

브라우저 작동 원리1 - 브라우저 구조

ihl 2021. 10. 15. 03:46

Browser

  웹 브라우저란 인터넷에서 사용자의 요청에 따라 HTML, 그림, 미디어 등의 자원을 서버에 요청하고 화면에 표시해주는 응용 프로그램이다. 대표적으로 크롬, 파이어폭스, 사파리 등이 있다. 특히 크롬을 중심으로 웹 브라우저는 어떻게 구성이 되어있고, 어떤 동작을 하는지 내가 이해한 바를 정리해보고자 한다.

 

1. 브라우저의 구조

브라우저를 구성하는 요소들

  브라우저의 구조는 제품 별로 조금씩 다르지만 위 그림의 요소들을 포함하고 있다. 위 요소이 모두 동급의 프로세스 혹은 스레드라기 보단 이러한 역할을 하는 요소들이 존재한다라는 식으로 이해하면 좋을 것 같다.

 

  • User Interface : 주소 표시줄, 이전/다음 버튼 등 컨텐츠를 보여주는 부분을 제외한 곳
  • 브라우저 프로세스 : User Interface와 렌더러 프로세스사이의 동작을 제어 및 렌더러 프로세스를 관리한다. 예를 들어 주소 표시줄에 주소가 변경되면 렌더러 프로세스를 호출하여 화면을 그리거나, 페이지에서 입력이 발생하면 이를 렌더러 프로세스에 전달한다.
  • 렌더러 프로세스 : 브라우저에 컨텐츠를 그려주는 역할을 수행하는 프로세스
  • UI 백엔드 : OS의 UI를 참조하여 버튼, 체크 박스 등 기본 요소들을 그린다.
  • 네트워크 : HTTP, FTP 등의 네트워크 요청 수행 및 통신 관련 보안 문제를 처리한다.
  • JS 인터프리터 : JS 코드를 해석하고 실행하는 도구 V8 엔진이 이에 속한다. 
  • 데이터 저장소 : Local Storage, Cookie 와 같은 데이터를 로컬에 저장한다.

 

2. 브라우저의 프로세스

  브라우저는 어떤 프로세스로 구성되어있을까? 사실 웹 브라우저가 어떤 프로세스를 가져야한다는 표준이 없기 때문에 어떤 프로세스는 하나의 프로세스에 여러 스레드가 있을 수도 있고, 여러 프로세스로 구성되어 있을 수도 있다. 

 

  크롬 브라우저는 여러 개의 프로세스로 이루어진 프로그램이다. 따라서 각 프로세스는 각자에게 할당된 메모리를 가지며, 프로세스간 공유해야할 메모리가 있거나 통신이 있다면 IPC를 이용하여 통신해야한다. 이 프로세스들은 여러 개의 스레드들로 구성될 수 있다. 스레드간에는 메모리를 공유할 수 있다.

 

  크롬 브라우저가 멀티 프로세스로 구성된 이유는 무엇일까? 싱글 프로세스였다면 브라우저에서 탭을 여러 개 킨 상태에서 하나의 잘못된 페이지에 접근할 경우 혹은 렌더링에 문제가 발생했을 때 브라우저 전체가 종료될 수 있다. 이 떄 정상적인 동작을 수행한 탭들은 억울하게 잃어버리게 된다. 실제로 이런 일이 종종 발생했기 때문에 멀티 프로세스로 구성이 되었다고 한다. 또한 프로세스 분리를 통해 각 프로세스가 접근 가능한 메모리 범위를 격리하고 보호할 수 있는 장점이 있다.

 

Chromium Structure

  크롬 브라우저는 다양한 프로세스를 갖지만 그중 가장 기본이 되는 것은 브라우저 프로세스와 렌더러 프로세스이다. 하나의 브라우저를 실행하면 브라우저 프로세스는 단 한가지이며 렌더러 프로세스는 여러 개일 수 있다. 크롬의 경우 기본적으로 탭마다 렌더러 프로세스를 생성하며, 설정에 따라 사이트(도메인)별로 렌더러 프로세스가 할당되기도 한다.(iframe 포함) 프로세스가 너무 많거나 이미 해당 도메인으로 이동한 프로세스가 있는 경우 이미 있는 프로세스를 재사용하기도 한다.

 

  크롬은 사이트 별로 렌더러 프로세스를 할당시켜 사이트 격리를 구현한다. 사이트 격리란 서로 다른 웹사이트의 페이지가 항상 서로 다른 프로세스에 배치되도록 하는 것이다. 즉, A 사이트의 웹 페이지 내에 B 웹사이트의 페이지를 가리키는 iframe이 존재하는 것이 문제점이라는 것이다. 어떤 점이 문제일까? 바로 동일 출처 정책(SOP)에 위반되기 때문이다. SOP는 한 사이트가 다른 사이트 자원을 접근할 수 없는 것을 의미한다. 따라서 이 둘을 다른 프로세스에서 격리함으로서 사이트를 분리하는 것이다.

 

  반면 다중 프로세서의 단점은 메모리가 비효율적으로 운영될 수 있다는 점이다. 프로세스간에는 메모리가 공유되지 않기 때문에 프로세스간에 공통으로 갖고 있어야 하는 부분(ex. V8)이 각 프로세스 별로 복사되어 갖고있는 경우가 있다. 크롬은 메모리를 절약하기 위해 기기에 따라 실행가능한 프로세스를 제한하고, 한계에 도달하면 여러 탭을 하나의 프로세스에서 처리하기도 한다.

브라우저 프로세스

  크롬 브라우저에서 브라우저 프로세스는 최상위 프로세스이다. 브라우저 프로세스는 User Interface 부분을 제어하고, 각 프로세스들을 조율하는 역할을 한다. 브라우저 프로세스는 메인 UI(User Interface) 스레드와 I/O 스레드를 항상 유지한다. 메인 UI 스레드는 탭을 관리하고, I/O 스레드를 이용하여 렌더러 프로세스와 통신하며 렌더러 프로세스가 UI를 그리도록 한다. I/O 스레드는 렌더 프로세스와의 IPC 통신, 네트워크 통신을 처리한다. 예를 들어 주소창에 naver.com을 입력 후 엔터를 치면 I/O 스레드로 naver.com에 콘텐츠를 요청한다. 콘텐츠가 도착하면 브라우저 프로세스의 메인 UI 스레드는 렌더러 프로세스에게 I/O 스레드를 통해 화면을 그리도록 요청하고, I/O 스레드는 콘텐츠가 html과 같은 프로세스가 다룰 수 있는 형태이므로 렌더러 프로세스에 전달한다.

 

렌더러 프로세스

  렌더러 프로세스는 HTML과 CSS, JavaScript를 사용자가 상호작용을 할 수 있는 웹 페이지로 그리는 것이다. 렌더러 프로세스는 메인 스레드와 렌더 스레드라는 2가지 프로세스를 유지한다. 메인 스레드는 렌더 스레드와 브라우저 프로세스와의 통신을 위한 RenderProcess 객체가 존재한다. 렌더 스레드는 웹 페이지를 생성한다. 렌더 스레드는 크롬의 렌더링 엔진인 Blink(혹은 Webkit)를 통해 화면을 그린다. Blink는 핵심 레이아웃 기능을 포함하는 WebCore와 JavaScript 인터프리터인 V8 엔진으로 구성된다. 렌더러 프로세스는 필요에 따라 워커 스레드를 이용하여 JS 코드의 일부를 처리하기도 하고, 페이지를 부드럽게 렌더링 하기 위한 컴포지터 스레드, 래스터 스레드를 실행하기도 한다.

 

  이 외에도 Flash와 같은 플러그인을 제어하는 플러그인 프로세스, GPU 작업을 수행하는 GPU 프로세스 등 다양한 프로세스들이 존재한다.


브라우저 엔진 vs 렌더링 엔진 : https://stackoverflow.com/questions/46169376/whats-the-difference-between-a-browser-engine-and-rendering-engine

모던 웹 브라우저 들여다보기 : https://developers.google.com/web/updates/2018/09/inside-browser-part1?hl=ko

크롬 뒤에 숨겨진 마법을 살펴보자 : https://zicodeng.medium.com/explore-the-magic-behind-google-chrome-c3563dbd2739

웹 브라우저가 프로세스와 스레드를 사용하는 방법 : https://levelup.gitconnected.com/how-web-browsers-use-processes-and-threads-9f8f8fa23371

Chrominum Project - Multi Process : https://velog.io/@djunnni/1.-Chromium-Projects-Multi-Process-Architecture