노트

합성 단계와 transform·opacity

Compositing

프런트엔드#browser#performance · 연결된 개념 8개

쉽게 말하면

합성은 투명 필름 여러 장에 따로 그린 그림을 겹쳐 한 화면을 만드는 마지막 단계예요. transform과 opacity는 그림을 다시 그리지 않고 필름만 밀거나 흐리게 하니 애니메이션이 부드러워요.

비유가 깨지는 곳 필름이 공짜는 아니에요. 자기 레이어로 올라간 요소는 GPU 메모리를 쓰고, will-change를 남발해 레이어가 많아지면 오히려 느려져요. 필름 위 내용이 바뀌면 그 레이어는 다시 칠해야 하고요.

페인트까지 끝난 레이어들을 순서대로 겹쳐 최종 화면을 만드는 렌더링 파이프라인의 마지막 단계. transform과 opacity는 (요소가 자기 레이어에 있으면) 이 단계만으로 처리할 수 있어서 리플로우와 리페인트를 모두 건너뛴다.

translate가 리플로우를 일으키지 않는 이유

  • left: 100px은 요소의 실제 위치를 바꾼다. 다른 요소의 배치에 영향을 줄 수 있으니 레이아웃을 다시 계산해야 한다
  • transform: translateX(100px)은 레이아웃에서 정해진 박스는 그대로 두고, 그려진 결과만 옮겨서 보여 준다. 레이아웃을 미루는 것이 아니라 아예 레이아웃 대상이 아니다
  • 그래서 애니메이션은 top·left·width 대신 transform과 opacity로 만드는 것이 기본이다
/* 나쁨: 프레임마다 레이아웃 */
.box { transition: left .3s; }
/* 좋음: 합성만 */
.box { transition: transform .3s; }

공짜는 아니다

  • 요소가 자기 레이어로 올라가면 GPU(Graphics Processing Unit) 메모리를 쓴다. will-change를 남발하거나 레이어가 많아지면 오히려 느려진다
  • 레이어 안의 내용이 바뀌면 그 레이어는 다시 칠해야 한다
  • 같은 원리로 레이아웃 스래싱을 피할 때도, 무한 스크롤처럼 움직임이 많은 UI에서도 transform을 먼저 떠올린다

출처: web.dev — Stick to compositor-only properties

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • Tailwind CSS

    flex, px-4, text-sm처럼 속성 하나를 담은 유틸리티 클래스(Utility Class)를 마크업에 조합해 스타일을 입히는 CSS 프레임워크. 빌드할 때 소스를 훑어 실제로 쓰인 클래스의 CSS만 만들어 내는 빌드 도구이고, 런타임에 돌아가는 JS(JavaScript)는 없다.

  • content-visibility

    화면 밖에 있는 요소의 렌더링을 건너뛰어도 된다고 브라우저에 알려 주는 CSS 속성. auto를 주면 뷰포트에서 멀리 있는 요소의 레이아웃·페인트를 생략하므로, 긴 페이지의 첫 렌더링과 스크롤이 빨라진다.

  • 상태 내리기와 컴포지션으로 리렌더 줄이기

    상태 내리기(State Colocation)는 state를 실제로 쓰는 컴포넌트 가까이로 옮겨, state가 바뀔 때 다시 렌더되는 범위를 좁히는 기법이다. 메모이제이션(Memoization)보다 먼저 시도할 구조적 최적화다.

  • Activity와 숨겨진 라우트 보존

    Activity는 React 19.2의 컴포넌트로, UI를 언마운트하지 않고 display: none으로 숨기면서 state와 DOM(Document Object Model)을 보존한다. 숨기는 동안 Effect는 정리(cleanup)된다. 예전 이름은 Offscreen이다.

  • requestAnimationFrame

    "다음 화면을 그리기 직전에 이 함수를 실행해 달라"고 브라우저에 예약하는 API. 콜백은 태스크 큐도 마이크로태스크 큐도 아닌 별도 목록에 들어가고, 이벤트 루프의 렌더링 단계에서 페인트 직전에 한꺼번에 실행된다.

보기 옵션