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

최신 브라우저는 transformopacity의 두 가지 CSS 속성을 저렴하게 애니메이션할 수 있습니다. 다른 요소를 애니메이션으로 처리하면 부드러운 60FPS를 달성하지 못할 가능성이 높습니다. 이 게시물에서는 그 이유를 설명합니다.

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

웹에서 항목을 애니메이션으로 만들 때 60FPS의 프레임 속도가 타겟이라는 것은 널리 알려져 있습니다. 이 프레임 속도를 사용하면 애니메이션이 매끄럽게 표시됩니다. 웹에서 프레임은 화면을 업데이트하고 다시 그리는 데 필요한 모든 작업을 수행하는 데 걸리는 시간입니다. 각 프레임이 16.7ms (1000ms / 60 ≈ 16.7) 내에 완료되지 않으면 사용자는 지연을 인식합니다.

렌더링 파이프라인

웹페이지에 항목을 표시하려면 브라우저가 다음 순차적 단계를 거쳐야 합니다.

  1. 스타일: 요소에 적용되는 스타일을 계산합니다.
  2. 레이아웃: 각 요소의 지오메트리와 위치를 생성합니다.
  3. 페인트: 각 요소의 픽셀을 채웁니다.
  4. 컴포지션: 요소를 레이어로 분리하고 레이어를 화면에 그립니다.

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

이미 로드된 페이지에서 항목을 애니메이션으로 처리하는 경우 이러한 단계를 다시 실행해야 합니다. 이 프로세스는 애니메이션이 발생하도록 변경해야 하는 단계에서 시작됩니다.

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

레이아웃 속성에 애니메이션 적용

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

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

페인트 속성 애니메이션

페인트는 요소를 화면에 페인트해야 하는 순서를 결정하는 프로세스입니다. 파이프라인의 모든 작업 중에서 가장 오래 실행되는 경우가 많습니다.

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

복합 속성 애니메이션

컴포지팅은 페이지를 레이어로 분리하고, 페이지의 모양에 관한 정보를 픽셀로 변환 (래스터화)하고, 레이어를 함께 배치하여 페이지를 만드는 프로세스입니다 (컴포지팅).

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

레이어란 무엇인가요?

애니메이션이나 전환이 적용될 요소를 새 레이어에 배치하면 브라우저에서 해당 요소만 다시 페인트하면 되고 다른 요소는 다시 페인트하지 않아도 됩니다. 함께 이동할 수 있는 여러 요소가 포함된 Photoshop의 레이어 개념을 잘 알고 계실 수도 있습니다. 브라우저 렌더링 레이어도 이와 유사합니다.

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

CSS와 JavaScript 성능 비교

애니메이션에 CSS를 사용하는 것이 성능 측면에서 더 나은지 아니면 JavaScript를 사용하는 것이 더 나은지 궁금할 수 있습니다.

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

이 도움말에 설명된 대로 변환 및 불투명도에 대한 다른 변경사항도 대부분 컴포지터 스레드에서 처리할 수 있습니다.

애니메이션으로 인해 페인트, 레이아웃 또는 둘 다 트리거되는 경우 기본 스레드에서 작업을 실행해야 합니다. 이는 CSS 및 JavaScript 애니메이션 모두에 해당하며 레이아웃 또는 페인트의 오버헤드가 CSS 또는 JavaScript 실행과 관련된 작업을 압도할 가능성이 높으므로 질문이 무의미해집니다.