탐색으로 돌아가기
Browser8 / 24 단계

Renderer Process

렌더러 프로세스

탭 하나의 웹 콘텐츠를 담당하며, 메인 스레드에서 파싱·스타일·레이아웃·JS를 처리한다.

렌더러 프로세스(renderer process)는 탭 하나(정확히는 사이트 인스턴스) 안에서 벌어지는 거의 모든 일을 처리하는 프로세스로, 내부는 여러 스레드로 구성된다. 중심은 메인 스레드(main thread)로, 여기서 HTML/CSS 파싱, DOM 구성, 스타일 계산(recalc), 레이아웃(layout), 히트 테스트, 이벤트 디스패치, 그리고 V8을 통한 JavaScript 실행과 문서 라이프사이클(document lifecycle)이 돌아간다. 스크롤·애니메이션·입력 처리는 컴포지터 스레드(compositor thread)로 분리되어, 메인 스레드가 무거운 JS로 막혀 있어도 부드러운 스크롤이 가능하도록 성능을 격리한다. 컴포지터가 레이어를 타일(tile)로 쪼개면 래스터 스레드(raster/compositor worker thread)들이 각 타일을 실제 픽셀로 래스터화하여 GPU 메모리에 저장한다. 이 외에 Web Worker/Service Worker/OffscreenCanvas를 돌리는 워커 스레드, 오디오·비디오를 다루는 미디어 스레드가 있다. 렌더링 엔진 Blink는 DOM과 웹 표준 API·렌더 파이프라인을 구현하고, V8은 JS와 WebAssembly를 실행하며, 이 모든 것은 신뢰할 수 없는 코드를 실행하므로 강한 샌드박스(sandbox) 안에 갇혀 있다.

내부 구성

메인 스레드 (Main Thread)
HTML/CSS 파싱, DOM 구성, 스타일 재계산, 레이아웃, 페인트 기록, 히트 테스트, 이벤트 디스패치, V8을 통한 JS 실행과 document lifecycle을 실행한다
컴포지터 스레드 (Compositor Thread)
입력 이벤트 처리, 스크롤·애니메이션, 최적 레이어화 계산, 이미지 디코드·래스터·paint worklet 태스크 조율을 담당해 메인 스레드와 성능을 격리한다
래스터 스레드 (Raster / Compositor Worker Threads)
컴포지터가 나눈 레이어 타일을 실제 픽셀 비트맵으로 래스터화하여 GPU 텍스처 타일로 저장한다
워커 스레드 (Worker Threads)
Web Worker/Service Worker의 스크립트와 OffscreenCanvas의 렌더링 이벤트 루프를 메인 스레드와 별개로 실행한다
미디어/오디오 스레드 (Media & Audio Threads)
비디오·오디오 스트림을 메인 렌더 파이프라인과 독립적으로 디코드·처리·동기화한다
V8 엔진 (V8 JavaScript Engine)
JavaScript와 WebAssembly를 파싱·컴파일(JIT)·실행한다. 메인 스레드(및 워커)에서 스크립트를 구동한다
Blink 렌더링 엔진 (Blink Rendering Engine)
DOM·CSSOM·웹 플랫폼 API를 구현하고 스타일→레이아웃→페인트→커밋의 렌더 파이프라인을 오케스트레이션한다
cc / 컴포지터 (Chromium Compositor, cc)
메인 스레드의 레이어 트리를 커밋받아 컴포지터 스레드에서 타일링·래스터·프레임 생성을 관리하는 레이어 합성 모듈이다
샌드박스 (Sandbox)
렌더러가 파일·네트워크·시스템콜에 직접 접근하지 못하게 OS 수준에서 격리한다. 특권 작업은 IPC로 브라우저 프로세스에 위임한다

핵심 포인트

  • 메인 스레드는 파싱·스타일·레이아웃·페인트 준비·JS 실행·문서 라이프사이클을 모두 처리하는 병목 지점이다
  • 컴포지터 스레드는 입력·스크롤·애니메이션·레이어화(layerization)를 담당해 메인 스레드가 막혀도 스크롤이 부드럽다
  • 래스터 스레드는 컴포지터가 나눈 타일을 픽셀로 래스터화해 GPU 텍스처에 저장한다
  • 워커 스레드는 Web/Service Worker와 OffscreenCanvas를, 미디어 스레드는 오디오·비디오 디코딩을 독립적으로 처리한다
  • Blink는 렌더링 엔진(DOM·CSS·웹 API·렌더 파이프라인)이고 V8은 JS/WASM 엔진으로, 둘은 바인딩으로 연결된다
  • 렌더러는 신뢰할 수 없는 웹 콘텐츠를 실행하므로 샌드박스로 격리되어 OS 자원에 직접 접근하지 못한다
  • 실제 화면 합성·그리기는 렌더러가 아니라 GPU 프로세스(Viz)에서 일어나며 렌더러는 컴포지터 프레임을 제출한다

심화

핵심 통찰은 '왜 메인 스레드와 컴포지터 스레드를 나누는가'이다. 스크롤이나 transform 애니메이션이 메인 스레드에 묶여 있으면, 무거운 JS(예: 대량 반복문)가 도는 동안 스크롤이 뚝뚝 끊긴다. 그래서 이미 레이어로 승격(promote)된 콘텐츠는 컴포지터 스레드가 메인 스레드 개입 없이 GPU 텍스처를 이동시켜 스크롤·애니메이션을 처리한다. 여기서 나오는 실무 개념이 'compositor-only 애니메이션'이다. transform과 opacity만 바꾸는 애니메이션은 레이아웃·페인트를 유발하지 않고 컴포지터 스레드에서만 처리되어(will-change로 레이어 승격) 60fps를 유지하지만, top/left나 width 같은 속성은 레이아웃을 다시 돌려 메인 스레드를 막는다. 또 하나 자주 오해하는 지점은 '렌더러가 화면에 직접 그린다'는 것인데, 실제로는 그렇지 않다. 래스터된 타일과 레이어 정보는 컴포지터 프레임(compositor frame)으로 묶여 GPU 프로세스(Viz)의 display compositor로 제출되고, Viz가 모든 렌더러·브라우저 UI의 프레임을 하나로 aggregate해 화면에 표시한다. 즉 렌더러는 '무엇을 어디에 그릴지' 지시를 만들고, 실제 픽셀을 스크린에 올리는 것은 GPU 프로세스다. 이 분리가 보안(GPU 드라이버 크래시 격리)과 성능(여러 프레임 소스 통합)을 동시에 달성한다.

쉽게 말하면 작업실(렌더러) 안에서 편집자(메인 스레드)가 원고(HTML/CSS/JS)를 지면(화면)으로 조판하는 것.

면접 예상 질문

#렌더러#메인 스레드#샌드박스#컴포지터