CSS vs JS Animation: Which is Faster?


이 글은

velocity.js 라는 javascript 기반 라이브러리가 애니메이션 효과에 대해서 

jquery 라이브러리나 css보다도 성능이 우수하다는 글입니다.

css가 jquery 애니메이션보다는 빠르다는건 이해가 잘 되는데

자바스크립트 라이브러리가 css보다 빠르다는건 솔깃할만한 이야기 입니다.

영문으로 되어 있어 번역 해봅니다.

출처는

https://davidwalsh.name/css-js-animation

입니다.





구글이나 어도비 같은 회사들이 모바일 페이지에서 native app 같은 페이지 성능을 내는 이유는 무엇일까요?

이 글은 velocity.js, GSAP 같은 DOM 라이브러리를 소개합니다. 이들은 jquery animation이나 css보다 빠릅니다.


우선 jquery부터 살펴봅니다.

jquery는 매우 강력한 엔진임에도 애니메이션 관련한 디자인 목표는 

상대적으로 높게 잡혀있지 않기때문에 조금 느립니다.

jquery는 레이아웃 스레싱이나, 가비지 콜렉션 트리거때문에 애니메이션을 일시정지 시키기도 합니다.

requestAnimationFrame 대신 setInterval을 사용하기 때문입니다.


var currentTop,
	currentLeft;

/* With layout thrashing. */
currentTop = element.style.top; /* QUERY */
element.style.top = currentTop + 1; /* UPDATE */

currentLeft = element.style.left; /* QUERY */
element.style.left = currentLeft + 1; /* UPDATE */

/* Without layout thrashing. */
currentTop = element.style.top; /* QUERY */
currentLeft = element.style.left; /* QUERY */

element.style.top = currentTop + 1; /* UPDATE */
element.style.left = currentLeft + 1; /* UPDATE */

레이아웃 스레싱이 일어나는 상황과 아닌 상황을 보여주고 있습니다.

DOM 쿼리와 DOM업데이트를 일괄적으로 배치해야 합니다.

업데이트 이후의 쿼리는 브라우저가 스타일 데이터를 강제로 다시 계산합니다.

떄문에 16ms의 작은 간격에도 상당한 오버헤드가 발생합니다.


위에 언급했던 requestAnimationFrame (이후 RAF라 부르겠습니다) 와 setInteval을 비교해보겠습니다.


var startingTop = 0;

/* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */
setInterval(function() {
	/* Since this ticks 60 times a second, we divide the top property's increment of 1 unit per 1 second by 60. */
    element.style.top = (startingTop += 1/60);
}, 16);

/* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */
function tick () {
    element.style.top = (startingTop += 1/60);
}

window.requestAnimationFrame(tick);


둘의 차이는 setInterval은 무조건 16ms마다 실행하는 것이라면 RAF는 브라우저가 최적 상태인지를 판단해서 실행합니다.


css는 애니메이션 실행 로직을 브라우저 자체에서 실행하기 때문에 jquery보다 성능이 뛰어납니다.

이러한 작업은 DOM 상호작용 및 메모리 소비를 최적화해줍니다.

여기에 RAF 원칙이 활용되며 하드웨어의 가속을 강화합니다.


velocity.js가 css 보다 빠른 속도를 가지는 이유는 최적화를 자바스크립트 내에서 직접 수행한다는 것입니다.

8K 정도의 용량일뿐인데 가성비가 좋습니다.

주의하실점은 모든 애니메이션 효과에 해당하는 것은 아니란 것입니다.

예를 들어 3d-transform같은 것은 css 작성이 필요합니다.


css 라이브러리의 transition은 하드웨어가 힘든 상황에서 버벅임과 밴딩을 초래합니다.

이러한 현상은 모바일장치에서 특히 더 악화됩니다.

그리고 익스플로러 10 이하에서는 작동이 안되기때문에 접근성 문제가 발생하기도 합니다.

스크립트 분야에서의 제어가 없기 때문에 최적화가 되어있지 않습니다.


위에서 한번 설명했듯이, 자바스크립트 라이브러리는 최적화에 관한 내용도

컨트롤할 수 있기 때문에 더 빠르다는 것입니다.


자바스크립트로 애니메이션을 만드는 것이 어느정도까지 가능한지를 보겠습니다.

일반적으로 webGL을 사용하여 제작된 3D 애니메이션 데모를 제작할수 있을정도로 빠릅니다.

플래시나 캔버스로 만드는 티저정도도 충분합니다.


이제 어떻게 최적화를 하고 높은 수준에 도달하는지를 알아보겠습니다.

1.

 레이아웃 스레싱을 최소화하기 위해 애니메이션 체인 전체에서 DOM에서 트윈스택으로 가는 과정을 동기화시킴

※ 트윈 스택 :

'tween' 이라는 개념은 제이쿼리의 애니메이션에서 사용되는 개념입니다. 

첫번째 이미지에서 두번째 이미지로 넘어가는 것을 부드럽게 하기 위한 중간 프레임입니다.


2.

 DOM 질의를 최소화하기 위해 속성값을 캐싱합니다.

3.

 px, em 같은 단위 변환 비율을 캐싱합니다.

4.

 업데이트가 시각적으로 판별할수 없는 수준일때 스타일 업데이트를 건너 뜁니다.



Velocity.js가 최종값을 캐싱하여 재활용하면서 dom을 다시 쿼리하지 않는 모습을 보겠습니다.

메서드 체이닝이 이뤄지고 있습니다.


$element
	/* Slide the element down into view. */
	.velocity({ opacity: 1, top: "50%" })
	/* After a delay of 1000ms, slide the element out of view. */
	.velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });


두번째 velocity 호출에서 opacity : 0, top -50% 인 이유는 첫번째 호출을 기반으로 시작하기 때문입니다.


브라우저는 자체적으로 많은 최적화를 진행할 수 있지만 개발자나 애니매이션 코드를 제한하기때문에

스펙을 깨거나 예상되는 동작을 벗어나는 최적화를 하지 않습니다.


이제 Velocity.js 를 자세히 소개하겠습니다.

기존에 jquery에서 .animate() 를 사용 했다면 animate 대신에 velocity를 넣어주면 됩니다. 

따로 코드를 수정하지 않아도 된다는게 강점입니다.


$element
	.delay(1000)
	/* Use Velocity to animate the element's top property over a duration of 2000ms. */
	.velocity({ top: "50%" }, 2000)
	/* Use a standard jQuery method to fade the element out once Velocity is done animating top. */
	.fadeOut(1000);


3D애니메이션을 사용하여 복잡한 스크롤링을 만드는데엔 두줄정도의 코드가 필요합니다.

$element
	/* Scroll the browser to the top of this element over a duration of 1000ms. */
	.velocity("scroll", 1000)
	/* Then rotate the element around its Y axis by 360 degrees. */
	.velocity({ rotateY: "360deg" }, 1000);

velocity 프로젝트는 웹성능향상을 위해 고수들이 모여서 2008년부터 시작한 프로젝트입니다.

간단한 웹작업이 아니라면 애니메이션 작업에는 velocity.js를 써주는게 이득입니다.

글을 마칩니다.


New Multi-Channel Dynamic CMS