cubic-bezier 뜻: CSS 이징 함수 숫자 4개의 원리

CSS에서 transition-timing-function에 ease나 ease-in-out 같은 이름을 넣어봤다면, cubic-bezier(0.42, 0, 0.58, 1) 같은 숫자 네 개짜리 표기도 한 번쯤 본 적 있을 겁니다. 이 네 개의 숫자가 정확히 무엇을 뜻하는지 모른 채 어디선가 복사해서 붙여넣기만 하는 경우가 많습니다.
사실 ease·linear·ease-in-out은 전부 같은 수학적 곡선의 서로 다른 값일 뿐입니다. 이 곡선이 무엇을 나타내고, 그중에서도 linear만 유독 뻣뻣하게 느껴지는 이유가 무엇인지 원리부터 짚어보겠습니다.
요약 ① cubic-bezier(x1, y1, x2, y2)의 네 숫자는 시작점(0,0)과 끝점(1,1)을 잇는 3차 베지어 곡선의 두 중간 제어점 좌표입니다. ② x축은 "시간이 얼마나 지났는가", y축은 "애니메이션이 얼마나 진행됐는가"를 뜻하며, 이 곡선의 기울기가 곧 순간 속도입니다. ③ ease·linear·ease-in-out 같은 이름은 전부 이 네 숫자 조합에 붙은 프리셋 이름일 뿐, 별도의 계산 방식이 따로 있는 게 아닙니다.
cubic-bezier(x1, y1, x2, y2) 네 숫자가 가리키는 것
cubic-bezier() 함수 안에 들어가는 x1, y1, x2, y2 이 네 숫자는 3차 베지어 곡선을 그리는 두 개의 제어점 좌표입니다. 곡선의 시작점(0,0)과 끝점(1,1)은 CSS 스펙에서 이미 고정돼 있어서, 실제로 우리가 조절할 수 있는 값은 그 사이에 있는 두 제어점뿐입니다.
그래프의 가로축(x)은 애니메이션이 시작된 뒤 전체 지속시간 중 얼마가 지났는지를 0에서 1 사이 비율로 나타냅니다. 세로축(y)은 그 시점에 애니메이션이 얼마나 진행됐는지, 즉 위치나 크기 같은 값이 시작값과 끝값 사이에서 몇 %까지 옮겨왔는지를 나타냅니다.
x는 시간이 거꾸로 흐를 수 없기 때문에 0과 1 사이로 고정되지만, y는 1을 넘거나 0 아래로 내려갈 수 있습니다. y가 1을 넘는 구간은 목표 지점을 살짝 지나쳤다가 되돌아오는, 튕기는 듯한 움직임을 만들어냅니다.
곡선의 기울기가 곧 체감 속도인 이유
이 곡선에서 특정 지점의 기울기는 그 순간에 애니메이션 값이 얼마나 빠르게 변하고 있는지를 나타냅니다. 기울기가 가파르면 짧은 시간 안에 값이 크게 움직이고, 기울기가 완만하면 시간이 지나도 값이 거의 바뀌지 않습니다.
실제 물체는 정지 상태에서 갑자기 최고 속도로 움직이지 않고, 멈추기 직전에도 갑자기 속도가 0이 되지 않습니다. 서서히 빨라지고 서서히 느려지는 이 과정이 우리 눈에 자연스럽게 보이는 이유입니다.
ease 계열 곡선은 시작과 끝 부근의 기울기를 일부러 완만하게 설계해서 이 가속·감속 구간을 만듭니다. 반대로 시작과 끝의 기울기까지 가팔라지는 곡선을 만들면, 움직임이 튀듯이 급하게 느껴집니다.
linear가 부자연스럽게 느껴지는 이유
linear는 사실 cubic-bezier(0, 0, 1, 1)과 똑같습니다. 두 제어점이 각각 시작점·끝점과 같은 자리에 놓이면서, 곡선 전체가 (0,0)과 (1,1)을 잇는 완전한 직선이 됩니다.
직선은 어느 지점에서든 기울기가 똑같습니다. 즉 애니메이션이 시작되는 순간부터 끝나는 순간까지 속도가 하나도 변하지 않고 일정하게 유지된다는 뜻입니다.
문제는 애니메이션 전후입니다. 정지해 있던 요소가 속도 0에서 갑자기 일정한 속도로 뛰어오르고, 끝날 때도 그 속도를 유지한 채로 갑자기 멈춥니다. 이 순간적인 속도 변화가 눈에는 뚝뚝 끊기는 부자연스러운 움직임으로 보입니다.
ease·ease-in·ease-out·ease-in-out은 사실 이 값 하나일 뿐
브라우저가 기본으로 제공하는 이름 붙은 이징들은 전부 미리 정해둔 cubic-bezier 좌표 하나에 붙은 별명일 뿐입니다. 별도의 계산 방식이 따로 있는 게 아니라, 자주 쓰는 제어점 조합에 이름을 붙여둔 것입니다.
| 이름 | cubic-bezier 값 | 특징 |
|---|---|---|
| linear | (0, 0, 1, 1) | 시작부터 끝까지 속도 일정 |
| ease | (0.25, 0.1, 0.25, 1) | 살짝 빠르게 출발해 서서히 느려짐(기본값) |
| ease-in | (0.42, 0, 1, 1) | 느리게 시작해 점점 빨라지다 끝에서도 속도 유지 |
| ease-out | (0, 0, 0.58, 1) | 빠르게 시작해 점점 느려지다 멈춤 |
| ease-in-out | (0.42, 0, 0.58, 1) | 느리게 시작, 중간에 빨라짐, 다시 느리게 끝남 |
ease-in은 끝 지점 제어점이 (1,1), 즉 끝점과 같은 자리에 있어서 마지막까지 가속이 붙은 채로 끝납니다. 화면 밖으로 사라지는 요소에 자주 쓰이는 이유입니다.
ease-out은 반대로 시작 지점 제어점이 (0,0)과 같은 자리에 있어 처음부터 속도를 내다가 끝에서 서서히 멈춥니다. 화면에 들어와 멈춰 서는 요소에 어울립니다.
손으로 이 곡선을 직접 확인하려면
이 값이 실제로 어떤 움직임을 만드는지 손으로 확인하려면, 3차 베지어 공식에 t를 0부터 1까지 여러 번 대입해 곡선 위의 점을 하나씩 계산하고 그래프 용지에 찍어봐야 합니다.
곡선 모양만 그려서는 부족합니다. 실제 CSS에 적용해서 눈으로 봐야 그 값이 원하는 속도감을 주는지 알 수 있으므로, 값을 조금 바꾸고 브라우저를 새로고침해서 다시 보는 과정을 여러 번 반복해야 합니다.
슬라이더로 곡선을 조정하고 실제 움직임 미리보기와 transition CSS를 바로 복사하는 큐빅 베지어 이징 생성기

도구가 곡선 계산과 움직임 확인을 동시에 보여주는 방식
큐빅 베지어 이징 생성기는 지금까지 설명한 그래프를 눈에 보이는 곡선으로 직접 그려줍니다. 왼쪽 영역에 정사각형 좌표평면과 곡선, 그리고 두 제어점의 위치가 점으로 표시되어 x1·y1·x2·y2 값이 그래프 위 어디에 해당하는지 바로 확인됩니다.
오른쪽 영역에서는 같은 cubic-bezier 값을 실제 CSS transition에 적용한 원과 막대가 반복해서 움직입니다. 이 미리보기는 실제 브라우저 렌더링 그대로이기 때문에, 그래프에서 본 곡선 모양과 화면에서 느껴지는 속도감이 정확히 일치하는지 바로 대조할 수 있습니다.
프리셋과 지속시간으로 곡선을 빠르게 비교하기
ease부터 bounce-ish까지 여덟 개의 프리셋 버튼을 누르면 지금까지 설명한 좌표 값이 슬라이더와 숫자 입력창에 그대로 채워집니다. x1·x2는 0에서 1 사이로 값이 제한되지만 y1·y2는 그 범위를 벗어날 수 있어, back-out처럼 튕기는 곡선도 직접 만들어볼 수 있습니다.
지속시간 슬라이더로 같은 곡선을 다른 속도에서 비교해볼 수 있고, 완성된 값은 transition 한 줄 또는 transition-timing-function 한 줄로 각각 바로 복사할 수 있습니다.
정리
- cubic-bezier(x1, y1, x2, y2)의 네 숫자는 고정된 시작점(0,0)·끝점(1,1) 사이 두 제어점의 좌표입니다.
- 곡선의 기울기는 그 순간의 속도를 뜻하며, 기울기가 완만할수록 느리게, 가파를수록 빠르게 값이 변합니다.
- linear는 cubic-bezier(0, 0, 1, 1), 즉 완전한 직선이라 시작과 끝에서 속도가 갑자기 바뀌어 부자연스럽게 느껴집니다.
- ease·ease-in·ease-out·ease-in-out은 별도의 알고리즘이 아니라 자주 쓰는 좌표값에 붙은 이름일 뿐입니다.
- y값은 1을 넘거나 0 밑으로 내려갈 수 있어, 목표 지점을 지나쳤다 되돌아오는 오버슈트 곡선도 같은 원리로 만들어집니다.
슬라이더로 곡선을 조정하고 실제 움직임 미리보기와 transition CSS를 바로 복사하는 큐빅 베지어 이징 생성기
📖 실제 개발자와 디자이너들이 겪은 3가지 큐빅 베지에(Cubic Bezier) 트러블 사연
단순한 속성 하나가 전체 프로젝트의 완성도를 어떻게 바꿔놓는지, 실제 현업에서 발생했던 생생한 사연들을 통해 CSS 이징(Easing)의 중요성을 살펴보겠습니다.
사연 1: "1995년 윈도우 프로그램 같았던 사이드바의 굴욕"
UI 디자이너 A씨는 야심 차게 설계한 내비게이션 사이드바가 슬라이드되어 들어오는 모션을 구현하면서, 개발자에게 ransition: all 0.3s linear를 요청했습니다. 결과물을 확인한 A씨는 충격에 빠졌습니다. 부드럽게 미끄러지듯 들어오기를 기대했던 사이드바가 마치 고장 난 기계처럼 뻣뻣하고 로봇같이 딱딱하게 움직였기 때문입니다. 처음부터 끝까지 동일한 속도로 움직이는 정속도(Linear) 특성 때문에 나타난 현상이었습니다. 이후 A씨는 애플(Apple) 스타일의 매끄러운 감속 모션인 **cubic-bezier(0.16, 1, 0.3, 1) (Expo Ease-Out)**으로 코드를 단 한 줄 수정했습니다. 그 결과 사이드바는 빠르게 진입한 뒤 목적지에 다다를수록 눈에 띄게 부드럽게 감속하며, 마치 원래 그 자리에 있었던 것처럼 자연스럽게 안착하는 고급스러운 모션으로 완벽하게 탈바꿈했습니다.
사연 2: "40줄의 키프레임 노가다를 1줄로 끝낸 오버슈트(Overshoot) 마법"
모바일 게임 프론트엔드 엔지니어 B씨는 사용자가 레벨을 클리어할 때 화면 중앙에 튀어 오르는 '승리 뱃지' 팝업 애니메이션을 개발 중이었습니다. 뱃지가 튀어 올랐다가 살짝 줄어들며 멈추는 쫀득한(Juicy) 스프링 바운스 느낌을 내기 위해, B씨는 퍼센트 단위로 잘게 쪼갠 40줄짜리 다단계 @keyframes를 작성하며 밤을 새우고 있었습니다. 코드는 지저분해졌고 유지보수는 최악이었습니다. 그러던 중 동료의 조언으로 **cubic-bezier(0.34, 1.56, 0.64, 1)**이라는 마법의 숫자를 알게 되었습니다. $y_1 = 1.56$처럼 y 좌표가 1.0을 초과하게 설정하자, 요소가 목표 크기를(100%) 잠시 넘어섰다가 다시 100%로 돌아오는 완벽한 탄성 바운스가 만들어졌습니다. 40줄의 복잡했던 키프레임 코드는 단 한 줄의 ransition 속성으로 우아하게 정리되었습니다.
사연 3: "사용자의 눈을 혹사시킨 끔찍한 데이터 대시보드"
데이터 시각화 엔지니어 C씨는 실시간으로 값이 업데이트되는 인터랙티브 막대그래프 대시보드를 구축했습니다. 요소가 바뀔 때마다 극적인 효과를 주고자 ease-in 이징을 적용했습니다. 하지만 대시보드를 하루 종일 쳐다봐야 하는 실무진들로부터 "눈이 너무 피로하고 그래프가 공격적으로 느껴진다"는 클레임이 쏟아졌습니다. ease-in은 서서히 출발하여 도착 순간에 최고 속도로 돌진하다가 벽에 부딪히듯 급정거(Hard Stop)하는 곡선이기 때문이었습니다. C씨는 즉시 모든 트랜지션을 **ease-out (cubic-bezier(0, 0, 0.2, 1))**으로 교체했습니다. 그래프는 빠르게 갱신된 후 도착지점에서 부드럽게 멈춰 섰고, 눈의 피로도는 획기적으로 줄어들었으며 대시보드는 한결 차분하고 전문적인 느낌을 주게 되었습니다.
🔬 핵심 기술 메커니즘: 3차 매개변수 베지에 방정식과 물리학
웹 브라우저가 CSS의 네 숫자(x1, y1, x2, y2)를 받아 어떻게 60fps의 부드러운 애니메이션을 그려내는지, 그 수학적 메커니즘을 심층 해부해보겠습니다.
1. 3차 매개변수 베지에 방정식 (3rd-Order Parametric Bézier Equation)
브라우저가 사용하는 곡선은 시간 $t$ ($0 le t le 1$)를 매개변수로 하는 3차 베지에 곡선(Cubic Bézier Curve)입니다. 기본 수학 공식은 다음과 같습니다.
$$B(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t) t^2 P_2 + t^3 P_3 quad (t in [0, 1])$$
CSS 트랜지션에서는 시작점 $P_0(0,0)$와 끝점 $P_3(1,1)$이 항상 고정되어 있습니다. 따라서 이 값을 공식에 대입하여 정리하면, 시간 $X$와 진행률 $Y$를 분리된 매개변수 방정식으로 나타낼 수 있습니다.
$$X(t) = 3(1-t)^2 t x_1 + 3(1-t) t^2 x_2 + t^3$$ $$Y(t) = 3(1-t)^2 t y_1 + 3(1-t) t^2 y_2 + t^3$$
여기서 우리가 CSS에 입력하는 값이 바로 제어점 $P_1(x_1, y_1)$과 $P_2(x_2, y_2)$입니다.
2. 뉴턴-랩슨 반복법을 통한 시간 매핑 (Time Mapping with Newton-Raphson)
개발자에게 주어지는 것은 "현재 애니메이션이 전체 시간의 몇 %를 지났는가"를 뜻하는 $X$값(시간 분율)입니다. 그러나 브라우저가 애니메이션의 현재 진행률 $Y$를 구하려면 먼저 보이지 않는 매개변수 $t$를 찾아야 합니다. 하지만 $X(t)$ 방정식은 $t$에 대한 3차 방정식이므로 역함수를 구하기가 매우 까다롭습니다. 따라서 최신 브라우저 엔진(크롬 V8, 사파리 WebKit 등)은 뉴턴-랩슨(Newton-Raphson) 수치 해석 알고리즘을 사용합니다. 특정 시간 $X$가 주어졌을 때 이와 일치하는 $t$값을 빠르게 근사치로 역산해내고, 그 $t$를 다시 $Y(t)$ 공식에 대입하여 최종 화면에 렌더링될 속성값을 도출해내는 고도의 연산을 초당 60회 이상 수행합니다.
3. 미분, 순간 기울기와 속도의 물리 (Derivative & Instantaneous Velocity)
애니메이션의 체감 속도는 이 곡선의 순간 기울기, 즉 미분값($rac{dY}{dX}$)으로 결정됩니다.
- 기울기($rac{dY/dt}{dX/dt}$): 매개변수 $t$에 대한 $Y$의 변화율을 $X$의 변화율로 나눈 값입니다.
- 곡선이 가파르다(Steep) = 기울기가 크다 = 짧은 시간 안에 값이 크게 변함 = 초고속 이동
- 곡선이 완만하다(Flat) = 기울기가 작다 = 시간이 흘러도 값이 거의 안 변함 = 정지(Standstill)에 가까운 감속
4. 오버슈트 물리학 (Overshoot Physics: $y > 1.0$ or $y < 0.0$)
정상적인 범위 $[0, 1]$을 벗어난 Y 제어점은 튕김(Bounce)과 탄성(Elastic) 물리를 시뮬레이션합니다.
- $y_1$이나 $y_2$가 1.0을 초과하면, $Y(t)$ 곡선은 1.0(최종 목적지) 선을 뚫고 올라갔다가 다시 1.0으로 내려옵니다. 사용자의 눈에는 물체가 목적지를 휙 지나쳐서(Overshoot) 부풀어 올랐다가 제자리로 통통 튕기며 돌아오는 것처럼 보입니다.
- 주의사항: Y값은 자유롭게 한계를 벗어날 수 있지만, $x_1, x_2$는 반드시 $0$과 $1$ 사이의 값만 가져야 합니다. X축은 '시간'을 의미하며, 아인슈타인의 상대성 이론이 적용되지 않는 웹 브라우저에서 시간은 거꾸로 흐를 수 없기 때문입니다. X값이 범위를 벗어나면 브라우저는 해당 CSS 선언 전체를 무효화(Invalid) 처리합니다.
📊 CSS 이징(Easing) 함수 스펙트럼 비교 분석 매트릭스
각 모션의 특성과 적합한 사용처를 한눈에 파악할 수 있는 종합 비교표입니다.
| 이징 타입 | 수학적 좌표 / 프리셋 | 가속 및 감속 프로필 (Acceleration Profile) | 추천하는 이상적인 UI 역할 | 시각적 성격 (Personality) | 눈 피로도 위험 (Eye Strain) |
|---|---|---|---|---|---|
| Linear (선형) | cubic-bezier(0, 0, 1, 1) | 시작부터 끝까지 가속/감속 제로 (정속도) | 무한 루프 스피너(로딩 애니메이션), 색상 변경 | 뻣뻣함, 기계적임, 로봇 같음 | 중간 (단순 반복시 낮음) |
| Standard (표준) | ease (0.25, 0.1, 0.25, 1) | 부드럽게 출발 $ | |||
| ightarrow$ 가속 $ | |||||
| ightarrow$ 길고 부드러운 감속 | 모바일 앱의 일반적인 화면 전환, 패널 이동 | 무난함, 보편적, 예측 가능함 | 낮음 | ||
| Ease-In (가속) | cubic-bezier(0.42, 0, 1, 1) | 정지 상태에서 출발 $ | |||
| ightarrow$ 끝날 때 최고 속도 도달 | **화면 밖으로 퇴장(Exit)**하는 모달이나 알림 | 날카로움, 긴급함, 단호함 | 매우 높음 (진입 시 사용 금지) | ||
| Ease-Out (감속) | cubic-bezier(0, 0, 0.58, 1) | 진입 시 이미 최고 속도 $ | |||
| ightarrow$ 부드럽게 감속하며 정차 | **화면 안으로 진입(Enter)**하는 사이드바, 팝업 | 안정감, 친절함, 세련됨 | 매우 낮음 (가장 편안함) | ||
| Ease-In-Out | cubic-bezier(0.42, 0, 0.58, 1) | 느린 출발 $ | |||
| ightarrow$ 중간 가속 $ | |||||
| ightarrow$ 느린 정차 (대칭) | 화면 내부에서의 크기 변화, 호버(Hover) 상태 | 묵직함, 여유로움, 부드러움 | 낮음 | ||
| Custom Expo | cubic-bezier(0.16, 1, 0.3, 1) | 폭발적인 진입 속도 $ | |||
| ightarrow$ 극도로 부드럽고 긴 감속 | 애플리케이션의 핵심 UI 컴포넌트 등장 모션 | 스내피(Snappy), 텐션 높음, 현대적 | 낮음 | ||
| Overshoot | cubic-bezier(0.34, 1.56, 0.64, 1) | 100%를 초과하여 팽창 $ | |||
| ightarrow$ 탄성력으로 100% 복귀 | 성공 뱃지, 강조 알림, 좋아요(Heart) 버튼 | 유쾌함(Playful), 쫀득함(Juicy) | 중간 (남용 시 산만해짐) |
⚠️ 절대 피해야 할 5가지 큐빅 베지에 애니메이션 실수
- X 제어점을 0~1 밖으로 설정하는 치명적 오류: cubic-bezier(1.2, 0, -0.2, 1)처럼 X축(시간) 제어점을 1보다 크게, 또는 0보다 작게 입력하면 해당 CSS 문장 전체가 파싱 에러로 무시됩니다. 시간 여행은 불가능합니다!
- 진입(Entering) UI에 ease-in 사용하기: 요소가 나타날 때 ease-in을 쓰면 도착지점에 다다랐을 때 최고 속도를 찍고 급정거(Hard Stop)하게 됩니다. 이는 시각적 충돌을 일으키며 사용자에게 큰 스트레스를 줍니다.
- UI 공간 이동에 linear 남용하기: 사이드바, 모달, 드롭다운 등이 선형으로 움직이면 현실 세계의 물리 법칙(관성, 마찰력)을 위배하기 때문에 뇌가 무의식적으로 "어색하고 저렴한 소프트웨어"라고 판단하게 됩니다.
- 과도한 오버슈트(y > 2.0)로 인한 레이아웃 클리핑(Clipping): 탄성을 주겠다고 Y값을 너무 크게 잡으면, 요소가 컨테이너 밖으로 심하게 이탈하며 overflow: hidden에 의해 잘려 나가는(Clipping) 시각적 버그가 발생합니다.
- 긴 지속시간(>500ms)과 가파른 곡선의 잘못된 만남: 0.5초가 넘어가는 긴 애니메이션에 초반 가속이 심한 곡선을 물리면, 사용자는 입력 피드백이 즉각적이지 않다고 느껴 앱이 "버벅거린다(Sluggish)"고 착각하게 됩니다.
💡 5단계 직관적인 큐빅 베지에 곡선 설계 워크플로우
감에 의존하지 않고 수학적으로 완벽한 모션을 설계하는 실전 5단계 가이드입니다.
- 1단계: 인터랙션 의도(Intent) 정의하기 $ ightarrow$ 이 요소가 화면에 진입하는가(Entering), 퇴장하는가(Exiting), 단순히 강조되는가(Emphasizing), 아니면 중립적인 상태 변화인가?
- 2단계: 베이스라인 프리셋 선택하기 $ ightarrow$ 진입 모션이라면 Ease-Out, 퇴장 모션이라면 Ease-In, 호버 모션이라면 Ease-In-Out을 기초 뼈대로 잡습니다.
- 3단계: 시각적 도구로 핸들 조율하기 $ ightarrow$ 본 페이지에서 제공하는 큐빅 베지에 이징 생성기에서 $P_1(x_1, y_1)$과 $P_2(x_2, y_2)$ 제어점 핸들을 드래그하며 곡선의 기울기(가속도)를 조율합니다.
- 4단계: 실제 UI 스케일로 테스트하기 $ ightarrow$ 작은 원형 그래프로는 완벽해 보여도, 300px을 이동하는 모달 창이나 1.2배로 커지는 버튼에서는 느낌이 다를 수 있습니다. 실제 크기에 근접하게 도구에서 확인합니다.
- 5단계: 지속시간(Duration) 마이크로튜닝 $ ightarrow$ 곡선이 완성되면 ransition-duration을 $150sim 300 ext{ms}$ 사이에서 미세 조정합니다. 곡선이 가파를수록 시간은 짧아야 쾌적합니다.
🔍 모션 디자이너가 숨기는 7가지 애니메이션 곡선 꿀팁
- 애플 감성의 모던 진입 모션: cubic-bezier(0.16, 1, 0.3, 1) (Expo Ease-Out)을 사용하면 엄청나게 빠릿하고(Snappy) 고급스러운 다이얼로그나 드로어(Drawer) 진입 애니메이션을 완성할 수 있습니다.
- 순식간에 사라지는 닌자 퇴장 모션: cubic-bezier(0.7, 0, 0.84, 0) 곡선은 화면에서 요소를 답답함 없이 신속하고 단호하게 치워버리고 싶을 때 최고의 선택입니다.
- 유쾌하고 발랄한 바운스 알림: cubic-bezier(0.34, 1.56, 0.64, 1)을 적용하여 뱃지나 툴팁이 통통 튀며 등장하도록 만들어 사용자에게 기분 좋은 피드백을 제공하세요.
- 퇴장(Exit)은 진입(Enter)보다 30% 빠르게: 진입할 때 300ms가 걸렸다면, 퇴장할 때는 200ms 이하로 설정하세요. 사용자는 한 번 확인한 요소가 사라지는 것을 기다려주지 않습니다.
- 풀스크린 모달에 오버슈트 금지: 전체 화면을 덮는 거대한 오버레이에 탄성(y > 1.0)을 주면 사용자가 멀미를 느낄 수 있습니다. 작은 요소에만 바운스를 적용하세요.
- 하드웨어 가속(will-change: transform)과 결합하기: 아무리 훌륭한 곡선을 짜더라도 margin이나 width를 애니메이션하면 뚝뚝 끊깁니다. 부드러운 베지에 곡선의 효과를 100% 보려면 반드시 ransform 속성과 함께 사용하세요.
- 실시간 웹 생성기로 곡선 검증 생활화: 본문에 제공된 시각화 툴을 북마크해두고, 코딩 전에 눈으로 먼저 속도감을 확인하는 습관을 들이세요.
🎯 실전 모션 결정 트리 (Decision Tree): 내게 필요한 곡선은?
상황에 맞는 최적의 곡선을 5초 만에 결정할 수 있는 가이드라인입니다.
- 요소가 화면 바깥에서 안으로 등장합니까? (Entering)
- $ ightarrow$ Yes: Ease-Out 계열을 사용하세요. (빨리 들어와서 천천히 멈춤)
- 요소가 화면 안에서 바깥으로 완전히 사라집니까? (Exiting)
- $ ightarrow$ Yes: Ease-In 계열을 사용하세요. (천천히 출발해서 쏜살같이 사라짐)
- 사용자의 마우스 호버(Hover)에 반응하여 색상/크기가 바뀝니까?
- $ ightarrow$ Yes: Ease-In-Out 또는 Ease를 사용하여 앞뒤가 대칭적이고 부드러운 느낌을 주세요.
- 목표를 달성했거나 시선을 확 끌어야 하는 강조 알림입니까?
- $ ightarrow$ Yes: Y값이 1을 초과하는 Overshoot (Spring) 곡선으로 탄력적인 바운스를 적용하세요.
- 데이터 차트가 로딩되거나 무한 회전하는 스피너입니까?
- $ ightarrow$ Yes: Linear를 사용하여 기계적이고 오차 없는 정속도를 유지하세요.
📑 전문가를 위한 필수 용어 치트시트
- 큐빅 베지에 (Cubic Bézier Curve): 4개의 제어점($P_0, P_1, P_2, P_3$)으로 형태가 결정되는 3차 다항식 곡선. 웹 애니메이션의 근간이 되는 수학적 모델.
- 제어점 (Control Points: $P_1, P_2$): 시작점과 끝점 사이에서 곡선의 모양(기울기)을 팽팽하게 당겨주는 자석 같은 역할을 하는 좌표. 우리가 cubic-bezier() 함수에 입력하는 4개의 숫자(x1, y1, x2, y2).
- 매개변수 곡선 (Parametric Curve): $y=f(x)$ 형태가 아닌, 숨겨진 변수 $t$를 이용해 $X(t), Y(t)$ 형태로 위치를 표현하는 수학적 방식.
- 뉴턴-랩슨 반복법 (Newton-Raphson Method): 주어진 시간 $X$값으로부터 매개변수 $t$를 고속으로 역산해내기 위해 브라우저 엔진이 사용하는 수치 해석적 근사 알고리즘.
- 순간 가속도 / 기울기 (Instantaneous Velocity / Slope): 특정 지점에서 곡선의 접선이 가지는 기울기. 기울기가 가파를수록 화면 속 요소는 더 빠른 속도로 움직입니다.
- 오버슈트 (Overshoot / Spring Physics): 애니메이션 진행률(Y축)이 일시적으로 100%(1.0)를 초과하여 최종 목적지를 지나쳤다가 다시 돌아오는 탄성 현상.
- 이즈인 / 이즈아웃 (Ease-In / Ease-Out): 가속(In)과 감속(Out)을 지칭하는 용어. Ease-In은 점점 빨라지는 모션, Ease-Out은 점점 느려지는 모션을 뜻합니다.
- 시간 분율 (Time Fraction): 전체 애니메이션 재생 시간 중 현재 흘러간 시간의 비율(0.0 ~ 1.0). X축을 구성합니다.
자주 묻는 질문
단순한 사용법을 넘어, 원리를 깊이 파고들고 싶은 개발자들을 위한 심화 문답입니다.
Q1. X 좌표(시간)는 0~1 사이로 제한되는데, 왜 Y 좌표(진행률)는 1을 넘거나 음수가 될 수 있나요?
A1. X축은 절대적인 물리 법칙인 **'시간의 흐름(Time Fraction)'**을 의미하기 때문입니다. 애니메이션이 3초짜리라면, 1.5초 지점은 정확히 $x=0.5$에 대응됩니다. 브라우저 엔진 입장에서 시간이 역행($x < 0$)하거나 정해진 지속시간보다 긴 미래($x > 1$)로 점프하는 것은 논리적으로 불가능합니다. 반면 Y축은 **'요소의 상태 변화량(Progress)'**을 의미합니다. 크기가 0px에서 100px로 커지는 애니메이션일 때, $y=1.2$가 된다는 것은 일시적으로 120px까지 팽창한다는 뜻입니다. 물체가 목표 지점을 지나쳐서 더 이동하는 것은 현실 세계의 탄성력이나 관성(Inertia)으로 쉽게 설명되며, 이것이 바로 역동적인 바운스(오버슈트)를 만들어내는 핵심 원리입니다.
Q2. Linear(정속도) 애니메이션이 유독 사람 눈에 부자연스럽고 뻣뻣하게 느껴지는 과학적 이유가 무엇인가요?
A2. 현실 세계의 물리 법칙 때문입니다. 우리 뇌는 평생 동안 중력, 마찰력, 관성의 지배를 받는 물체들의 움직임만을 보고 자랐습니다. 현실의 어떤 자동차도 정지 상태에서 0.001초 만에 시속 100km/h로 순간이동하지 않으며, 정지할 때도 브레이크를 밟아 서서히 감속합니다. 반면 Linear 모션은 질량과 관성이 '0'인 상태에서만 가능한 움직임입니다. 속도 0에서 갑자기 최고 속도로 뛰쳐나가고, 끝날 때도 돌처럼 굳어버리듯 멈춥니다. 뇌는 이러한 '비현실적인 즉각적 가속/감속 부재'를 인지하고 무의식적으로 이 움직임을 인공적이고(Robotic), 저렴하며(Cheap), 버그가 있는 기계적인 움직임으로 처리해버리기 때문에 뻣뻣함을 느끼는 것입니다.
Q3. 브라우저는 시간 $X$를 가지고 어떻게 현재 화면의 위치 $Y$를 계산해내나요?
A3. 이 과정은 매우 고도화된 연산을 거칩니다. CSS 엔진은 $X(t)$ 공식을 통해 현재 경과된 시간 분율을 매개변수 $t$와 맞물려야 합니다.
- 브라우저는 현재 경과된 시간 $X$(예: 0.3)를 확인합니다.
- 3차 방정식 $X(t) = 0.3$을 만족하는 $t$를 찾아야 하는데 역함수가 없으므로, 뉴턴-랩슨(Newton-Raphson) 수치 해석법을 동원하여 접선의 방정식을 반복 수행하며 $t$의 근사치를 초고속으로 추정해냅니다.
- 계산된 매개변수 $t$를 다시 3차 방정식 $Y(t)$에 대입하여 최종적인 진행률(예: 0.15)을 얻습니다.
- 이 연산을 초당 60프레임(16.6ms) 간격으로 쉴 새 없이 반복하여 화면의 픽셀 좌표를 업데이트하는 것이 바로 우리가 보는 부드러운 하드웨어 가속 애니메이션의 실체입니다.
