Spring Animation은 무엇인가 (개념 설명)

Spring 애니메이션은 물리세계를 반영한 애니메이션을 말한다. 애니메이션이라는 단어를 떠올리면 ease-in 또는 ease-out 같은 Bezier Curve 애니메이션이 생각나는데 이 애니메이션과는 무엇이 다를까? 효과적인 비교를 위해서 애니메이션을 사용하는 이유와 Bezier Curve 애니메이션에 대해서 간단하게 알아보자.

거의 모든 프로덕트에는 애니메이션이 포함되어 있다. 예를 들어 스위치의 on, off 상태가 변할 때 부드러운 스타일 전환을 위해서 애니메이션을 사용한다. 왜 부드러운 스타일 전환을 사용할까? 위치가 순식간에 변하는 것보다 변화하는 과정을 보여주는 것이 더 자연스럽게 느껴지기 때문이다. 위치뿐만 아니라 속도(velocity)도 순식간에 변하는 것보다 서서히 변하는 게 더 자연스럽다. 왜냐하면 실제 물리 세계에서는 운동 중에 동일한 속도를 가지는 물체는 거의 없기 때문이다.(가속도가 없는 물체는 없다.) 그래서 CSS 속성인 transition-timing-function에서 linear보다는 속도가 서서히 변하는 ease-in, ease-out을 더 자주 사용한다.

ease-inease-out를 사용한 애니메이션은 Bezier Curve 애니메이션에 속한다. Bezier Curve 애니메이션은 durationcurve의 조합으로 구성된다. Bezier curve 애니메이션은 x축이 시간이고 y축이 위치인 곡선 그래프로 표현할 수 있다. Bezier curve의 구성요소 중 하나인 curve는 그래프의 모양을 뜻한다. ease-in, ease-in-outcurve의 종류 중 하나다. duration은 애니메이션이 끝날 때까지 걸리는 시간을 의미한다. 아래 이미지에서 볼 수 있듯, linear는 일직선으로 이루어져 있어서 속도가 항상 일정하지만 ease-in이나 ease-in-out은 곡선으로 이루어져 있어서 속도가 연속적으로 변해서 훨씬 자연스럽게 느껴진다.

Spring 애니메이션도 Bezier curve 애니메이션과 비슷한 모양(곡선)을 가지지만 ease-in, ease-in-out처럼 정확한 모양을 가지지 않는다.
velocity(초기 속도), mass(질량), stiffness(탄성), damping(감쇠)에 따라서 그 모양이 다르다. 이 점이 가장 큰 차이다. ease-in,ease-in-out과의 공통점은 속도와 위치가 연속적으로(서서히) 변한다는 것이다.

Spring Animation은 언제 사용할까?

Spring애니메이션은 언제 사용해야 하는지 궁금할 것이다. 지금까지는 Bezier curve와 다를 것이 없어 보인다. 사용자와의 인터렉션이 있을 때 Spring 애니메이션은 빛을 발한다. 핸들을 통해서 열림/닫힘을 조절할 수 있는 바텀시트를 생각해보자. 우리가 모바일에서 경험하는 바텀시트는 다음의 특징을 가진다. 바텀시트의 핸들을 잡고 빠르게 밀면 닫을 수 있지만 비교적 약하게 밀었을 때는 닫을 수 없다. 그리고 빠르게 밀수록 더 빠르게 바텀시트가 닫혀야한다. Bezier curve 애니메이션을 통해서는 빠르게 밀수록 바텀시트가 빠르게 닫히는 것을 자연스럽게 구현하기 힘들다. 사용자가 핸들을 민 속도에 따라서 애니메이션의 속도도 결정되어야 하지만 Bezier curve의 초기 속도는 항상 정해져 있기 때문이다. 하지만 앞서 말한 네 가지 요소 (속도,질량,탄성,감쇠)에 의해 결정되는 Spring 애니메이션은 Spring 애니메이션을 통해서 더 자연스럽고 정교한 애니메이션을 만들 수 있다.

또 다른 예시로는 스크롤이 있다. 웹페이지를 스크롤 해보면 바로 멈추지 않고 서서히 멈춘다. 힘의 크기가 클수록 더 많이 내려간다. Spring 애니메이션이라서 항상 용수철처럼 튕김(bounce)이 있어야 될 것 같지만 튕김이 있어야 꼭 Spring 애니메이션은 아니다. 앞서 소개했던 바텀시트와 스크롤 모두 튕김이 없는 Spring 애니메이션을 사용했다. 물리적 세계를 구현한 애니메이션이라고 생각하자.

1. linear
2. ease-in
3. spring
원을 직접 이동시켜서 각 애니메이션의 차이를 살펴보자.

Spring 애니메이션은 어떻게 동작하는가?

스프링 애니메이션은 네 가지 요소에 의해서 결정된다. 많은 Spring 애니메이션에서 옵션으로 사용되기에 알아두면 애니메이션 라이브러리를 사용할 때 유용하다.

  1. 탄성 (stiffness 혹은 tension)
  2. 질량 (mass)
  3. 초기 속도 (initial velocity)
  4. 감쇠 (damping)

탄성과 질량

이제부터 용수철과 관련된 공식을 통해서 세 가지 요소에 대해서 설명해 보겠다. 물리를 몰라도 알 수 있다. 용수철을 생각해 보자. 용수철은 늘리거나 줄이면 다시 원래의 상태로 돌아가려고 한다. 그리고 늘리는 정도가 클수록 원래 상태로 돌아가려는 힘도 커진다. 공식을 써보면 다음과 같다.

F = -kx

k는 탄성(stiffness)를 가리키는 상수다. k 값이 큰 봄은 더 강한 힘으로 원래 상태로 돌아가려고 하며, k 값이 작은 봄은 그만큼 약한 힘으로 돌아가려고 한다. x는 변형 정도(늘어나거나 압축된 정도)를 뜻한다. 이 공식의 핵심은 이 법칙의 핵심은 작용하는 힘(F)이 그 변형 정도에 비례한다는 것이다. 이를 훅의 법칙이라고 한다.

그런데 F를 보면 학교에서 한 번쯤 들었던 공식이 생각날 것이다. 바로 F = ma다. 힘은 질량(mass)과 가속도에 비례 한다는 것이다. 그렇다면 훅의 법칙을 다음과 같이 변형할 수 있다.

ma = -kx

또 아래와 같이 표현할 수 있다. 이 공식을 통해서 질량(mass)이 작을수록 가속도가 커지는 것을 알 수 있다.

a = -kx/m

초기속도

초기속도는 어떤 상관이 있을까? 초기속도는 힘과 관련이 있다. 용수철을 세게 잡아당길수록 초기 속도는 빨라진다. 용수철이 원래 상태로 돌아가려고 할 때 더 빠른 속도로 움직인다는 것이다. 초기 속도(initial velocity)는 물체에 가하는 힘이라고 생각하면 된다. 예를 들어 바텀시트 핸들을 얼마나 빨리 내리느냐 같은 것이다.

감쇠

훅의 법칙으로 현실 세계를 모두 표현할 수 없다. 현실 세계에서는 마찰이 존재한다. 하지만 훅의 법칙은 이를 고려하지 않았다. 실제 세계에서는 속도가 점차 감소해서 용수철이 결국 멈출 것이다. 이를 감쇠(damping)라고한다. 감쇠가 크면 클수록 더 빠르게 용수철이 멈춘다.

식으로 간단하게 표현하면 다음과 같다. 전체 힘을 용수철의 힘 Fs와 감쇠 힘 Fd로 나눌 수 있다.

Fd = -d * v
Fs + Fd = ma
 
// 이렇게 표현할 수 있다. F = ma의 변형
a = (Fs + Fd)/m

Spring 애니메이션의 종류

Spring 애니메이션은 앞서 설명한 여러 요소들에 의해서 모양이 달라지지만 크게 세 가지로 나뉠 수 있다.


  1. Underdamped (미계쇠 상태)

이 상태에서 감쇠가 있지만 충분하지 않아 과하게 진동한다. 여러 번 진동하다가 멈추게 된다.

  1. Critically damped (임계 감쇠 상태)

임계 감쇠 상태에서는 가능한 가장 빠른 시간 내에 원래 위치로 돌아간다. 불필요한 진동 없이 정지한다. 이는 감쇠가 정확히 적절한 수준으로 설정되어 있을 때 발생한다.

  1. Overdamped (과감쇠 상태)

이 상태에서는 감쇠는 강해서 시스템이 원래 위치로 돌아오는 것이 느리다. 불필요한 진동이 없다.

각 상태는 여러 요소들의 조합으로 이루어진다. react-spring이나 swift에서는 bounce라는 옵션 하나로 여러 요소들의 조합을 설정할 수 있게 간소화 하기도 했다.

Spring 애니메이션을 사용하면 안되는 경우

모든 애니메이션에 Spring 애니메이션을 사용해야 하는 것은 아니다. 예를 들어 일정한 속도를 유지해야 하는 로딩 애니메이션이 그렇다. 그리고 Spring 애니메이션은 아직 CSS로 구현할 수 없기에 구현하기 위해서 Javascript를 사용해야 한다. Javascript를 통해서 frame마다 스타일을 업데이트해야 한다. 만약 웹 페이지에서 무거운 연산이나 잦은 Javascript 실행을 하고 있다면 Spring 애니메이션을 사용하지 말아야한다. 되려 UX를 향상 시키려고 Spring 애니메이션을 도입했지만 UX를 해칠 수 있다.

이제 Spring 애니메이션에 대한 개념을 이해했으니 각자 spring visualizer에서 각 요소들을 조절해가며 Spring을 좀 더 탐구 해보자. 그리고 더 관심이 간다면 react-spring 이나 framer-motion을 사용해서 애니메이션을 구현해 보길 권장한다. 최근에 react-spring으로 Picker 컴포넌트를 구현했다. 이에 대한 글을 써서 실용적인 부분을 다뤄보려고 한다. 구현 영상을 첨부하며 글을 마무리한다.

참조