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

Screen Output

GPU 컴포지팅 · 화면 출력

합성된 최종 프레임이 GPU를 통해 디스플레이로 전송되어, 사용자가 보는 화면이 된다. 여정의 끝.

화면 출력은 브라우저가 합성한 최종 레이어들을 GPU가 실제 픽셀 프레임으로 합쳐 디스플레이에 내보내는 여정의 마지막 단계다. 컴포지터는 페인트로 만들어진 각 레이어를 텍스처로 GPU에 업로드하고, GPU는 레이어 계층을 순회하며 프레임 버퍼(frame buffer)에 그려 하나의 완성된 이미지를 만든다. 이 프레임은 곧바로 화면에 뿌려지지 않고, 디스플레이의 주사율(refresh rate, 예: 60Hz는 초당 60번)에 맞춰 수직 동기화(VSync) 신호에 동기화되어 스왑(swap)된다. VSync는 모니터가 한 프레임을 위에서 아래로 스캔하는 도중에 버퍼가 교체되어 두 프레임이 섞여 보이는 테어링(tearing)을 방지하며, 이를 위해 최소 두 개(더블 버퍼링) 또는 세 개(트리플 버퍼링)의 버퍼를 번갈아 쓴다. 최종적으로 프레임 버퍼의 각 픽셀 값이 디스플레이의 물리 픽셀(RGB 서브픽셀)로 발광하며 사용자 눈에 도달한다. 즉 전체 여정은 '상태 변경 → React 렌더(Fiber diff) → React 커밋(DOM 반영) → 브라우저 파이프라인(Style/Layout/Paint) → 합성 → GPU 프레임 버퍼 → VSync 스왑 → 픽셀 발광'으로 요약된다.

내부 구성

GPU (그래픽 처리 장치)
레이어 텍스처를 병렬로 합성·래스터화해 프레임 버퍼를 채우는 하드웨어. 컴포지팅 가속의 주체
컴포지터 (Compositor)
페인트 산출 레이어들을 텍스처로 GPU에 업로드하고 합성 명령(GL/Vulkan)을 발행하는 브라우저 구성요소(별도 스레드)
레이어 텍스처 (Layer Texture)
각 합성 레이어의 픽셀 데이터를 담는 GPU 텍스처. transform/opacity는 이 텍스처를 재합성만 해 저렴하다
프레임 버퍼 (Frame Buffer)
완성된 한 프레임의 전체 픽셀을 담는 메모리. 프론트(표시)·백(그리기) 버퍼로 구성
백 버퍼 / 프론트 버퍼 (Double/Triple Buffering)
그리는 버퍼와 표시하는 버퍼를 분리·순환해 렌더와 스캔아웃을 디커플링, 테어링·스터터링 완화
주사율 (Refresh Rate)
디스플레이가 초당 프레임을 갱신하는 횟수(Hz). 프레임 예산(1/Hz초)과 애니메이션 부드러움을 결정
VSync (수직 동기화)
수직 블랭킹 구간에 버퍼 스왑을 정렬하는 신호. 앱 렌더·컴포지터·디스플레이 리프레시의 타이밍을 동기화
스캔아웃 (Scanout)
프레임 버퍼의 픽셀을 스캔라인 단위로 위→아래 순차 전송해 디스플레이 패널을 구동하는 과정
픽셀 / 서브픽셀 (Pixel / Subpixel)
화면의 최소 발광 단위. 각 픽셀은 RGB 서브픽셀로 이뤄져 프레임 버퍼 색값대로 발광해 최종 이미지를 형성

핵심 포인트

  • 컴포지터가 페인트된 레이어를 텍스처로 GPU에 올리고, GPU가 레이어 계층을 순회하며 프레임 버퍼에 합성한다
  • 프레임 버퍼(frame buffer): 한 프레임의 모든 픽셀 색값을 담는 GPU 메모리 영역. 완성되면 디스플레이로 스캔아웃된다
  • 주사율(refresh rate): 디스플레이가 초당 화면을 갱신하는 횟수(60Hz=16.7ms/frame, 120Hz=8.3ms). 애니메이션 예산의 기준
  • VSync(수직 동기화): 모니터의 수직 블랭킹 구간에 맞춰 버퍼를 스왑, 스캔 중 교체로 생기는 테어링을 방지
  • 더블/트리플 버퍼링: 프론트 버퍼(표시용)와 백 버퍼(그리기용)를 분리·순환해 렌더와 표시를 디커플링
  • 픽셀: 프레임 버퍼의 값이 디스플레이의 물리 RGB 서브픽셀 발광으로 변환되어 최종 이미지가 된다
  • 전체 여정: 상태 변경→React 렌더/커밋→브라우저 파이프라인→합성→GPU 프레임 버퍼→VSync 스왑→화면

심화

실무에서 이 단계를 이해해야 하는 이유는 '프레임 예산(frame budget)'이라는 절대 마감선 때문이다. 60Hz 디스플레이는 VSync가 16.7ms마다 오고, 그 안에 자바스크립트+스타일+레이아웃+페인트+합성을 모두 끝내지 못하면 프레임이 스킵되어 사용자는 버벅임(jank)을 느낀다. 컴포지팅은 별도 컴포지터 스레드에서 돌기 때문에, transform/opacity 애니메이션은 메인 스레드가 긴 JS로 막혀 있어도 GPU가 계속 부드럽게 프레임을 뽑아낼 수 있다 — 이것이 '컴포지터 온리(compositor-only) 애니메이션'을 권장하는 근본 이유다. 면접에서 한 단계 더 들어가면 '왜 requestAnimationFrame인가'가 나온다. rAF 콜백은 브라우저가 다음 리페인트 직전, 즉 VSync 주기에 맞춰 호출하기로 약속한 훅이라, setTimeout처럼 리프레시와 어긋나 프레임을 두 번 그리거나 건너뛰는 낭비를 막는다. 또 VSync를 켜면 테어링은 사라지지만 GPU가 다음 스왑까지 대기하므로 입력 지연(latency)이 늘어나는 트레이드오프가 있고, 이를 완화하려 트리플 버퍼링이나 가변 주사율(VRR, G-Sync/FreeSync)이 등장했다. 전체 그림을 요약하면: 개발자가 만지는 것은 파이프라인 앞단(JS·CSS)뿐이지만, 그 선택이 뒷단의 레이아웃/페인트/합성 비용을 결정하고, 그 비용이 프레임 예산 안에 들어와야만 GPU와 VSync를 거쳐 매끄러운 픽셀로 사용자에게 도달한다는 것이다.

쉽게 말하면 완성된 필름을 영사기(GPU)로 스크린(모니터)에 비추는 마지막 순간.

면접 예상 질문

#GPU#프레임 버퍼#주사율#화면 출력