MOTIVE · 읽을거리
SVG 애니메이션은 어떻게 움직이고, 얼마나 가벼울까?
알림을 켤 때 살짝 흔들리는 종, 저장을 마칠 때 그려지는 체크. 작은 움직임은 인터페이스의 상태 변화를 전합니다. SVG가 이 움직임을 만드는 방법과, 여러 아이콘을 사용할 때 확인할 성능 기준을 살펴봅니다.
1. 도형에 시간표를 더하면 애니메이션이 된다
SVG는 path, circle, rect 같은 도형을 좌표와 속성으로 표현합니다. viewBox="0 0 24 24"는 내부 좌표계를 정하고, width와 height는 화면에 표시할 크기를 정합니다. 같은 도형을 여러 크기로 표현할 수 있는 이유입니다.
애니메이션은 이 도형의 속성이 시간에 따라 바뀌는 과정입니다. 예를 들어 0%에서 회전각이 0도, 중간에 -18도, 끝에 다시 0도가 되도록 키프레임을 정하면 종이 흔들립니다. 브라우저는 지정한 duration과 easing에 따라 중간 값을 계산합니다. 모든 프레임의 이미지를 따로 저장할 필요는 없습니다.
2. 체크가 그려지는 원리: 선의 시작점을 움직인다
체크가 새로 생기는 것처럼 보여도 도형 자체는 이미 있습니다. stroke-dasharray로 선과 빈 구간의 패턴을 만들고, stroke-dashoffset을 바꿔 그 패턴의 시작점을 이동하면 선이 점차 나타납니다.
아래 예제는 pathLength="60"으로 경로 길이 계산의 기준을 60으로 맞춘 뒤 dashoffset을 60에서 0으로 바꿉니다. 여기서 60은 화면 픽셀 수가 아닙니다. 기본 속성은 완성된 체크를 표시하므로 애니메이션을 끄거나 동작 줄이기를 켜도 의미가 남습니다. 코드를 HTML에 붙여 넣어 같은 효과를 확인할 수 있습니다.
MDN · stroke-dashoffsetMDN · pathLength
직접 확인하는 선 그리기
동일한 SVG와 CSS를 아래에 실었습니다. 반복 재생을 멈추거나 다시 시작할 수 있으며, 시스템의 동작 줄이기 설정에서는 완성된 체크가 표시됩니다.
<svg xmlns="http://www.w3.org/2000/svg"
width="64" height="64" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<style>
.motive-draw { animation: motive-draw 1.8s ease-in-out infinite; }
@keyframes motive-draw {
0% { stroke-dashoffset: 60; }
60%, 100% { stroke-dashoffset: 0; }
}
@media (prefers-reduced-motion: reduce) {
.motive-draw { animation: none; }
}
</style>
<path class="motive-draw" d="m6 12 4 4 8-8"
pathLength="60" stroke-dasharray="60" stroke-dashoffset="0" />
</svg> 3. CSS와 Web Animations API는 어디에 쓰일까?
정해진 움직임을 반복하거나 한 번 재생할 때는 CSS @keyframes로 충분한 경우가 많습니다. Motive에서 다운로드하는 SVG에는 CSS가 들어 있어 별도 애니메이션 라이브러리 없이 재생됩니다. img로 넣은 SVG의 내부 요소는 페이지의 CSS나 DOM 선택자로 직접 제어할 수 없으므로, 내부 도형과 상호작용해야 한다면 인라인 SVG를 고려하세요.
편집 화면처럼 재생·정지·구간 이동을 제어할 때는 Web Animations API가 편리합니다. Motive 편집기는 같은 모션 모델에서 미리보기의 키프레임과 내보낼 CSS를 만듭니다. 프레임마다 React 상태를 바꾸는 방식이 아니라 브라우저의 애니메이션 재생 기능을 사용합니다. CSS와 JavaScript 중 무엇을 골랐는지만으로 렌더링 성능이 결정되지는 않습니다.
4. SVG라는 이유만으로 가볍지는 않다
다운로드 용량과 재생 중의 렌더링 비용은 따로 봐야 합니다. 도형 몇 개로 만든 아이콘은 간결할 수 있지만, 복잡한 경로·필터·많은 DOM 요소가 있는 SVG는 처리할 일이 많아집니다. SVG가 항상 GIF보다 작거나 모든 기기에서 일정한 FPS를 낸다고 단정할 수는 없습니다.
브라우저는 필요한 스타일·레이아웃·페인트·합성 작업을 수행해 화면을 갱신합니다. 움직이는 속성과 그리는 영역, 동시에 재생하는 수가 비용에 영향을 줍니다. transform과 opacity를 우선 검토하되, 특히 SVG에서는 실제 합성 여부를 브라우저와 장면에서 확인해야 합니다.
| 효과 | 주로 바꾸는 속성 | 확인할 비용 |
|---|---|---|
| 회전·이동·크기·깜박임 | transform, opacity | 합성으로 처리할 여지가 있지만 GPU 처리나 페인트 생략이 항상 보장되지는 않습니다. |
| 선 그리기·도형 변화 | stroke-dashoffset, d | 선이나 도형을 다시 그리는 비용을 확인하세요. 복잡한 경로를 여러 개 동시에 움직이면 부담이 커질 수 있습니다. |
| 흐림·그림자·많은 도형 | filter, 도형 수와 그리기 영역 | 필터 영역과 도형 수를 줄이며 페인트 시간과 메모리 변화를 비교하세요. |
5. 실제 화면에 넣을 때 확인할 것
- 완료·오류처럼 짧은 상태 변화는 필요한 순간에 재생하고, 계속 반복할 이유가 있는지 확인하세요.
- 긴 목록에서는 IntersectionObserver로 화면 밖의 반복 재생을 멈추고, 탭이 숨겨질 때의 동작도 확인하세요. Motive 목록은 화면 안의 카드만 재생합니다.
- prefers-reduced-motion: reduce를 존중하고 정지 상태에서도 의미가 남도록 만드세요. 장식용 아이콘은 aria-hidden을, 정보를 전달하는 이미지는 적절한 대체 텍스트를 사용하세요.
- width와 height로 표시 공간을 미리 확보하세요. 같은 SVG를 인라인으로 여러 번 넣는다면 title·마스크·그라디언트 등의 ID가 겹치지 않게 하세요.
- will-change를 모든 아이콘에 미리 지정하지 마세요. 실제 문제를 측정한 뒤 필요한 요소에만 적용하고 효과를 비교하세요.
6. 성능은 같은 조건에서 측정한다
- 같은 아이콘·크기·모션·재생 시간으로 조건을 고정합니다. 1개, 20개, 100개처럼 동시 재생 수를 바꾸되 화면에 보이는 수와 전체 수를 구분해 기록하세요.
- 개발 서버 대신 실제 배포와 비슷한 빌드를 사용합니다. Network에서 압축 후 전송량과 요청 수를 확인하세요. 파일 크기만으로 재생 성능을 판단하지 마세요.
- DevTools의 Performance 패널로 재생과 스크롤을 기록하고 Layout·Paint·프레임 지연을 비교합니다. 60Hz 화면의 한 프레임은 약 16.7ms이지만 이는 페이지 전체 작업의 시간 예산입니다. 측정 없이 특정 FPS를 보장하지 마세요.
- 실제 모바일 기기에서도 확인합니다. 동작 줄이기, 화면 밖의 아이콘, 숨겨진 탭, 반복 횟수를 바꿔 보고 사용한 기기·브라우저·조건을 함께 남기면 결과를 재현하기 쉽습니다.