Animation

Reina·2024년 1월 9일
0
post-thumbnail

페이지 스크롤링과 함께 애니메이션을 구현한 사이트를 보면 렉이 많이 걸려서 개발자들이 원하는 애니메이션 효과를 제대로 경험하지 못하는 것 같다는 느낌을 종종 받았다.

역동적인 느낌을 나 역시 좋아하기 때문에 이런 사이트를 볼 때마다 안타까움도 있었고, 해결할 방법이 없는 걸까? 라는 생각만 갖고 있었는데 드디어 대해 알아보게 되었다.



애니메이션이란 무엇인가?

웹 페이지 내 요소들의 동작을 부드럽게 만들어주는 기능으로, 웹 페이지를 좀 더 생동감 있게 만들어준다. 애니메이션이 발생하는 CSS의 기능은 두 가지 정도 있는데, transformanimation이 있다. 유저의 특정 액션이 트리거가 되어 전환을 발생시키는 transform과 달리, animation은 유저의 특정 액션없이 자동으로 진행된다.

이러한 애니메이션은 유저의 행동에 의해 움직이거나 변하는 등 간단한 인터렉션을 할 수 있지만, 많거나 복잡한 애니메이션을 적용하면 웹 페이지의 성능을 떨어뜨릴 수 있다


성능은 왜 떨어지는 건데?

리플로우(reflow)와 리페인트(repaint)가 발생하기 때문이다.

리플로우와 리페인트를 설명하기에 앞서, 우선 웹 브라우저의 UI 렌더링 과정은 아래와 같다.

  1. Styles : 가장 먼저 객체에 적용할 스타일을 계산하거나 재계산한다.
  2. Layout : 요소의 레이아웃을 생성하고 위치를 설정한다.
      → width, height, top, bottom, left, right 등
  3. Paint : Layout 단계를 통해서 생성된 각각의 레이아웃에 픽셀을 채운다.
      → background, border, color 등
  4. Composite : 브라우저는 각각의 레이어 순서에 따라 화면에 객체를 그린다.
      → transform, opacity

리플로우(reflow) 란, 브라우저가 웹 페이지를 렌더링할 HTML 요소 노드의 추가 및 삭제, 요소의 크기 및 위치 변경, 윈도우 리사이징 등 레이아웃에 영향을 주는 변경이 발생했을 경우 레이아웃을 다시 계산하고 렌더링하는 과정이다. (Layout → Paint → Composite)

리페인트(repaint) 는 재결합된 렌더트리를 기반으로 다시 렌더링하는 과정이다. (Paint → Composite)

리플로우와 리페인트는 반드시 순차적으로 동시에 실행되진 않고, 레이아웃에 영향이 없는 변경은 리페인트만 실행된다. 이러한 리플로우, 리페인트 과정은 CPU의 자원을 많이 사용해 성능이 저하되므로 최적화를 위해 이 둘의 사용을 최소화 시켜야 한다.


리플로우가 발생하는 속성 (참고)
width, height, min-height / margin, padding / position / display, float / vertical-align / border, border-width / font-size, font-weight, font-family, text-align, line-height / overflow, overflow-y / top, bottom, left, right, clear / white-space / ...

리페인트가 발생하는 속성 (참고)
color border-style / visibility / background, background-image, background-position, background-repeat, background-size / outline, outline-color, outline-style, outline-width / border-radius / box-shadow / text-decoration / ...



이러한 애니메이션의 성능을 최적화하는 방법

✔️ 리플로우를 발생시키는 속성 대신 transform 사용하기
top, left 등의 속성을 통해 애니메이션 효과를 주는 경우와 transformtranslate를 통해 애니메이션 효과를 주는 경우로 나누어 비교할 수 있다.

top, left, bottom, right과 같은 속성들로 애니메이션을 설정하면 리플로우를 거쳐 브라우저를 다시 렌더링을 하게 된다. 이와 달리, transform 속성을 이용해서 애니메이션을 설정하면 브라우저는 Composite 단계만 다시 거쳐서 렌더링을 하게 된다.

따라서, transform을 통해 애니메이션을 설정하면 다른 속성들과 비교했을 때 렌더링 단계를 최대한으로 줄일 수 있어 렌더링 부담이 줄어든다.


✔️ 2d 대신 3d transform 사용하기
transform은 독자적으로 요소의 위치 및 확대, 축소, 회전이 가능한 css 요소이다. 이는 브라우저에서 GPU를 사용하므로 CPU의 부담을 덜어 성능 저하를 막아준다.

3d transform의 경우 x, y, z축으로 3차원 상에서 이동할 수 있기 때문에 2d transform보다 더 다양한 변환을 구현할 수 있고, 자연스러운 움직임을 구현할 수 있다.
예를 들어, 3d transform을 사용하면 객체를 회전시키거나 평면에 수직한 면에 글자를 새겨 넣는 등 다양한 변환을 구현할 수 있다. 또한 특정 객체가 다른 객체보다 더 앞쪽에 위치하도록 설정할 수 있어 더욱 다양한 시각적 효과를 구현할 수 있게 해주며, 더욱 부드러운 애니메이션을 구현할 수 있습니다.


✔️ will-change 사용하기
will-change는 css의 속성으로, 미래에 값에 변화가 있을 것을 미리 알려줘서 최적화할 수 있도록 도와준다. 변화가 일어날 요소의 속성으로 넣어주면 되고, 값으로는 변화가 일어날 속성을 넣어주면 된다.

div {
	/* 키워드 값 */	
    will-change: auto;
    will-change: scroll-position;
    will-change: contents;
    will-change: transform;  /* Example of <custom-ident> */
    will-change: opacity;    /* Example of <custom-ident> */
    will-change: left, top;  /* Example of two <animateable-feature> */

    /* 전역 값 */
    will-change: inherit;
    will-change: initial;
    will-change: unset;
}

MDN에서는 이 속성을 적당하게 사용할 것을 권장한다.

will-change는 성능 문제를 해결하기 위한 마지막 수단으로 계획된 것이기 때문에 페이지가 잘 작동한다면 추가하지 않는 것이 좋다. 또한, 브라우저는 최적화를 위해 가능한 모든 것을 시도하고 있으므로, will-change를 난무한다면 최적화하는 것에 과한 시간을 투자해 성능은 다시 저하될 수 있다.



참고

profile
호기심 많은 프론트엔드 개발자

0개의 댓글