애니메이션 측정, 애니메이션 프레임 고려 방법, 전반적인 페이지 부드러움에 대해 알아봅니다.
스크롤이나 애니메이션 중에 페이지가 '끊기거나' '멈추는' 경험을 해보셨을 것입니다. 이러한 경험은 원활하지 않다고 말할 수 있습니다. 이러한 유형의 문제를 해결하기 위해 Chrome팀은 애니메이션 감지를 위한 실험실 도구에 더 많은 지원을 추가하고 Chromium 내에서 렌더링 파이프라인 진단을 꾸준히 개선하고 있습니다.
최근 진행 상황을 공유하고, 구체적인 도구 안내를 제공하며, 향후 애니메이션 부드러움 측정항목에 관한 아이디어를 논의하고자 합니다. 언제든지 의견을 들려주세요.
이 게시물에서는 다음 세 가지 주요 주제를 다룹니다.
- 애니메이션과 애니메이션 프레임을 빠르게 살펴봅니다.
- 전반적인 애니메이션 부드러움을 측정하는 방법에 관한 현재 생각
- 오늘 실습 도구에서 활용할 수 있는 몇 가지 실용적인 제안사항
애니메이션이란 무엇인가요?
애니메이션으로 콘텐츠에 생기를 불어넣으세요. 특히 사용자 상호작용에 대한 응답으로 콘텐츠를 이동하면 애니메이션을 통해 경험이 더 자연스럽고 이해하기 쉽고 재미있게 느껴질 수 있습니다.
하지만 애니메이션을 잘못 구현하거나 애니메이션을 너무 많이 추가하면 경험이 저하되고 재미가 없어질 수 있습니다. '유용한' 전환 효과를 너무 많이 추가한 인터페이스와 상호작용한 적이 있을 것입니다. 이러한 효과는 성능이 좋지 않으면 실제로 경험에 적대적이 됩니다. 따라서 일부 사용자는 실제로 동작 줄이기를 선호할 수 있으며, 이는 존중해야 하는 사용자 환경설정입니다.
애니메이션은 어떻게 작동하나요?
간단히 요약하면 렌더링 파이프라인은 다음과 같은 몇 가지 순차적 단계로 구성됩니다.
- 스타일: 요소에 적용되는 스타일을 계산합니다.
- 레이아웃: 각 요소의 지오메트리와 위치를 생성합니다.
- 페인트: 각 요소의 픽셀을 레이어로 채웁니다.
- 컴포지션: 레이어를 화면에 그립니다.
애니메이션을 정의하는 방법은 다양하지만 기본적으로 다음 중 하나를 통해 작동합니다.
- 레이아웃 속성을 조정합니다.
- 페인트 속성을 조정합니다.
- 컴포지트 속성을 조정합니다.
이러한 단계는 순차적이므로 파이프라인에서 더 아래에 있는 속성 측면에서 애니메이션을 정의하는 것이 중요합니다. 프로세스에서 업데이트가 일찍 발생할수록 비용이 많이 들고 원활하게 진행될 가능성이 낮습니다. 자세한 내용은 렌더링 성능을 참고하세요.
레이아웃 속성을 애니메이션으로 처리하면 편리할 수 있지만, 비용이 발생합니다. 이 비용은 즉시 명확하게 드러나지 않을 수도 있습니다. 애니메이션은 가능한 경우 복합 속성 변경사항 측면에서 정의해야 합니다.
선언적 CSS 애니메이션을 정의하거나 Web Animations를 사용하고 컴포지트 속성에 애니메이션을 적용하면 부드럽고 효율적인 애니메이션을 만드는 데 도움이 됩니다. 하지만 효율적인 웹 애니메이션에도 성능 제한이 있으므로 이것만으로는 부드러움을 보장할 수 없습니다. 따라서 항상 측정하는 것이 중요합니다.
애니메이션 프레임이란 무엇인가요?
페이지의 시각적 표현이 업데이트되어 표시되는 데 시간이 걸립니다. 시각적 변경사항은 새로운 애니메이션 프레임으로 이어지며, 이 프레임은 결국 사용자의 디스플레이에 렌더링됩니다.
일정 간격으로 업데이트를 표시하므로 시각적 업데이트가 일괄 처리됩니다. 많은 디스플레이가 초당 60회 (즉, 60Hz)와 같은 고정된 시간 간격으로 업데이트됩니다. 최신 디스플레이는 더 높은 화면 재생 빈도(90~120Hz가 일반적임)를 제공할 수 있습니다. 이러한 디스플레이는 필요에 따라 새로고침 빈도 간에 적극적으로 적응하거나 완전히 가변적인 프레임 속도를 제공할 수 있습니다.
게임이나 브라우저와 같은 모든 애플리케이션의 목표는 이러한 일괄 시각적 업데이트를 모두 처리하고 매번 기한 내에 시각적으로 완전한 애니메이션 프레임을 생성하는 것입니다. 이 목표는 네트워크에서 콘텐츠를 빠르게 로드하거나 JavaScript 작업을 효율적으로 실행하는 등 다른 중요한 브라우저 작업과는 완전히 다릅니다.
어느 시점에는 디스플레이에서 할당한 기한 내에 모든 시각적 업데이트를 완료하기가 너무 어려워질 수 있습니다. 이 경우 브라우저에서 프레임을 삭제합니다. 화면이 검은색으로 변하지 않고 반복됩니다. 이전 프레임 기회에 표시된 것과 동일한 애니메이션 프레임이 조금 더 오래 표시됩니다.
이런 일은 실제로 자주 발생합니다. 특히 웹 플랫폼에서 흔히 볼 수 있는 정적 콘텐츠나 문서와 같은 콘텐츠의 경우 인식되지 않을 수도 있습니다. 프레임 누락은 부드러운 움직임을 표시하기 위해 안정적인 애니메이션 업데이트 스트림이 필요한 애니메이션과 같은 중요한 시각적 업데이트가 있을 때만 명확해집니다.
애니메이션 프레임에 영향을 미치는 요소는 무엇인가요?
웹 개발자는 브라우저가 시각적 업데이트를 빠르고 효율적으로 렌더링하고 표시하는 기능에 큰 영향을 미칠 수 있습니다.
예를 들면 다음과 같습니다.
- 타겟 기기에서 빠르게 디코딩하기에는 너무 크거나 리소스 집약적인 콘텐츠를 사용합니다.
- 너무 많은 레이어 사용으로 인해 너무 많은 GPU 메모리가 필요합니다.
- 지나치게 복잡한 CSS 스타일 또는 웹 애니메이션을 정의합니다.
- 빠른 렌더링 최적화를 사용 중지하는 디자인 안티 패턴을 사용합니다.
- 기본 스레드에서 너무 많은 JS 작업이 실행되어 시각적 업데이트를 차단하는 긴 작업이 발생합니다.
하지만 애니메이션 프레임이 기한을 놓쳐 프레임이 삭제되었는지 어떻게 알 수 있을까요?
한 가지 가능한 방법은 requestAnimationFrame() 폴링을 사용하는 것이지만 몇 가지 단점이 있습니다. requestAnimationFrame() 또는 'rAF'는 브라우저에 애니메이션을 실행하고 싶다고 알리고 렌더링 파이프라인의 다음 페인트 단계 전에 애니메이션을 실행할 기회를 요청합니다. 콜백 함수가 예상한 시간에 호출되지 않으면 페인트가 실행되지 않았고 하나 이상의 프레임이 건너뛰었다는 의미입니다. rAF가 호출되는 빈도를 폴링하고 계산하면 일종의 '초당 프레임 수'(FPS) 측정항목을 계산할 수 있습니다.
let frameTimes