웹에서 애니메이션을 표현할 때 어떤 언어를 쓰고 계신가요?
간단한 작업은 CSS, 복잡한 작업엔 JavaScript를 쓰고 있을 것이라고 생각합니다.
간단한 작업이라 하면 버튼의 색을 바꾸는 것과 같은 UI 요소의 상태 전환을 뜻하고, 복잡한 작업은 공이 튀는 바운스 애니메이션 같은 세밀한 제어가 필요한 애니메이션을 뜻합니다. 그리고 애니메이션 기능이 포함된 jQuery 또는 JavaScript 프레임워크를 이미 사용 중인 경우, CSS 애니메이션은 잘 안 쓸 겁니다.
CSS는 꼭 간단한 애니메이션 작업에만 써야 하는 걸까요? PURE CSS라고 올라오는 작업물들을 보면 꽤 복잡한 것들도 있는데 말이죠. 실무에서 적용하긴 어려워 보이는 작업물들이 태반이지만, 속성(property)들을 조합하여 재밌는 결과물들을 만들어냈다는 것은 확실합니다.
PURE CSS 예시 : http://codepen.io/davidkpiano/pen/wMqXea
코드를 효율적으로 작성해서 재활용 할 수 있고, 속성들을 잘 조합할 수만 있다면 실무에서도 사용할 기회가 생기지 않을까요? 이제부터 연재하려는 글에서는 CSS 애니메이션 코드를 효율적으로 짜려면 어떻게 해야하는지, 속성들의 조합에 대해 주로 다뤄볼 예정입니다. 궁금한 점이나 의견, 잘못된 점이 있다면 댓글로 알려주세요.
CSS와 JavaScript는 어떻게 다른가요?
CSS와 JavaScript의 큰 차이점은 선언형과 명령형 언어라는 점입니다. 더 간단하게 설명하자면 CSS는 이미 정해진 룰이 있기 때문에 어느정도 표현의 한계가 있고, JavaScript는 정형화된 것이 없어 표현에 자유롭습니다. 그래서 JavaScript를 세밀한 제어가 필요한 애니메이션에 주로 쓰는 것이구요.
하지만 선언형 언어인 CSS는 JavaScript보다 쉽게 사용할 수 있습니다. 정해져 있는 속성들에 값을 넣는 규칙만 안다면 바로 사용할 수 있죠. 코드를 보면 확실하게 와닿을거에요.
CSS 애니메이션
animation-name: move;
animation-duration: 3.5s;
@keyframes move {
from { transform:translate(0,0); }
to { transform:translate(350px,350px); }
}
CSS 애니메이션은 직관적인 이름을 가진 속성들을 활용하는데 이런 장점때문에 JavaScript 코드보다 배우기도 쉽고 이해하기 쉬워요.
JavaScript 애니메이션
myMove();
function myMove() {
var elem = document.getElementById("moveAnimation");
var pos = 0;
var id = setInterval(frame, 10);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
비교해보니 JavaScript 애니메이션이 다루기 어려워보이죠? 그래도 값을 하나하나 다 조절할 수도 있으니 세밀한 애니메이션 작업엔 더 유리해보입니다. 다시 CSS 애니메이션의 장점으로 돌아가면, 브라우저에 최적화하기 쉽다는 장점이 있습니다. 왜 최적화하기 쉬운지에 대해 차근차근 알려드리도록 할게요.
일단 브라우저에서 CSS가 어떻게 실행되는지 알아봅시다.
CSS 애니메이션이 실행됐을 때의 타임라인을 캡쳐한 이미지에요. 아래쪽에 잘 보면 Call Tree 탭이 있고 액티비티(Activity)마다 소요된 시간이 나와있습니다. 각 액티비티들이 어떤 역할을 하는지, 어떤 순서로 진행되는지 알려드릴게요.
1. Recalculate Style - 요소에 적용할 스타일을 계산합니다.
2. Layout - 각 요소의 형태와 위치를 생성합니다.
3. Paint - 각 요소들이 그려지고(paint) 레이어에 넣습니다. 그리고 레이어들을 GPU로 업로드합니다.
4. Composite Layers - 레이어를 합성하여 화면에서 그려냅니다. (= 프레임을 그려냅니다.)
(그림 2)는 CSS가 어떤 순서로 어떻게 실행되는지 요약한 이미지입니다. CSS 애니메이션은 Composite Layers Activity에서 이뤄지게 되는데 더 자세히 알아보도록 합시다.
그리고 컴포지팅(Compositing)이라는 말을 자주 사용하게 될텐데 'Composite Layers Activity에서 레이어를 합성하는 것'이라고 이해하시면 되겠습니다.
CSS 애니메이션은 어떻게 동작할까요? (Composite Layers Activity)
CSS 기반 애니메이션, 웹 애니메이션은 일반적으로 브라우저의 메인 쓰레드가 아닌 컴포지터 쓰레드에서 처리됩니다. 메인 쓰레드는 Styling, Layout, Painting, JavaScript를 실행하고 컴포지터 쓰레드에서 애니메이션에 관련된 작업을 처리하죠.
컴포지터 쓰레드는 메인 쓰레드에서 정보를 받아와 독립적으로 프레임을 그려냅니다. 메인 쓰레드가 무거운 작업을 하고있더라도 말이죠. 여기서 그린다는 말을 정확히 짚고 넘어가겠습니다. 컴포지팅 단계에서 프레임을 그린다(픽셀을 그린다)는 것은 drawing입니다. 그 후에 나오는 페인팅 단계에서 그린다는 것은 painting이구요. drawing != painting을 명심해두시길 바랍니다.
페이지가 컴포지터 쓰레드를 통해 렌더링 될 때, 모든 픽셀은 GPU 프로세스를 통해 윈도우의 백 버퍼에 직접 그려집니다.
JavaScript는 메인 쓰레드가 무거운 작업을 하고 있으면 우선순위가 밀리는 반면, CSS 애니메이션은 독립적인 컴포지터 쓰레드가 처리해주기 때문에 큰 문제가 없습니다. 이 차이점때문에 최적화하기 쉽다는 이야기가 나온 것이죠. 하지만 마구잡이로 CSS 애니메이션을 썼을 때에도 장점을 가져갈 수 있을까요? 어떻게 써야 브라우저에 최적화할 수 있는 걸까요?
부드러운 애니메이션을 표현(최적화)하기 위해선 컴포지팅에 영향을 주는 속성(transform, opacity)만을 사용하는 것이 바람직합니다. 그렇지 않을 경우 아래 영상과 같은 결과가 나타나죠.
레이아웃(Layout)에 영향을 주는 속성인 top, left을 사용한 경우 툭툭 끊기는 것을 볼 수 있습니다.
반면, 컴포지팅에 영향을 주는 속성인 transform을 사용했을 땐 한층 부드러워 보입니다.
레이아웃은 영향받을 때마다 페이지 또는 페이지의 일부를 다시 계산해야 하며, 일반적인 작업보다 훨씬 많은 시간이 소요됩니다. 그러므로 레이아웃과 페인팅(Painting)에 영향을 주는 속성으로 애니메이션을 표현하는 것은 지양해야 합니다.
레이아웃, 페인팅, 컴포지팅에 영향을 주는 속성들은 어떤 것들이 있을까요?
레이아웃에 영향을 주는 속성들은 다음과 같습니다.
요소가 레이아웃 속성에 의해 변경될 때 브라우저는 영향을 받는 모든 요소들의 형태와 위치를 계산합니다. 하나의 요소만 수정했다고 하더라도 다른 요소들의 형태와 위치가 재계산될 수 있습니다. 부모 요소의 width 값이 변경됐을 때 자식 요소의 width 값이 퍼센트라면 영향을 받아 함께 변경되는 것처럼요.
페인팅에 영향을 주는 속성들은 다음과 같습니다.
위에 나열된 속성들을 사용하면 요소들은 다시 그려져야 하고 요소들이 속한 레이어들은 GPU로 다시 업로드해야 합니다. 모바일 디바이스들의 CPU는 데스크탑보다 낮은 성능을 가지고 있기 때문에 특히 더 조심해서 써야 합니다. 페인팅 작업에 더 많은 시간이 소요될 수 있기 때문이죠. 그리고 CPU와 GPU 간의 대역폭이 제한되어 있으므로 텍스쳐의 전송에 많은 시간이 소요됩니다.
컴포지팅에 영향을 주는 속성들은 다음과 같습니다.
CSS 애니메이션에서 주로 사용해야 하는 것은 컴포지팅에 영향을 주는 Transform과 Opacity입니다.
Transform은 많은 하위 속성들을 가지고 있으며, 속성들의 조합을 통해 재미있는 애니메이션을 만들어낼 수 있습니다. 하위 속성들에 대해서는 다음 글에서 더 자세하게 다뤄볼 예정입니다. Opacity는 GPU에 의해서 단순한 페인팅으로 처리되어 컴포지팅됩니다. 그리고 동작하려면 요소가 레이어 안에서 하나여야만 합니다.
마지막으로 정리하자면
CSS 애니메이션은 JavaScript보다 브라우저에 최적화하기 쉽습니다.
레이아웃과 페인팅 속성들은 요소에 직접적인 영향을 주기 때문에 프레임 저하를 일으킬 수 있으며, 효율적으로 CSS 애니메이션을 사용하기 위해선 요소가 아닌 레이어를 다루는 것(컴포지팅 속성)이 핵심입니다.
다음 글에서는 애니메이션 관련 속성들과 Transform 속성들에 대해 알아보겠습니다.
같이 광복 이후, 한 세기 넘게 변화가 없던 15조 원에 달하는 주류� 시장을 바꿔나가봐요.
참고한 글
https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
https://developers.google.com/web/fundamentals/design-and-ui/animations/css-vs-javascript
https://developers.google.com/web/fundamentals/design-and-ui/animations/animations-and-performance
https://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
http://blog.ryumiel.net/articles/introducing-threaded-compositor/