디자이너가 Figma에서 프로토타입을 넘기며 "여기 자연스럽게 ease-out으로 빠져주세요"라고 말할 때, 저는 속으로 이런 생각을 합니다. 그 'ease-out'이 정확히 cubic-bezier(0, 0, 0.58, 1)인지, 아니면 머릿속에 있는 감각적 무언가인지. CSS의 ease, ease-in-out 같은 프리셋 키워드는 편리하지만, 디자이너가 의도한 곡선과 1:1로 매칭되는 경우가 생각보다 드뭅니다. 결국 누군가는 그 커브를 px 단위의 정밀함으로 교정해야 하고, 그 도구는 감(感)이 아니라 수학입니다.
최근 GeekNews에 소개된 애니메이션을 설계하는 방법이라는 글은 이 문제를 정면으로 다룹니다. 핵심 주장은 명쾌합니다: 모든 애니메이션은 그래프이고, 그래프의 모양이 곧 움직임의 느낌을 결정한다. 시간, 스크롤, 마우스 위치 같은 입력에 따라 값이 어떻게 변하는지를 곡선으로 그릴 수 있으면, 그 곡선을 의도대로 조각하는 것이 곧 인터랙션 설계의 본질이라는 것이죠.
베지어 커브의 함정: 두 점이 전부를 결정한다
사실 cubic-bezier는 프론트엔드 개발자라면 매일 쓰는 도구인데, 정작 두 제어점이 곡선을 "자석처럼 끌어당기는" 원리를 수학적으로 이해하고 있는 사람은 많지 않습니다. 저도 솔직히 Chrome DevTools의 이징 에디터를 드래그하면서 "이 정도면 괜찮겠지" 하고 넘긴 적이 한두 번이 아닙니다. 하지만 같은 ease-in이라도 cubic-bezier(0.42, 0, 1, 1)과 cubic-bezier(0.55, 0.055, 0.675, 0.19)는 사용자에게 완전히 다른 인상을 줍니다. 전자는 묵직하게 출발하고, 후자는 살짝 머뭇거리다 밀어내는 느낌이죠. 이 미묘한 차이가 버튼 클릭 피드백의 "찰진 느낌"과 "뭔가 느린 느낌"을 가르는 경계선입니다.
스프링이 베지어를 이기는 순간
사용자 입장에서 정말 어색한 순간은 애니메이션 도중에 방향이 바뀔 때입니다. 모달을 여는 중에 닫기를 누르거나, 드래그 중에 손을 뗐다가 다시 잡거나. 베지어 기반 이징은 시작과 끝이 정해져 있어서, 중간 인터럽트가 발생하면 현재 위치에서 새 애니메이션을 강제로 시작하게 됩니다. 결과는? 뚝 끊기는 점프. 사용자 테스트 히트맵을 보면 이런 지점에서 이탈이 일어납니다.
스프링 물리 모델은 이 문제를 구조적으로 해결합니다. stiffness(복원력)와 damping(감쇠력) 두 파라미터만으로 움직임의 성격을 정의하고, duration이라는 개념 자체가 없습니다. 목표가 바뀌면 현재 속도를 유지한 채 자연스럽게 새 목표를 향해 전환되죠. framer-motion이 spring을 기본 트랜지션 타입으로 채택한 이유가 바로 이것입니다.
value += (target - value) * factor — 한 줄의 마법
그런데 모든 인터랙션에 스프링 라이브러리를 붙일 수는 없습니다. 번들 사이즈를 생각하면요. 커서를 부드럽게 따라가는 커스텀 포인터, 스크롤에 반응하는 프로그레스 바 같은 경우에는 지수적 접근(exponential approach) 한 줄이면 충분합니다. value += (target - value) * 0.1 — 이 한 줄이 매 프레임마다 목표값의 10%씩 좁혀가면서, 라이브러리 임포트 없이도 자연스러운 추종 애니메이션을 만들어냅니다. Lighthouse 점수에 영향 없이 인터랙션 품질을 끌어올리는, 가성비 최고의 수학 도구입니다.
Gemini 3.1 Pro가 바꾸는 디자인-개발 갭
여기서 흥미로운 교차점이 생깁니다. 구글이 최근 출시한 Gemini 3.1 Pro는 코드 기반 애니메이션 생성을 대표 활용 사례로 내세우고 있습니다. 텍스트 프롬프트만으로 웹에 바로 삽입 가능한 애니메이션 SVG를 순수 코드로 생성한다는 건데, ARC-AGI-2 벤치마크에서 77.1%를 기록한 추론 성능을 생각하면 단순 CSS 키프레임을 넘어 베지어 커브 조합이나 상태 전환 로직까지 설계할 수 있는 가능성이 열립니다.
"기획자가 이걸 의도한 건지..." 하고 기획 문서와 Figma 프로토타입 사이에서 의도를 추론하던 작업을, AI가 디자인 토큰과 모션 가이드라인을 입력받아 구간별 이징 함수를 제안하는 방식으로 대체하는 시나리오가 점점 현실적이 되고 있는 겁니다.
실무에서 꺼내 쓸 수 있는 교정 프레임워크
원문이 제시하는 설계 파이프라인은 실무에 바로 적용할 만합니다:
- 의존성 파악 — 이 움직임은 시간 기반인가, 스크롤(값) 기반인가, 클릭(이벤트) 기반인가?
- 도구 선택 — 시간 기반이면 베지어, 실시간 추종이면 지수적 접근, 인터럽트가 잦으면 스프링
- 속성 분리 — 위치·크기·투명도·색상을 독립 트랙으로 쪼개서 각각 다른 이징 적용
- 파이프라이닝 — 순차(stagger), 겹침(overlap), 동시(parallel) 배치 전략 결정
- 양방향 검증 — 나타나는 도중 방향 전환 시 점프 없이 이어지는지 확인
사실 이건 flexbox vs grid 선택처럼 "정답은 없지만 근거 있는 선택"이 필요한 영역입니다. 중요한 건 Figma Dev Mode에서 넘어온 이징 값을 그대로 복사-붙여넣기 하는 게 아니라, 사용자가 실제로 경험할 맥락에 맞게 교정하는 습관입니다.
헤드리스 컴포넌트가 시사하는 것
이 맥락에서 최근 React 생태계의 헤드리스 UI 트렌드도 같은 방향을 가리킵니다. @hasthiya_/headless-comments-react 같은 라이브러리가 "로직은 훅으로, UI는 100% 커스텀"을 분리하듯, 애니메이션 역시 이징 로직(수학 모델)과 렌더링(CSS/JS 구현)을 분리해서 생각해야 합니다. Radix나 Headless UI가 <div> 하나 강제하지 않듯, 인터랙션 설계도 특정 라이브러리의 기본 커브에 종속되면 안 됩니다.
전망: 커브는 코드가 아니라 언어가 된다
Gemini 3.1 Pro의 코드 생성 능력, 스프링 물리 모델의 보편화, 그리고 디자인 토큰 기반 워크플로우의 성숙 — 이 세 흐름이 합류하면, 가까운 미래에 디자이너가 "좀 더 탱글탱글하게"라고 말하면 AI가 stiffness: 180, damping: 12를 제안하고, 프론트엔드 개발자가 Core Web Vitals 영향도를 확인한 뒤 승인하는 협업 루프가 만들어질 수 있습니다.
다만 잊지 말아야 할 것은, 원문이 분명히 지적하듯 코드 애니메이션의 진짜 강점은 사용자 입력에 즉각 반응하는 실시간 인터랙션에 있다는 점입니다. Lottie나 Rive로 대체할 수 있는 영역은 위임하고, 코드로만 가능한 — 스크롤 위치, 마우스 궤적, 디바이스 방향 같은 라이브 입력에 반응하는 — 곡선 설계에 수학적 정밀함을 집중해야 합니다.
결국 cubic-bezier(0.25, 0.1, 0.25, 1)은 출발점이지 답이 아닙니다. 그 네 개의 숫자 뒤에 베지어의 재귀적 선형 보간이 있고, 스프링의 미분 방정식이 있고, atan2의 방향 벡터가 있습니다. 그리고 그 수학을 이해하는 개발자만이 디자이너의 "자연스럽게"를 정말로 자연스럽게 만들 수 있습니다. 여기서 로딩 스켈레톤 대신, 한번 이징 에디터를 열어보는 건 어떨까요?