토스쇼핑 결제 모션 / 2026.05
토스쇼핑 결제모션: WebKit 레이어 순서 문제 대응
TL;DR
토스쇼핑 결제모션의 밀어서 결제 버튼에서 WebKit 환경에서만 그라디언트 레이어가 핸들 위로 올라오는 문제가 있었어요.
CSS상으로는 그라디언트가 z-index 1, 핸들이 z-index 100이라 핸들이 위에 있어야 했어요. 하지만 Safari/WKWebView에서는 애니메이션 시작 직후 약 0.73초 동안 의도와 다르게 그려졌어요.
z-index 숫자를 더 키우는 대신 두 요소의 transform 갱신 경로와 WebKit의 layer 처리 시점이 영향을 줬을 가능성을 살펴봤어요. 내부 동작을 원인으로 단정하지 않고, 문제가 생긴 핸들에만 will-change: transform을 적용했어요.
문제 정의 Problem
밀어서 결제 버튼은 그라디언트, 배경, 결제 중 오버레이, 핸들이 겹쳐 있는 구조였어요. 이 중 그라디언트는 뒤에서 흐르고 핸들은 항상 그 위에 보여야 했어요.
그런데 Safari/WKWebView 같은 WebKit 환경에서만 애니메이션 시작 직후 약 0.73초 동안 그라디언트가 핸들 앞에 보였어요. Chrome·Firefox와 모션이 없는 정지 상태에서는 재현되지 않았어요.
결제 CTA에서 직접 보이는 모션이라, 짧은 순간이라도 레이어 순서가 뒤집히면 사용자가 느끼는 완성도가 크게 떨어질 수 있었어요. CSS의 z-index 값은 이미 의도대로 설정돼 있었기 때문에, 숫자를 더 키우기보다 애니메이션 중 브라우저의 layer 처리 방식이 영향을 주는지도 살펴봤어요.
접근 방식 Approach
두 레이어의 transform 갱신 경로가 서로 다르다는 점에 집중했어요.
z-index 값 자체는 의도대로였기 때문에 stacking context를 더 쌓기보다 transform animation과 compositor layer 처리 시점을 살펴봤어요. 애니메이션 중인 그라디언트와 초기값이 translateX(0px)인 핸들이 서로 다른 시점에 layer로 다뤄지는 것이 증상에 영향을 줬을 가능성이 있다고 봤어요.
핸들에 will-change: transform을 추가해 브라우저가 transform 변경을 미리 고려하도록 했어요. 원인을 확정하기보다 이 변경 뒤 같은 증상이 사라지는지 확인했어요.
핵심 결정 Decision
z-index를 조정하기보다 문제가 생긴 핸들의 transform 처리 조건만 바꿨어요.
wrapper에는 이미 isolation: isolate가 적용돼 있었고 z-index 값도 의도대로였어요. 그래서 stacking context를 더 바꾸기보다, 핸들에 will-change: transform만 적용한 뒤 같은 재현 조건에서 결과를 확인했어요.
다만 will-change는 GPU 메모리를 쓸 수 있어서 넓게 적용하지 않았어요. 문제가 생긴 핸들에만 제한적으로 사용했어요.
해결 결과 Result
수정 뒤 Safari/WKWebView에서도 밀어서 결제 버튼의 그라디언트가 핸들 뒤로 지나갔고, 레이어 순서가 뒤집히는 증상이 재현되지 않았어요.
레이어 구조나 z-index 값을 더 손대지 않고, 문제가 생긴 요소 하나에만 변경을 제한했어요. 확인한 것은 이 변경 뒤 증상이 재현되지 않았다는 결과이며, WebKit 내부의 어떤 처리 과정이 원인이었는지까지 확정한 것은 아니에요.
배운 점 Learning
겉으로 드러난 z-index 수치가 정상이어도, transform 갱신 경로가 다른 요소가 겹치면 브라우저의 layer 처리 방식도 원인 후보로 살펴봐야 한다는 걸 배웠어요.
다음에 비슷한 증상을 보면 z-index 값만 키우기 전에, 브라우저별 재현 조건과 각 요소의 transform 갱신 경로부터 좁혀보려고 해요.