고성능 CSS 애니메이션을 만드는 방법

이 가이드에서는 고성능 CSS 애니메이션을 만드는 방법을 설명합니다.

이러한 권장사항의 이론을 알아보려면 일부 애니메이션 속도가 느린 이유를 참고하세요.

브라우저 호환성

이 가이드에서 권장하는 모든 CSS 속성은 브라우저 간 원활한 지원을 제공합니다.

요소 이동

요소를 이동하려면 transform 속성의 translate 또는 rotation 키워드 값을 사용합니다.

예를 들어 항목을 뷰로 슬라이드하려면 translate를 사용합니다.

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

예를 들어 360도 미만의 항목을 회전할 수도 있습니다.

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

요소 크기 조절

요소의 크기를 조절하려면 transform 속성의 scale 키워드 값을 사용합니다.

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

요소의 공개 상태 변경

요소를 표시하거나 숨기려면 opacity을 사용합니다.

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

레이아웃 또는 페인트를 트리거하는 속성 피하기

애니메이션에 CSS 속성 (transformopacity 제외)을 사용하기 전에 속성이 렌더링 파이프라인에 미치는 영향을 확인합니다. 꼭 필요한 경우가 아니라면 레이아웃 또는 페인트를 트리거하는 속성은 사용하지 않습니다.

레이어 생성 강제

일부 애니메이션이 느린 이유는 무엇인가요?에 설명된 대로 요소를 새 레이어에 배치하면 레이아웃의 나머지 부분을 다시 그릴 필요 없이 요소를 다시 그릴 수 있습니다.

브라우저는 보통 새 레이어에 어떤 항목을 배치할지 신중하게 결정하지만 will-change 속성을 사용하여 수동으로 레이어를 강제로 생성할 수 있습니다. 이름에서 알 수 있듯이 이 속성은 이 요소가 어떤 식으로든 변경될 것임을 브라우저에 알립니다.

CSS에서 이 속성은 모든 선택기에 적용할 수 있습니다.

body > .sidebar {
  will-change: transform;
}

그러나 사양에 따르면 이 접근 방식은 항상 변경될 예정인 요소에만 사용해야 합니다. 위의 예가 사용자가 슬라이드 인/아웃할 수 있는 사이드바였다면 그럴 수 있습니다. 페이지의 일부 항목은 자주 변경되지 않을 수 있으므로 변경될 가능성이 있는 시점에 JavaScript를 사용하여 will-change를 적용하는 것이 좋습니다. 브라우저가 필요한 최적화를 실행할 수 있도록 충분한 시간을 제공하고 변경이 중지되면 속성을 삭제해야 합니다.

will-change을 지원하지 않는 드문 브라우저 (현재 대부분의 경우 Internet Explorer)에서 레이어 생성을 강제하는 방법이 필요하다면 transform: translateZ(0)를 설정하면 됩니다.

느리거나 버벅거리는 애니메이션 디버그

Chrome DevTools 및 Firefox DevTools에는 애니메이션이 느리거나 버벅거리는 이유를 파악하는 데 도움이 되는 도구가 많이 있습니다.

애니메이션이 레이아웃을 트리거하는지 확인

transform 이외의 항목을 사용하여 요소를 이동하는 애니메이션은 속도가 느릴 수 있습니다. 다음 예에서는 topleft를 애니메이션 처리하고 transform를 사용하여 동일한 시각적 결과를 얻었습니다.

금지사항
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
의견을 제시하지
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

다음 두 가지 Glitch 예시에서 이를 테스트하고 DevTools를 사용하여 성능을 살펴볼 수 있습니다.

Chrome DevTools

  1. 성능 패널을 엽니다.
  2. 애니메이션이 실행되는 동안 런타임 성능을 기록합니다.
  3. 요약 탭을 살펴봅니다.

요약 탭에 0이 아닌 렌더링 값이 표시되면 애니메이션으로 인해 브라우저에서 레이아웃 작업이 이루어진 것일 수 있습니다.

Summary 패널에는 렌더링 37ms와 페인팅 79ms가 표시됩니다.
animation-with-top-left 예시에서는 렌더링 작업이 발생합니다.
Summary(요약) 패널에 렌더링 및 페인팅 값이 0으로 표시됩니다.
animation-with-transform 예는 렌더링 작업을 일으키지 않습니다.

Firefox DevTools

Firefox DevTools의 Waterfall(폭포식 구조)를 통해 브라우저가 시간을 보내는 위치를 파악할 수 있습니다.

  1. 성능 패널을 엽니다.
  2. 패널에서 애니메이션이 진행되는 동안 녹화 시작을 선택합니다.
  3. 기록을 중지하고 Waterfall(폭포식 구조) 탭을 검사합니다.

Recalculate Style 항목이 표시되면 브라우저가 폭포식 구조 렌더링이 시작될 때 시작해야 합니다.

애니메이션이 프레임을 떨어뜨리는지 확인

  1. Chrome DevTools의 렌더링을 엽니다.
  2. FPS 미터 체크박스를 사용 설정합니다.
  3. 애니메이션이 실행될 때 값을 확인합니다.

FPS 측정기 UI 상단에 프레임 라벨이 표시됩니다. 아래에는 50% 1 (938 m) dropped of 1878의 선을 따라 값이 표시됩니다. 고성능 애니메이션은 비율이 높습니다(예: 99%). 비율이 높으면 드롭된 프레임이 적고 애니메이션이 부드럽게 보인다는 의미입니다.

fps 측정기에 프레임의 50% 가 드롭된 것으로 표시됨
animation-with-top-left 예시에서는 프레임의 50% 가 드롭됩니다.
fps 측정기에 프레임의 1% 만 드롭된 것으로 표시됨
animation-with-transform 예에서는 프레임의 1% 만 드롭합니다.

애니메이션이 페인트를 트리거하는지 확인

페인팅은 다른 작업에 비해 비용이 많이 듭니다. 예를 들어 그림자와 같이 블러가 포함된 요소는 빨간색 상자를 그리는 것보다 그리는 데 시간이 더 오래 걸립니다. 그러나 CSS 관점에서는 이것이 항상 명확하지는 않습니다. background: red;box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5);는 성능 특성이 크게 다른 것처럼 보이지는 않지만 그렇습니다.

브라우저 DevTools를 사용하면 다시 그려야 할 영역과 페인트와 관련된 성능 문제를 식별할 수 있습니다.

Chrome DevTools

  1. Chrome DevTools의 렌더링을 엽니다.
  2. Paint Flashing을 선택합니다.
  3. 화면에서 포인터를 이동합니다.
다시 페인트된다는 것을 보여주기 위해 녹색으로 강조표시된 UI 요소
이 Google 지도의 예에서는 다시 페인트될 요소를 확인할 수 있습니다.

전체 화면이 깜박이거나 변경되지 않아야 한다고 생각되는 영역이 강조 표시되면 몇 가지 조사를 해볼 수 있습니다.

특정 속성이 페인팅으로 인해 성능 문제를 일으키는지 확인해야 하는 경우 Chrome DevTools의 페인트 프로파일러가 도움이 될 수 있습니다.

Firefox DevTools

  1. 설정을 열고 페인트 플래싱 전환을 위한 도구 상자 버튼을 추가합니다.
  2. 검사할 페이지에서 버튼을 사용으로 전환하고 마우스를 움직이거나 스크롤하여 강조표시된 영역을 확인합니다.

결론

가능한 경우 애니메이션을 렌더링 경로의 합성 단계에서 유지하려면 애니메이션을 opacitytransform로 제한합니다. DevTools를 사용하여 경로의 어느 단계가 애니메이션의 영향을 받는지 확인하세요.

페인트 프로파일러를 사용하여 특히 비용이 많이 드는 페인트 작업이 있는지 확인합니다. 발견한 경우 다른 CSS 속성이 더 나은 성능으로 동일한 디자인과 분위기를 제공하는지 확인하세요.

will-change 속성은 성능 문제가 발생하는 경우에만 드물게 사용합니다.