Compit
소개문의요금제개인정보처리방침이용약관환불규정

온드(ONDE) | 대표: 노승현 | 사업자등록번호: 778-22-02215

서울특별시 광진구 긴고랑로 133-1, 401호(중곡동, 백림주택) | 전화: 010-7794-3962

© 2026 Compit. All rights reserved.
COMPIT
챌린지연습장쇼케이스학습블로그랭킹가이드보안기초
챌린지연습장쇼케이스학습블로그랭킹가이드보안기초
홈/블로그/CSS 애니메이션과 트랜지션 — 움직이는 UI 만들기
CSS

CSS 애니메이션과 트랜지션 — 움직이는 UI 만들기

transition, transform, @keyframes로 자연스러운 인터랙션을 만드는 방법을 단계별로 알아봅니다.

2026-03-10·⏱ 11분
CSS애니메이션transitiontransform

왜 애니메이션이 중요한가?

버튼을 클릭했을 때 아무 반응이 없으면 "눌린 건가?" 싶습니다. 호버했을 때 색이 툭 바뀌면 어색하죠. 부드러운 애니메이션은 사용자에게 "잘 동작하고 있어요"라는 피드백을 줍니다.

좋은 UI 애니메이션의 원칙:

  • 목적이 있어야 합니다 — 예쁘기만 하면 안 되고, 사용자 경험을 개선해야 합니다
  • 빨라야 합니다 — 대부분의 UI 트랜지션은 200~300ms가 적당합니다
  • 자연스러워야 합니다 — ease-out, ease-in-out 같은 타이밍 함수를 사용합니다

transition: 상태 변화를 부드럽게

CSS 속성이 변할 때 중간 과정을 자동으로 보간합니다.

.btn {
  background: #1a1a1a;
  color: white;
  transition: background 0.2s ease;
}

.btn:hover {
  background: #333;
}

transition 없이는 색이 확 바뀌지만, transition을 넣으면 0.2초에 걸쳐 부드럽게 변합니다.

transition 속성 분해

transition: property duration timing-function delay;

/* 예시 */
transition: all 0.3s ease-out;
transition: background 0.2s ease, transform 0.2s ease;
transition: opacity 0.15s ease-in-out 0.1s;  /* 0.1초 후 시작 */

타이밍 함수 (easing)

함수특징용도
ease시작·끝 느리게범용 (기본값)
ease-in시작만 느리게화면 밖으로 나갈 때
ease-out끝만 느리게화면 안으로 들어올 때
ease-in-out시작·끝 느리게부드러운 왕복
linear일정 속도프로그레스 바

프로 팁: UI 요소가 나타날 때는 ease-out, 사라질 때는 ease-in을 사용하면 가장 자연스럽습니다.

transform: 변형

요소를 이동, 회전, 확대/축소합니다. 레이아웃을 건드리지 않고(리플로우 없이) GPU로 처리되므로 성능이 뛰어납니다.

/* 이동 */
transform: translateX(20px);
transform: translateY(-10px);
transform: translate(20px, -10px);

/* 크기 */
transform: scale(1.05);       /* 5% 확대 */
transform: scaleX(1.5);       /* 가로만 1.5배 */

/* 회전 */
transform: rotate(45deg);
transform: rotate(-90deg);

/* 기울이기 */
transform: skewX(10deg);

/* 조합 */
transform: translateY(-4px) scale(1.02);

호버 효과 예시

.card {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

카드가 살짝 떠오르면서 그림자가 깊어지는 효과. 많은 웹사이트에서 볼 수 있는 클래식한 패턴입니다.

@keyframes: 복잡한 애니메이션

transition은 A→B 두 상태만 처리합니다. 여러 단계가 필요하면 @keyframes를 사용합니다.

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.element {
  animation: fadeIn 0.5s ease-out;
}

여러 단계

@keyframes bounce {
  0%   { transform: translateY(0); }
  40%  { transform: translateY(-20px); }
  60%  { transform: translateY(-10px); }
  80%  { transform: translateY(-5px); }
  100% { transform: translateY(0); }
}

.icon {
  animation: bounce 0.6s ease;
}

animation 속성

animation: name duration timing delay iteration direction fill;

/* 무한 반복 */
animation: spin 1s linear infinite;

/* 2번만 반복 */
animation: shake 0.3s ease 2;

/* 왕복 */
animation: pulse 2s ease-in-out infinite alternate;
속성설명
infinite무한 반복
alternate왕복 (0→100→0→100...)
forwards끝나면 마지막 상태 유지
backwards시작 전에 첫 번째 상태 적용

실전 레시피

로딩 스피너

@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 32px;
  height: 32px;
  border: 3px solid #e2e8f0;
  border-top-color: #2dd4bf;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

펄스 효과

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

.skeleton {
  animation: pulse 1.5s ease-in-out infinite;
  background: #e2e8f0;
  border-radius: 4px;
}

페이지 진입 애니메이션

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card:nth-child(1) { animation: slideUp 0.4s ease-out 0.0s both; }
.card:nth-child(2) { animation: slideUp 0.4s ease-out 0.1s both; }
.card:nth-child(3) { animation: slideUp 0.4s ease-out 0.2s both; }

nth-child로 순차적 딜레이를 주면 카드가 하나씩 올라오는 연출이 됩니다.

성능 최적화

GPU 가속 속성 (빠름)

transform, opacity — 레이아웃을 건드리지 않아서 60fps 유지 가능

CPU 속성 (느림)

width, height, top, left, margin, padding — 리플로우가 발생해서 버벅일 수 있음

규칙: 애니메이션에는 transform과 opacity만 사용하세요.

/* 나쁜 예 */
.box:hover { left: 20px; }

/* 좋은 예 */
.box:hover { transform: translateX(20px); }

prefers-reduced-motion

일부 사용자는 애니메이션이 불편할 수 있습니다 (전정기관 장애 등). 접근성을 위해 이 미디어 쿼리를 추가하세요:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

정리

기능용도문법
transitionA→B 부드러운 전환transition: all 0.2s ease
transform이동/회전/확대transform: translateY(-4px)
@keyframes다단계 애니메이션animation: name 0.5s ease

이 세 가지를 조합하면 전문적인 UI 인터랙션을 만들 수 있습니다.

관련 챌린지로 연습하기

그라데이션 버튼
Lv.2 · 버튼
아이콘 버튼
Lv.2 · 버튼
소프트 버튼
Lv.1 · 버튼
그림자 버튼
Lv.2 · 버튼
← 블로그 목록으로