토스쇼핑 결제 모션 / 2026.05

토스쇼핑 결제모션: 구현 방식 전환과 성능 개선

TL;DR

토스쇼핑 결제 플로우의 밀어서 결제 모션은 처음에 GSAP 기반 Rally timeline으로 구현했어요. 구조 자체가 무질서했던 것은 아니었고, 모션과 책임도 분리해둔 상태였어요.

스테이징에서 저사양 기기 프레임드랍이 발견되면서 문제가 드러났어요. 결제 CTA를 누른 직후 전환 초기의 체감 멈춤이 컸고, 이 문제는 단순히 애니메이션 라이브러리를 바꾸는 것만으로 설명하기 어려웠어요.

그래서 결제 전환 모션을 Framer Motion 기반 state 중심 구조로 재구성하고, 바텀시트 전환 중 몰리던 렌더링 작업을 startTransition으로 분산했어요. 결과적으로 6x CPU throttle 환경에서 300ms 이상 멈춤 발생률을 30/30에서 0/30으로 줄였어요.

문제 정의 Problem

최초 구현은 Rally timeline 기반이었고, 복잡한 모션을 명시적인 timeline으로 제어하기 좋은 구조였어요. 기존에도 바텀시트는 마운트되고 있었는데, 여기에 결제 전환 모션이 더해지면서 저사양 기기에서 렌더링 병목이 드러났어요.

이 이슈는 PR이 머지된 뒤 스테이징에서 다른 버그로 잠시 홀드되던 중에 다른 개발자분이 발견해 제보해주셨어요. 사용자 결제 흐름에서 바로 보이는 전환 모션이라, 짧은 멈춤도 체감 품질에 직접 영향을 줄 수 있었어요.

문제를 “어떤 애니메이션 라이브러리가 더 좋은가”로만 볼 수는 없었어요. 애니메이션 실행 방식, React state 변화, 바텀시트 전환 중 발생하는 렌더링 작업을 함께 봐야 했어요.

접근 방식 Approach

먼저 문제를 클릭 직후 500ms 안에서 일어나는 frame freeze로 좁혀 봤어요. 결제 CTA를 누른 뒤 어느 시점에 프레임이 크게 벌어지는지 확인하고, 그 구간을 모션 실행과 React state 변화, 바텀시트 렌더링 작업으로 나눠서 봤어요.

기존 구현은 모션과 책임이 이미 분리돼 있었기 때문에, 그 경계가 실제 병목인지부터 확인했어요. 모션 자체가 무거운지, 상태 전환 때문에 렌더링 작업이 한꺼번에 몰리는지, 바텀시트 전환이 클릭 직후 작업량을 키우는지 순서대로 분리해서 봤어요.

수정 후에는 같은 6x CPU throttle 조건에서 클릭 직후 500ms 내 최대 frame gap을 다시 봤어요. p50, p95, 300ms 이상 멈춤 발생 횟수를 기준으로 전환 초기의 체감 멈춤이 실제로 줄었는지 비교했어요.

핵심 결정 Decision

GSAP 기반 Rally timeline에서 Framer Motion 기반 state 중심 구현으로 옮겼어요.

Rally timeline은 복잡한 모션을 명시적으로 제어하기 좋았어요. 하지만 이 결제 플로우에서는 state 변화와 렌더링 병목을 함께 다뤄야 했고, timeline 중심 구현만으로는 저사양 기기의 체감 멈춤을 줄이기 어려웠어요. Framer Motion으로 옮긴 건 React state 흐름과 모션 상태를 자연스럽게 맞추기 위해서였어요.

원인을 animation engine만의 문제로 보지도 않았어요. WAAPI의 영향은 생각보다 미미했고, 정작 유의미했던 개선은 바텀시트 전환 중 발생하던 렌더링 작업을 startTransition으로 분산한 데서 나왔어요. 그래서 라이브러리 교체와 React 렌더링 병목 대응을 함께 가져갔어요.

해결 결과 Result

클릭 후 500ms 내 최대 frame gap p50
357.5ms → 241.7ms
클릭 후 500ms 내 최대 frame gap p95
400.5ms → 283.4ms
300ms 이상 멈춤 발생률
30/30 → 0/30runs

6x CPU throttle 환경에서 클릭 직후 500ms 내 peak frame freeze p50을 357.5ms에서 241.7ms로 줄였어요. 약 32.4% 감소였어요. p95도 400.5ms에서 283.4ms로 약 29.2% 줄었어요.

기존 구현에서는 30회 중 30회 모두 300ms 이상 멈췄지만, 재구현 이후에는 30회 중 0회로 줄었어요. 저사양 조건에서 구매 CTA 클릭 직후 전환 초기의 체감 멈춤이 크게 줄었어요.

배운 점 Learning

애니메이션 성능 문제는 라이브러리를 바꾸는 것만으로 해결된다고 보기 어렵다는 걸 배웠어요.

이번 개선도 Framer Motion으로 옮겼기 때문만은 아니었어요. 실제 병목이 어디 있는지 확인하고, 바텀시트 전환 중 blocking이 되는 렌더링 작업을 startTransition으로 분산한 데서 유의미한 개선이 나왔어요.