Lottie와 모션 접근성 — 멀미 나지 않는 애니메이션
애니메이션은 제품을 생동감 있게 만들지만, 전정 장애가 있는 사용자에게는 어지러움과 멀미를, ADHD 사용자에게는 심각한 주의 분산을 일으킬 수 있습니다. 모션 접근성은 "있으면 좋은 것"이 아니라 WCAG가 요구하는 기본입니다.
이게 극소수의 문제라고 생각하기 쉬운데, 실제로는 그렇지 않습니다. 미국 국립보건원 조사를 인용한 자료들을 보면 40세 이상 성인의 약 35%가 전정 기능 이상을 한 번 이상 경험한 것으로 알려져 있고, 굳이 진단명이 없어도 화면 전환 애니메이션에 멀미를 느껴 iOS의 "동작 줄이기"를 켜 두는 사용자는 주변에서도 어렵지 않게 볼 수 있습니다. 저는 CGM(연속혈당측정) 앱을 만들다 보니 사용자 중 고령층 비중이 높은 편인데, 화려한 전환 효과를 넣었다가 "화면이 어지럽다"는 피드백을 받고 걷어낸 경험이 있습니다. 그 뒤로는 모션 축소 설정을 기능 요구사항의 하나로 취급하고 있습니다.
1. 모션 축소 설정을 존중하라
iOS·Android·모든 데스크톱 OS에 "동작 줄이기" 설정이 있고, 이를 켠 사용자에게는 장식성 애니메이션을 끄는 것이 원칙입니다.
웹
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
const anim = lottie.loadAnimation({
container: box,
path: "/assets/hero.json",
autoplay: !reduced, // 축소 설정이면 자동재생 안 함
loop: !reduced,
});
// 주의: path 로드는 비동기 — totalFrames는 로드 완료 후에만 유효합니다
if (reduced) anim.addEventListener("DOMLoaded", function () {
anim.goToAndStop(anim.totalFrames - 1, true); // 마지막 프레임 정지화면
});
iOS
if UIAccessibility.isReduceMotionEnabled {
// 정지 프레임 표시 또는 페이드로 대체
}
Android
val scale = Settings.Global.getFloat(
contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f)
if (scale == 0f) { /* 애니메이션 비활성 사용자 */ }
2. 자동재생 기준 — WCAG 2.2.2
5초 이상 자동으로 움직이는 콘텐츠에는 일시정지·정지·숨기기 수단을 제공해야 합니다. 실무 적용 기준:
- 5초 미만 1회 재생(온보딩 체크 등) — 그대로 OK
- 무한 루프(배경 장식·히어로) — 축소 설정 존중 + 정지 수단 제공
- 로딩 인디케이터 — 상태 표시이므로 예외로 보지만, 축소 설정 시 단순한 형태로 대체하면 더 좋음
3. 깜빡임 — 초당 3회 규칙
초당 3회를 넘는 번쩍임은 광과민성 발작을 유발할 수 있습니다(WCAG 2.3.1). 파티클 폭발, 빠른 색 반전이 들어간 에셋은 받았을 때 뷰어에서 느리게 재생해 보며 깜빡임 빈도를 확인하세요.
4. 스크린 리더 — 의미가 있다면 대체 텍스트
애니메이션이 정보를 전달한다면(예: 성공/실패 상태) 스크린 리더 사용자에게도 같은 정보가 가야 합니다.
<!-- 웹: 장식이면 숨기고 -->
<div id="deco-anim" aria-hidden="true"></div>
<!-- 의미가 있으면 라벨 -->
<div id="success-anim" role="img" aria-label="결제가 완료되었습니다"></div>
iOS는 accessibilityLabel, Android는 contentDescription으로 동일하게 처리합니다.
체크리스트
위 내용을 릴리즈 전에 빠르게 훑을 수 있게 정리했습니다. 각 항목이 어떤 상황을 잡아내는지 짧게 붙여 두었으니, 팀 QA 시트에 옮길 때 참고하세요.
- ☐ 모션 축소 설정에서 장식 애니메이션이 꺼지는가 — OS 설정을 켠 상태로 주요 화면에 한 번씩 진입해 눈으로 확인
- ☐ 5초+ 루프에 정지 수단이 있는가 — 히어로·배경처럼 무한 반복하는 에셋이 대상
- ☐ 초당 3회 이상 깜빡이는 구간이 없는가 — 파티클·색 반전이 있는 에셋은 느린 배속으로 재생해 확인
- ☐ 의미 있는 애니메이션에 대체 텍스트가 있는가 — 성공/실패 같은 상태를 전달하는 경우 필수
- ☐ 애니메이션 없이도 기능을 쓸 수 있는가 — 애니메이션이 유일한 안내 수단이라면 설계를 다시 볼 것
팀에 모션 접근성 도입하기
개인이 기억해서 챙기는 방식은 오래가지 않습니다. 담당자가 바뀌거나 일정이 급해지면 가장 먼저 빠지는 게 이런 항목이기 때문입니다. 제 팀에서 해보고 실제로 유지되고 있는 방법 두 가지를 공유합니다.
QA 체크리스트에 모션 축소 테스트 넣기
릴리즈 전 리그레션 시트에 "동작 줄이기 켜고 주요 화면 진입" 한 줄을 추가하는 것으로 시작했습니다. iOS라면 설정 → 손쉬운 사용 → 동작 → 동작 줄이기를 켠 상태에서 온보딩·홈·주요 플로우를 한 번씩 도는 데 몇 분이면 충분합니다. 처음 이 항목을 넣은 릴리즈에서 바로, 축소 설정을 켰는데도 온보딩 Lottie가 그대로 무한 루프를 도는 문제를 QA가 잡아냈습니다. 개발자가 시뮬레이터 기본 설정으로만 확인하면 절대 발견되지 않는 유형의 버그라, 프로세스에 넣은 효과를 체감한 순간이었습니다.
디자이너와 정지 프레임 정하기
모션 축소 사용자에게 보여줄 정지 화면을 개발자가 임의로 "마지막 프레임"으로 정하면 어색해지는 경우가 많습니다. 체크 표시처럼 결과로 끝나는 애니메이션은 마지막 프레임이 자연스럽지만, 루프형 장식은 마지막 프레임이 하필 요소가 화면 밖으로 빠진 순간일 수도 있습니다. 그래서 저희는 에셋을 전달받을 때 디자이너가 정지용 프레임 번호를 함께 지정해 주는 규칙을 만들었습니다. 디자이너와 함께 뷰어에서 프레임 단위로 넘겨 보며 가장 안정적인 장면을 고르고, 코드에서는 그 번호로 goToAndStop을 호출하면 됩니다.