9장. 계산된 화면은 어떻게 픽셀과 프레임이 될까

페인트와 합성, 화면이 픽셀이 되는 마지막 구간

z-index를 크게 주면 GPU 가속이 되나요?

그렇지 않습니다. 스태킹 컨텍스트는 CSS가 정하는 그리기 순서와 겹침의 의미이고, 합성 레이어는 브라우저가 렌더링 결과를 관리하려고 쓰는 구현 단위입니다. 모든 스태킹 컨텍스트가 별도 GPU 레이어가 되지는 않습니다.

8장에서 브라우저는 표시할 박스의 크기와 위치를 계산했습니다. 이제 제목의 글자 모양, 카드의 배경색, 이미지, 테두리와 그림자를 실제 화면에 나타내야 합니다. 이 과정을 흔히 페인트(paint)와 합성(compositing)이라고 부릅니다.

입문서에는 다음 파이프라인이 자주 등장합니다.

스타일 → 레이아웃 → 페인트 → 래스터 → 합성 → 화면

이 그림은 변화가 어느 단계까지 영향을 미치는지 생각하는 데 유용합니다. 그러나 엔진은 결과를 재사용하고 작업을 나누며 일부 단계를 건너뛸 수 있습니다. 레이어와 타일을 구성하는 방식도 구현마다 다릅니다. 이 장에서는 Chromium 계열에서 관찰할 수 있는 모형을 중심으로 CSS가 보장하는 의미와 브라우저의 최적화를 구분합니다.

엔진이 다르면 무엇이 달라지나

WebKit과 Gecko는 내부 단계의 명칭도, 어떤 콘텐츠를 독립 레이어로 승격할지 정하는 조건도 Chromium과 다를 수 있습니다. 개발자 도구의 패널 이름과 표시 항목이 브라우저마다 갈리는 까닭입니다. 다만 기하 계산 → 그리기 항목 기록 → 래스터 → 합성이라는 흐름의 순서 자체는 세 엔진이 공유합니다. 명칭을 외우는 대신 지금 보고 있는 작업이 이 흐름의 어느 단계인지 묻는 편이 옮겨 다니기 좋습니다.

페인트는 곧바로 모든 픽셀을 칠한다는 뜻만은 아닙니다

레이아웃 결과에는 박스의 위치와 크기가 있습니다. 페인트 단계에서는 무엇을 어떤 순서와 모양으로 그릴지 기록합니다. 배경을 채우고, 테두리를 그리고, 글자와 이미지를 표시하며, 그림자와 장식을 적용하는 등의 그리기 항목이 만들어집니다. Chromium의 설명에서는 페인트가 디스플레이 목록(display list) 같은 그리기 명령을 만들고, 래스터화(rasterization)가 그 명령을 픽셀로 바꾸는 과정으로 나뉩니다.

변경된 영역과 필요한 그리기 항목만 무효화될 수 있고, 래스터 작업은 타일 단위로 나뉠 수 있습니다. 실제 범위와 장치 사용 여부는 엔진의 판단에 달려 있습니다.

다음 카드의 배경색만 바꾼다고 합시다.

.card {
  width: 280px;
  padding: 16px;
  background: white;
}

.card.selected {
  background: #fff1f0;
}

카드의 기하 정보가 그대로라면 새 레이아웃이 필요하지 않을 가능성이 큽니다. 하지만 배경의 그리기 결과는 달라지므로 페인트와 이후 작업이 필요할 수 있습니다. 반대로 width를 바꾸면 카드 크기, 내부 줄바꿈, 이웃의 위치가 달라져 스타일 계산과 레이아웃부터 다시 필요할 가능성이 큽니다.

‘가능성이 크다’고 표현하는 이유는 속성 하나가 전체 상황을 결정하지 않기 때문입니다. 의존하는 사용자 지정 속성, 애니메이션 방식, 포함 관계, 브라우저 최적화와 현재 레이어 구성이 영향을 줍니다. 성능 표는 진단의 출발점이지 구현 계약이 아닙니다.

그리는 순서와 합성 레이어는 서로 다른 층에서 정해집니다

요소가 겹치면 무엇을 먼저 그리고 무엇을 위에 보일지 정해야 합니다. CSS의 페인팅 순서와 스태킹 컨텍스트(stacking context)는 이 시각적 순서를 설명합니다. position과 z-index, opacity, transform 같은 조건이 새로운 스태킹 컨텍스트를 만들 수 있습니다.

하지만 스태킹 컨텍스트와 합성 레이어(composited layer)는 같지 않습니다.

  • 스태킹 컨텍스트는 CSS에 따른 그리기 순서와 겹침의 의미입니다.
  • 합성 레이어는 브라우저가 렌더링 결과를 관리하고 결합하기 위해 사용하는 구현 단위입니다.
  • 모든 DOM 요소가 독립 레이어를 갖는 것도 아니고, 모든 스태킹 컨텍스트가 반드시 별도 GPU 레이어가 되는 것도 아닙니다.

브라우저는 스크롤, 변형, 동영상, 캔버스, 겹침 관계, 메모리 비용 등의 조건을 보고 일부 콘텐츠를 독립적으로 합성할 수 있는 단위로 관리합니다. 이 판단은 버전과 장치, 페이지 상태에 따라 달라질 수 있습니다. z-index: 9999를 주면 GPU 가속된다는 설명이나, 요소마다 투명 필름 한 장이 생긴다는 설명은 틀립니다.

합성은 준비된 결과를 최종 프레임으로 결합합니다

래스터 결과가 준비되면 합성 단계는 필요한 표면이나 타일을 올바른 위치와 순서로 결합해 프레임을 만듭니다. 스크롤 위치, 잘림, 변형, 투명도 같은 정보가 이 과정에 관여할 수 있습니다. 현대 브라우저는 합성 작업에 GPU를 활용할 수 있지만 ‘합성=무조건 GPU’라는 등식은 아닙니다. 장치와 드라이버, 브라우저 설정, 콘텐츠와 자원 상태에 따라 경로가 달라집니다.

합성의 이점은 이미 준비된 콘텐츠의 위치나 투명도만 바뀌는 경우에 드러날 수 있습니다. 브라우저가 해당 콘텐츠를 독립적으로 합성 가능한 형태로 보유하고 있다면, DOM의 다른 부분을 다시 레이아웃하거나 페인트하지 않고 합성 정보만 갱신할 수 있습니다. 그러나 독립 표면을 처음 만드는 비용, 내용을 래스터하는 비용, 메모리 사용량은 사라지지 않습니다.

따라서 “GPU를 쓰면 공짜”가 아닙니다. 고해상도 이미지를 가진 큰 요소를 여러 레이어로 유지하면 GPU 메모리와 전송 비용이 늘 수 있습니다. 레이어가 지나치게 많으면 관리와 합성 비용도 커질 수 있습니다. 브라우저가 요소를 언제 별도 레이어로 만들지 전적으로 개발자가 명령할 수 있는 것도 아닙니다.

변경한 속성에 따라 필요한 단계가 달라질 수 있습니다

렌더링 비용을 설명할 때 다음 표를 출발점으로 사용할 수 있습니다.

변경의 예 흔히 필요한 작업 반드시 확인할 조건
width, height, padding, 글꼴 크기 스타일, 레이아웃, 페인트, 합성 주변 박스와 줄바꿈에 실제 영향이 있는가
color, background, box-shadow 스타일, 페인트, 합성 페인트 범위와 효과의 복잡도는 얼마인가
transform 스타일, 합성만으로 처리될 가능성 콘텐츠가 합성 가능한 상태인지, 래스터 갱신이 필요한지
opacity 스타일, 합성만으로 처리될 가능성 그룹 투명도·겹침·레이어 상태와 메모리 비용
DOM 삽입·텍스트 변경 스타일과 레이아웃부터 영향을 줄 수 있음 새 내용의 크기와 위치, 영향 범위

이 표에서 transform과 opacity에도 ‘가능성’이라고 쓴 점이 핵심입니다. 이 속성을 사용했다고 GPU 레이어 승격이나 합성 전용 처리가 표준으로 보장되지는 않습니다. 다른 효과와 결합하거나 콘텐츠가 다시 래스터되어야 한다면 페인트 비용이 생길 수 있습니다. 언제나 개발자 도구로 확인해야 합니다.

또한 작업이 한 단계에서 끝난다는 것은 앞 단계의 결과가 이미 유효하다는 전제입니다. 요소가 처음 나타나는 순간에는 스타일·레이아웃·페인트·래스터가 필요할 수 있습니다. 그 뒤 위치만 바꾸는 애니메이션에서 이전 결과를 재사용할 수 있는지가 관건입니다.

transform은 시각적 변형이지 일반 흐름의 재배치가 아닙니다

메뉴를 오른쪽으로 움직이는 두 방법을 비교해 봅시다.

/* 기하 위치에 영향을 주기 쉬운 방식 */
.menu.open {
  left: 0;
}

/* 그려진 좌표계를 변형하는 방식 */
.menu {
  transform: translateX(-100%);
}

.menu.open {
  transform: translateX(0);
}

CSS 변형(transform)은 요소가 보이는 좌표계를 이동·회전·확대·축소할 수 있습니다. 변형은 주변 콘텐츠의 일반 흐름 배치를 다시 밀어내지 않습니다. 원래 레이아웃 위치는 유지된 채 시각적 결과가 옮겨집니다. 다만 변형된 영역은 넘침 영역 계산 등에 영향을 줄 수 있고, 새로운 스태킹 컨텍스트와 포함 블록을 만드는 등의 의미도 있습니다.

이 특성 때문에 이동 애니메이션에서 left나 margin-left보다 transform이 적합한 경우가 많습니다. 주변 레이아웃을 매 프레임 바꿀 의도가 아니라 이미 배치된 패널을 시각적으로 미끄러뜨리려는 경우입니다. 반대로 이동한 요소가 실제로 이웃을 밀어내야 한다면 transform은 레이아웃 의미를 충족하지 못합니다. 성능 때문에 잘못된 CSS 의미를 선택해서는 안 됩니다.

opacity는 내용 전체에 적용되는 그룹 투명도입니다

opacity는 요소의 배경만 투명하게 만드는 속성이 아닙니다. 요소와 그 내용이 하나로 그려진 뒤 전체에 적용되는 투명도입니다. 값이 1보다 작으면 스태킹 컨텍스트를 만듭니다.

.dialog {
  opacity: 0;
  transition: opacity 180ms ease;
}

.dialog.open {
  opacity: 1;
}

이런 페이드 전환은 합성 단계에서 효율적으로 처리될 가능성이 있습니다. 그러나 opacity: 0은 display: none과 다릅니다. 박스는 레이아웃에 남고, 투명하다는 사실만으로 적중 검사에서 제외되지 않습니다. 보이지 않는 버튼이 클릭되거나 키보드 초점을 받을 수 있는지 UI 상태와 접근성 속성을 함께 설계해야 합니다.

배경만 반투명하게 하고 글자는 선명하게 유지하려면 요소 전체의 opacity보다 알파 채널이 있는 배경색을 사용하는 편이 의미에 맞습니다. opacity를 부모에 주고 자식에서 다시 1로 올린다고 부모의 그룹 투명도를 취소할 수 있는 것도 아닙니다.

한 프레임에 주어진 시간은 얼마일까요

부드러운 애니메이션을 설명할 때 ‘브라우저는 반드시 초당 60프레임을 그린다’고 말하기 쉽습니다. 하지만 디스플레이 주사율은 60 Hz, 90 Hz, 120 Hz 등 다양하고, 절전 상태나 백그라운드 탭, 브라우저 스케줄링과 장치 부하에 따라 실제 프레임 제공 조건도 달라집니다.

60 Hz 환경에서는 한 주기당 약 16.7 ms이지만 그 시간을 JavaScript가 전부 사용할 수 있는 것은 아닙니다. 120 Hz에서는 주기가 약 8.3 ms입니다. 고정 숫자를 품질 보증처럼 제시하기보다 대상 장치에서 긴 작업과 놓친 프레임을 측정해야 합니다.

JavaScript 애니메이션은 보통 requestAnimationFrame()을 이용해 브라우저가 다음 프레임을 준비하는 시점에 갱신합니다. 이것도 특정 프레임률을 보장하는 함수는 아닙니다. 콜백 안의 작업이 너무 길거나 메인 스레드가 다른 작업으로 막히면 프레임을 놓칠 수 있습니다.

function update(time) {
  // time을 기준으로 상태를 계산합니다.
  panel.style.transform = `translateX(${position(time)}px)`;
  requestAnimationFrame(update);
}

requestAnimationFrame(update);

전달된 시간 정보를 기준으로 위치를 계산하면 프레임 간격이 달라져도 전체 속도를 유지하기 쉽습니다. CSS 전환 같은 선언적 애니메이션도 고려합니다.

will-change는 명령이 아니라 제한적으로 쓰는 힌트입니다

will-change: transform을 붙이면 GPU 가속이 강제로 켜진다고 알려진 경우가 있습니다. 명세상 will-change는 앞으로 어떤 속성이 바뀔지 사용자 에이전트에 미리 알리는 렌더링 힌트입니다. 브라우저마다 다르게 사용할 수 있고, 같은 브라우저도 자원 상황에 따라 다른 최적화를 선택할 수 있습니다.

.drawer.preparing {
  will-change: transform;
}

필요한 상호작용에서 잠시 적용하고 끝난 뒤 제거할 수 있습니다. 반면 모든 요소에 적용하면 메모리와 렌더링 자원을 낭비할 수 있습니다.

/* 사용하지 말아야 할 전역 처방 */
* {
  will-change: transform, opacity;
}

어느 단계가 비싼지 측정합니다

Chrome 개발자 도구를 예로 들면 다음 도구를 함께 사용할 수 있습니다.

1. Performance 패널에서 페이지 로드나 애니메이션을 기록합니다.

2. Main 트랙에서 스타일 계산, Layout, Paint와 긴 JavaScript 작업을 찾습니다.

3. Frames 영역에서 오래 걸리거나 놓친 프레임이 특정 상호작용과 겹치는지 봅니다.

4. Rendering 패널의 Paint flashing을 켜서 갱신 때 다시 칠해지는 영역을 관찰합니다.

5. Layer borders나 Layers 패널로 합성 레이어의 수, 크기와 생성 이유를 살펴봅니다.

같은 패널 이동을 left와 transform으로 각각 구현해 같은 기기·창 크기·캐시 상태에서 비교해 봅시다. Layout과 Paint 시간, 프레임 간격, 레이어 메모리를 함께 봅니다. 첫 실행에는 준비 비용이 포함될 수 있으므로 첫 상호작용과 반복 상호작용도 나눠 기록합니다.

최적화의 목표는 단계를 없애는 것이 아니라 필요한 일만 하는 것입니다

렌더링 성능을 좋게 만드는 일반적인 순서는 다음과 같습니다.

1. 사용자에게 중요한 장면을 정합니다. 첫 화면, 메뉴 열기, 스크롤, 입력 반응처럼 구체적으로 적습니다.

2. 네트워크 지연, 긴 JavaScript, 레이아웃, 페인트, 합성 중 실제 병목을 측정합니다.

3. 레이아웃 의미를 보존하면서 불필요한 DOM 변경과 읽기·쓰기 교차를 줄입니다.

4. 이동과 페이드에는 의도에 맞을 때 transform과 opacity를 고려합니다.

5. 큰 그림자·필터·고해상도 표면과 과도한 레이어의 페인트·메모리 비용을 확인합니다.

6. 변경 뒤 같은 조건에서 다시 측정하고 시각 품질과 접근성을 함께 검사합니다.

‘레이아웃을 없애자’는 목표는 현실적이지 않습니다. 새 콘텐츠가 들어오고 화면 크기가 바뀌면 올바른 위치를 다시 계산해야 합니다. ‘페인트를 절대로 하지 말자’도 불가능합니다. 처음 나타나는 콘텐츠는 그려야 하고 내용이 바뀌면 새 결과가 필요합니다. 좋은 최적화는 사용자가 원하는 변화에 꼭 필요한 작업만 수행하도록 구조를 정리하는 것입니다.

브라우저는 레이아웃 결과를 바탕으로 그리기 명령을 만들고, 이를 래스터화해 픽셀 결과를 준비하며, 필요한 단위를 합성해 최종 프레임을 만듭니다. 페인트 순서의 스태킹 컨텍스트와 구현상의 합성 레이어는 서로 다르고, 모든 요소가 독립 레이어를 갖지 않습니다. transform과 opacity는 합성만으로 갱신될 가능성을 높일 수 있지만 GPU 사용이나 페인트 생략을 보장하지 않습니다. will-change 역시 강제 명령이 아니라 자원 비용을 가진 힌트입니다.

7장부터 이 장까지 우리는 HTML 바이트가 DOM이 되고, CSS 규칙이 박스와 위치로 계산되며, 그 결과가 픽셀과 프레임으로 이어지는 과정을 살펴봤습니다. 다음 장에서는 브라우저와 서버가 요청을 한 번씩 주고받는 HTTP의 비상태성 위에서 어떻게 로그인 상태를 이어 가는지 살펴보겠습니다.

도해 9. 페인트·래스터·합성

도해 9. 페인트·래스터·합성

도해 9. 페인트·래스터·합성

페인트는 그리기 항목을 만들고 래스터는 이를 픽셀로 바꾸며 합성은 준비된 결과를 프레임으로 결합합니다. 모든 요소가 레이어를 갖는 것은 아니고, transform·opacity의 합성 전용 처리와 GPU 사용은 브라우저가 조건에 따라 선택하므로 개발자 도구로 검증해야 합니다.

이 장의 근거 문서

  • CSS Positioned Layout — 위치 지정과 스태킹 컨텍스트
  • CSS Display·CSS Box Model — 그리기 대상이 되는 박스의 생성 규칙
  • WHATWG HTML Standard — 렌더링 기회와 프레임 갱신 시점

이 장에서 함께 다루는 질문

페인트는 픽셀을 칠하는 단계인가요?

곧바로 모든 픽셀을 칠한다는 뜻만은 아닙니다. 페인트 단계에서는 무엇을 어떤 순서와 모양으로 그릴지 기록합니다. 그 그리기 명령을 실제 픽셀로 바꾸는 과정은 래스터화로 따로 나뉩니다.

배경색만 바꾸면 레이아웃도 다시 하나요?

기하 정보가 그대로라면 새 레이아웃이 필요하지 않을 가능성이 큽니다. 다만 그리기 결과는 달라지므로 페인트와 이후 작업이 필요할 수 있습니다. 반대로 너비를 바꾸면 스타일 계산과 레이아웃부터 다시 필요할 가능성이 큽니다.

렌더링 성능 표를 그대로 믿어도 되나요?

진단의 출발점이지 구현 계약은 아닙니다. 속성 하나가 전체 상황을 결정하지 않습니다. 의존하는 사용자 지정 속성과 애니메이션 방식, 포함 관계, 브라우저 최적화와 현재 레이어 구성이 함께 영향을 줍니다.

합성은 무조건 GPU 가 하나요?

그런 등식은 아닙니다. 현대 브라우저가 합성 작업에 GPU 를 활용할 수 있지만 장치와 드라이버, 브라우저 설정, 콘텐츠와 자원 상태에 따라 경로가 달라집니다. 레이어를 많이 유지하면 메모리와 전송 비용도 늘 수 있습니다.

EPUB으로 소장하기

전체 내용과 부록을 EPUB으로 읽고 소장할 수 있습니다.

9,900원

이 장이 실린 책

웹은 어떻게 동작하는가

이 책의 목차 보기

같은 분야의 다른 책

이 글 공유하기

X 스레드 네이버 카카오톡

최종 수정일 2026년 9월 3일

이 콘텐츠는 저자가 기획하고 AI 도구를 집필·정리 과정에 활용했습니다. 구성, 사실 확인, 표현, 최종 판단과 출판 책임은 저자와 보이드로그에 있습니다.