일부 애니메이션이 느린 이유는 무엇인가요?

최신 브라우저는 transformopacity라는 두 가지 CSS 속성에 저렴하게 애니메이션을 적용할 수 있습니다. 다른 항목에 애니메이션을 적용하면 매끄러운 60FPS (초당 프레임 수)를 달성하지 못할 가능성이 높습니다. 이 게시물에서는 그 이유를 설명합니다.

애니메이션 성능 및 프레임 속도

웹에서 애니메이션을 만들 때는 60FPS의 프레임 속도가 목표인 것으로 널리 알려져 있습니다. 이 프레임 속도는 애니메이션을 부드럽게 보여줍니다. 웹에서 프레임은 화면을 업데이트하고 다시 칠하는 데 필요한 모든 작업을 실행하는 데 걸리는 시간입니다. 각 프레임이 16.7ms (1000ms / 60 avg 16.7) 내에 완료되지 않으면 사용자는 지연을 인지하게 됩니다.

렌더링 파이프라인

웹페이지에 무언가를 표시하려면 브라우저에서 다음과 같은 순차적 단계를 거쳐야 합니다.

  1. 스타일: 요소에 적용되는 스타일을 계산합니다.
  2. 레이아웃: 각 요소의 도형과 위치를 생성합니다.
  3. 페인트: 각 요소의 픽셀을 레이어로 채웁니다.
  4. 합성: 화면에 레이어를 그립니다.

이 네 단계를 브라우저의 렌더링 파이프라인이라고 합니다.

이미 로드된 페이지에서 애니메이션을 적용하려면 이러한 단계를 다시 실행해야 합니다. 이 프로세스는 애니메이션이 실행되도록 변경해야 하는 단계에서 시작됩니다.

앞서 언급했듯이 이러한 단계는 순차적으로 진행됩니다. 예를 들어 레이아웃을 변경하는 애니메이션을 사용하면 페인트 및 합성 단계도 다시 실행해야 합니다. 따라서 레이아웃을 변경하는 항목을 애니메이션하는 것은 컴포지션만 변경하는 항목을 애니메이션하는 것보다 비용이 더 많이 듭니다.

레이아웃 속성 애니메이션

레이아웃 변경에는 변경사항의 영향을 받는 모든 요소의 도형 (위치 및 크기)을 계산하는 작업이 포함됩니다. 한 요소를 변경하면 다른 요소의 도형을 다시 계산해야 할 수 있습니다. 예를 들어 <html> 요소의 너비를 변경하면 그 하위 요소가 영향을 받을 수 있습니다. 요소가 오버플로되고 서로 영향을 주는 방식으로 인해 트리 아래쪽에서 변경하면 레이아웃 계산이 맨 위까지 다시 이루어질 수 있습니다.

표시되는 요소의 트리가 클수록 레이아웃 계산을 실행하는 데 더 오래 걸립니다.

페인트 속성 애니메이션

페인트는 요소를 화면에 그릴 순서를 결정하는 프로세스입니다. 대체로 파이프라인의 모든 작업 중 가장 오래 실행되는 과정입니다.

최신 브라우저의 대부분의 페인팅은 소프트웨어 래스터라이저에서 실행됩니다. 앱의 요소가 레이어로 그룹화되는 방식에 따라 변경된 요소 외의 다른 요소도 페인트해야 할 수 있습니다.

복합 속성 애니메이션

합성은 페이지를 레이어로 분리하고 페이지가 어떻게 표시되어야 하는지에 관한 정보를 픽셀로 변환 (래스터화)한 다음 레이어를 결합하여 페이지를 만드는 프로세스입니다 (합성).

이것이 opacity 속성이 애니메이션 처리가 저렴한 항목 목록에 포함되는 이유입니다. 이 속성이 자체 레이어에 있는 한 컴포지션 단계에서 GPU가 변경사항을 처리할 수 있습니다. Chromium 기반 브라우저와 WebKit은 opacity에 CSS 전환이나 애니메이션이 있는 요소에 새 레이어를 만듭니다.

레이어란 무엇인가요?

애니메이션이 적용되거나 전환될 항목을 새 레이어에 배치하면 브라우저는 다른 모든 항목이 아닌 해당 항목만 다시 칠하면 됩니다. 함께 이동할 수 있는 여러 요소가 포함된 Photoshop의 레이어 개념에 익숙할 수 있습니다. 브라우저 렌더링 영역은 이 아이디어와 유사합니다.

브라우저는 새 레이어에 어떤 요소가 있어야 하는지를 잘 결정하지만, 요소가 누락되면 레이어를 강제로 만들 수 있습니다. 고성능 애니메이션을 만드는 방법에서 자세히 알아보세요. 하지만 각 레이어는 메모리를 사용하므로 새 레이어를 만들 때는 주의해야 합니다. 메모리가 제한된 기기에서 새 레이어를 생성하면 해결하려는 문제보다 더 많은 성능 문제가 발생할 수 있습니다. 또한 각 레이어의 텍스처는 GPU로 업로드되어야 합니다. 따라서 CPU와 GPU 간의 대역폭 제약이 발생할 수 있습니다.

CSS와 JavaScript의 성능 비교

애니메이션에 CSS를 사용하는 것이 성능 측면에서 더 나은가요?

CSS 기반 애니메이션과 웹 애니메이션 (API를 지원하는 브라우저의 경우)은 일반적으로 컴포지터 스레드라고 하는 스레드에서 처리됩니다. 이는 스타일 지정, 레이아웃, 페인트, JavaScript가 실행되는 브라우저의 기본 스레드와는 다릅니다. 즉, 브라우저가 메인 스레드에서 비용이 많이 드는 작업을 실행 중인 경우, 이러한 애니메이션은 중단되지 않고 계속 실행될 수 있습니다.

이 도움말에서 설명한 대로 변형 및 불투명도의 다른 변경사항도 많은 경우에 컴포지터 스레드에 의해 처리될 수 있습니다.

애니메이션이 페인트, 레이아웃 또는 둘 다를 트리거하는 경우 작업을 수행하기 위해 기본 스레드가 필요합니다. 이는 CSS 및 JavaScript 애니메이션에 모두 적용되며, 레이아웃 또는 페인트의 오버헤드는 CSS 또는 JavaScript 실행과 연관된 모든 작업에 악영향을 미치고, 해결 불가능한 문제를 유발할 수 있습니다.