본문 바로가기
카테고리 없음

CSS 로딩 애니메이션 (스피너, 스켈레톤, 체감속도) - 속도가 아니라 불안을 해결하는 장치다

by BOOST YOUR INFORMATION 2026. 4. 13.

로딩 애니메이션 구현 페이지가 로딩되는 동안 이탈률을 줄이는 CSS 참고이미지
로딩 애니메이션 구현 페이지가 로딩되는 동안 이탈률을 줄이는 CSS 효과

 

이미지를 10장 넘게 넣은 리뷰 글을 발행하고 나서, 핸드폰으로 접속해봤을 때 처음 든 생각은 "이건 좀 아닌데"였다. 이미지가 하나씩 뚝뚝 로드될 때마다 레이아웃 전체가 들썩이는 게 보였다. 이미지 용량을 줄이는 것만으로는 한계가 있었고, 그때부터 CSS 로딩 애니메이션을 직접 파고들기 시작했다.

링크를 클릭하고 아무것도 안 나오면 누구나 일단 기다린다. 1초, 2초. 근데 3초가 넘어가면 손가락이 자동으로 뒤로 가기를 누르게 된다. 이건 의식적인 선택이 아니다. 그냥 반사다. 식당에서 자리에 앉았는데 3분이 지나도 직원이 안 오면 그냥 나가고 싶어지는 것처럼. 뭔가 진행되고 있다는 신호가 없으면 사람은 본능적으로 포기한다.

내 블로그를 처음 만들었을 때 로딩 화면 같은 건 신경도 안 썼다. 로딩이 빠르면 장땡이지, 무슨 로딩 효과가 필요해? 하는 마음이었다. 근데 어느 날 내 글에 무거운 이미지를 잔뜩 넣고 나서 페이지 로딩이 느려졌고, 그때 처음으로 흰 화면이 얼마나 불안한지를 직접 경험했다. 이미지가 뚝뚝 내려오면서 레이아웃이 계속 바뀌는 그 화면. 내 글인데도 보기 싫었다. 로딩 애니메이션은 속도를 높이는 게 아니다. 기다리는 동안 "지금 뭔가 되고 있어요"라고 알려주는 것이다.

스피너 하나로 시작한 이유

처음에 선택한 건 가장 단순한 방식, 전체 화면 오버레이 위에 스피너를 올리는 구조였다. CSS의 @keyframes를 사용하면 별도 라이브러리 없이 구현할 수 있어서 진입 장벽이 낮았다. @keyframes란 CSS 애니메이션의 시작과 끝 상태를 정의하는 규칙으로, "이 요소가 어떻게 움직일지" 그 경로를 코드로 작성하는 것이다.

그런데 막상 적용하고 나서 문제가 생겼다. 로딩이 빠른 글에서는 스피너가 화면에 나타났다 눈 깜빡할 사이에 사라지는 게 오히려 어색해 보였다. 깜빡이듯 등장했다 사라지니 뭔가 오류가 난 것처럼 느껴질 정도였다. 그래서 최소 표시 시간을 800ms로 고정했더니 훨씬 자연스러워졌다. 기술적인 해결책이 아니라 심리적인 설계가 필요한 순간이었다. 이 경험이 내게 의미 있었던 건, 사용자가 느끼는 경험이 실제 기술 수치와 다를 수 있다는 걸 처음으로 실감한 순간이었기 때문이다.

솔직히 말하면 스피너 하나가 얼마나 바꿔줄 수 있을까 반신반의했다. 그런데 직접 내 페이지에 붙여보고 나서 차이를 느꼈다. 흰 화면에서 멈춘 것 같았던 느낌이 사라지고, 무언가 진행 중이라는 신호만으로도 기다리는 게 덜 답답해졌다. 같은 3초라도 뭔가 움직이는 게 보이면 덜 답답하다. 공항 수하물 컨베이어 벨트가 빙글빙글 돌고 있으면 짐이 안 나와도 기다릴 수 있는 것처럼. 움직임 자체가 신뢰감이다.

스켈레톤 로딩이 완성도를 바꾼 순간

스피너에 어느 정도 익숙해진 다음, 이미지 플레이스홀더에 스켈레톤 로딩을 적용해봤다. 스켈레톤 로딩이란 실제 콘텐츠가 들어올 자리에 회색 블록 형태의 임시 레이아웃을 먼저 보여주는 방식이다. 사용자 입장에서는 "이 자리에 뭔가 들어오겠구나"를 직관적으로 인식할 수 있어서 빈 화면보다 훨씬 안정감 있게 느껴진다.

여기에 shimmer 효과까지 더하면 체감이 확 달라진다. shimmer란 그라디언트가 좌에서 우로 흘러가는 듯한 빛 번짐 효과로, animation-delay 속성을 활용해 여러 요소가 순차적으로 반짝이도록 설정할 수 있다. 직접 써봤는데, 이 효과 하나 들어가니 로딩 중이라는 느낌이 살아있어서 단순 회색 박스와는 완성도 차이가 확연했다. 레이아웃이 들썩이던 문제도 자연스럽게 해결됐다.

그런데 솔직히 스켈레톤 로딩은 개인 블로그에 넣기엔 구현 비용이 적지 않다. 각 콘텐츠 블록의 크기와 형태를 미리 정의해둬야 하고, shimmer 효과까지 추가하면 코드 복잡도가 꽤 올라간다. 내 경험으로는 개인 블로그 수준이라면 스피너 하나에 최소 표시 시간 설정 정도로도 충분히 자연스러운 경험이 나왔다. 복잡한 걸 넣었다고 더 좋은 경험이 되는 건 아니다. 관리하기 어려운 코드는 결국 건드리지 않게 되고, 그러다 깨진 채로 방치되는 경우도 봤다.

체감 속도가 실제 속도보다 중요한 이유

로딩 시간이 1초에서 3초로 늘어날 때 이탈률이 32% 상승한다는 연구 결과가 있다. 숫자만 보면 속도 자체가 문제인 것 같지만, 내 경험상 이건 좀 다르다. 실제로 빠른 사이트인데도 로딩 표시가 없으면 사용자는 "멈춘 건가?" 하고 이탈한다. 반대로 진행 표시기가 있을 때 사람들이 평균 40% 더 오래 기다린다는 심리학 연구 결과도 있다. 로딩 애니메이션은 속도를 개선하는 게 아니라 불안을 제거하는 장치다.

lazy loading도 같은 맥락에서 이해할 수 있다. lazy loading이란 화면에 보이는 영역의 이미지만 먼저 불러오고, 스크롤해서 해당 위치에 가까워졌을 때 나머지를 로드하는 방식이다. 처음부터 모든 이미지를 받아오지 않으니 초기 로딩이 빨라지고, 플레이스홀더와 함께 쓰면 사용자는 로딩 중임을 인지하면서도 끊기지 않는 경험을 하게 된다. 이건 내가 써보고 나서 "왜 진작 안 썼지"라고 생각한 몇 안 되는 방법 중 하나다.

CSS 로딩 애니메이션을 구현하는 방식은 크게 이렇게 정리할 수 있다. 기본 스피너는 @keyframes와 border 속성으로 회전 원형을 구현한다. 점 세 개 순차 애니메이션은 animation-delay로 각 점의 등장 시간을 엇갈리게 설정한다. 상단 프로그레스 바는 indeterminate 방식으로 진행률과 무관하게 움직이는 바를 표현한다. 스켈레톤 로딩은 콘텐츠 자리를 미리 잡아두는 회색 블록에 shimmer 효과를 더한다. 전체 화면 오버레이는 페이지 전환 시 스피너를 전면에 배치한다. 이미지 지연 로딩 플레이스홀더는 lazy loading과 스켈레톤을 함께 적용한다.

그리고 한 가지 더, 로딩 애니메이션은 실제 속도 문제를 대신할 수 없다. 이미지 최적화, 캐싱 설정, CDN 활용 같은 근본적인 성능 개선이 먼저다. CDN이란 전 세계 여러 서버에 콘텐츠를 분산 저장해두고 사용자와 가장 가까운 서버에서 데이터를 전송하는 구조로, 물리적 거리에 따른 로딩 지연을 줄여준다. 실제 로딩이 5초 이상 걸리는 상황에서는 아무리 예쁜 스피너도 이탈을 막지 못한다. 로딩 애니메이션은 첫 번째 수단이 아니라 마지막 수단이다.

그렇다고 흰 화면으로 놔두는 건 더 아깝다. 기술보다 심리를 먼저 이해하는 것이 UX의 시작이라는 걸, 작은 스피너 하나 붙이면서 다시 배웠다. 사이트가 빠르다고 알리는 게 아니라, 사이트가 살아 있다고 알리는 것. 그 차이가 3초를 버티느냐 포기하느냐를 가른다. 지금 당장 이미지 많은 페이지 하나를 골라서 스켈레톤 플레이스홀더부터 적용해보길 권한다. 단, 넣기 전에 먼저 이미지 최적화부터 하는 것이 순서다.


참고:

Google Research – Find Out How You Stack Up to New Industry Benchmarks for Mobile Page Speed
MDN Web Docs – CSS Animations
Nielsen Norman Group – Progress Indicators
web.dev – Lazy loading images
CSS-Tricks – @keyframes


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 ⚡ 정보 부스터 🚀