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

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

웹에서 애니메이션을 만들 때 타겟 프레임 속도는 60FPS로 널리 알려져 있습니다. 이 프레임 속도를 사용하면 애니메이션이 부드럽게 보입니다. 웹에서 프레임은 화면을 업데이트하고 다시 칠하는 데 필요한 모든 작업을 실행하는 데 걸리는 시간입니다. 각 프레임이 16.7밀리초 (1,000밀리초 / 60 ≈ 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 실행과 관련된 모든 작업을 압도할 수 있으므로 이 질문은 무의미합니다.