개인 프로젝트를 진행 중에, 크롬과 사파리 간의 차이로 인해 발생한 이슈를 트러블슈팅한 내용을 기록한다.
사용 스택: React, TypeScript, TailwindCSS, Framer-motion
발단
데스크탑의 개발자 도구에서 본 모바일 화면과 실제 모바일 기기로 본 화면은 차이가 있어서, vercel로 중간 단계에 배포 후 실제 내 핸드폰(아이폰 13pro)으로 반응형이 잘 구현됐는지 살펴보려는데, 시작 화면부터 아래처럼 버튼 컴포넌트가 깜빡였다. 처음엔 인터넷 이슈인줄만 알았는데, 계속 그랬다. 뭔가 이상했다.
나는 윈도우 데스크탑과 맥북 랩탑에서는 브라우저로 크롬을 쓰지만, 모바일에서는 사파리를 쓴다. 컴퓨터를 켜고 맥북 사파리로 확인해도 똑같았다. 브라우저 차이로 인해 발생한 것이다.
그래서 사파리 개발자 도구를 열고 어떤 부분이 변하는 것인지 살펴봤더니, 아래처럼 버튼 컴포넌트의 애니메이션이 끝나고 순간적으로 버튼의 opacity가 변하는 것을 확인할 수 있었다. (아래 개발자 도구에 주목)
전개
그래서 열심히 키워드를 조합해서 구글링을 해보니 아래의 stackoverflow 글을 찾을 수 있었다. (무려 2014년의 글..)
글이 오래된 것을 보니 뭔가 고질적인 문제겠거니 생각이 들었다.
이 글에 따르면, 모든 내용을 세세히 이해하진 못했지만 애플의 iOS나 macOS에서 사용하는 그래픽 및 애니메이션 렌더링 프레임워크인 Core Animation에서 발생하는 문제라고 한다.
사파리는 WebKit 엔진과 macOS의 Core Animation 프레임워크를 사용하여 애니메이션을 렌더링을 하는 것이고, 크롬은 Core Animation을 사용하지 않고 Blink 엔진을 사용하여 렌더링을 하기 때문에 문제가 발생하지 않았던 것이다.
위기
처음엔 stackoverflow의 답글에 있는 것처럼 -webkit-으로 시작하는 다양한 요소들을 넣어서 실험해봤는데 해결이 되지 않았다. 한 개씩도 넣어보고, 뭉텅이로도 넣어보고, 하나씩 빼보면서 조합을 해보기도 하고..
그런데 생각해보니 시작하기 버튼 위에 img나 h1같은 다른 요소들도 framer-motion으로 transition이 발생하는데 아무 문제가 없는 것이다.
비교적 최근인 2023. 7월에 쓰여진 다른 글(아래의 글)에선 시작 opacity를 0이 아니고 0.01처럼 미세하게 낮은 값으로 줘보라는 글도 있었다. 근데 이렇게 해도 해결되지 않았음.
아래는 해당 버튼 컴포넌트의 코드이다.
<motion.header
className="flex flex-col items-center gap-5"
>
<motion.img
src={logo}
className="w-44 lg:h-full"
alt="리그 오브 레전드 로고"
initial={{ opacity: 0, x: -50 }}
animate={{ opacity: 1, x: 0, transition: { duration: 1 } }}
/>
<motion.h1
className="text-gray-100 font-OAGothicExtraBold text-center"
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0, transition: { duration: 1 } }}
>
롤 MBTI 테스트
</motion.h1>
</motion.header>
<motion.button
onClick={() => navigate("/test")}
initial={{ opacity: 0, y: 0 }}
animate={{ opacity: 1, y: 0, transition: { duration: 1, delay: 0.5 } }}
className="lg:text-xl bg-neutral-400 px-6 py-3 rounded-lg hover:bg-neutral-500 transition-all ease-in-out"
>
시작하기
</motion.button>
왜 그럴까 코드를 보면서 계속 고민하다가, button에 tailwind css를 준 요소들 중 transition 관련된 것들부터 싹 다 빼보기로 했다.
결말
버튼 컴포넌트의 transition-all와 ease-in-out 두 클래스를 뺐더니...
바로 해결이 됐다. 🥹
framer motion 컴포넌트의 속성으로 준 transition과 tailwindcss의 transition이 중복되어서 발생한 문제였던걸까?
처음에 button 스타일링 할 때 tailwind 코드를 써놓고 그 이후에 framer-motion 효과를 주었더니 아무 이상이 없는 줄로만 알았던 것이다. (그리고...크롬에선 멀쩡했잖아요..!!!!!!)
이래서 중복 코드와 불필요한 코드를 최대한 덜어내는 것이 중요하다고 하는건가보다!
'✍️ What I Learned > 트러블슈팅' 카테고리의 다른 글
[트러블슈팅] Chrome에서 React framer-motion 애니메이션이 어설프게 작동하는 문제 (0) | 2024.01.29 |
---|---|
[트러블슈팅] Module not found: Error can't resolve '@/app' (0) | 2024.01.18 |
[트러블슈팅] Error: document is not defined (0) | 2023.08.21 |
[트러블슈팅] ReactServerComponentsError (feat. Server Component, Client Component) (0) | 2023.08.20 |
[트러블슈팅] TS17004: Cannot use JSX unless the '--jsx' flag is provided. (0) | 2023.08.01 |