# Vue 반응성 시스템과 TanStack Query 충돌로 인한 무한 루프 에러 해결
Nuxt 배포(Vercel) 환경에서 페이지 진입 시 'Maximum call stack size exceeded' 에러와 함께 브라우저가 멈추는 무한 루프 현상이 발생했습니다. 로컬 개발 환경에서는 발생하지 않아 이전 배포 이력을 트래킹한 결과, TanStack Query의 useMutation 훅 추가 이후 발생한 문제임을 확인했습니다.
문제의 핵심은 useMutation의 mutationKey에 Pinia의 반응형 객체(store)를 통째로 전달한 것에 있었습니다. Vue의 반응성 시스템이 store를 읽는 순간 이를 종속성으로 등록(track)하고, 평가와 렌더링이 반복되며 무한 루프(trigger)를 유발한 것입니다. 이를 해결하기 위해 mutationKey에 반응형 객체를 직접 넣지 않고, store.businessNumber, store.category와 같이 원시값(Primitive Type)으로 해체 및 구조 분해하여 전달하는 방식으로 코드를 전면 수정했습니다.
✨ 개선 결과
- mutationKey에 Pinia Store(반응형 객체) 대신 원시값을 명시적으로 전달함으로써, 불필요한 재렌더링과 track/trigger 무한 루프 고리를 완벽하게 끊어냈습니다.
- 로컬 환경에서는 감춰져 있던 문제를 배포 환경(Vercel)의 엄격한 평가 타이밍에서 발견하고 트래킹하여, 사용자가 직면할 수 있는 크리티컬한 에러(브라우저 멈춤 현상)를 조기에 차단했습니다.
Before
무한 루프 (브라우저 다운)
After
정상 렌더링
- • Vue의 반응성 시스템(Reactivity)이 어떻게 동작(track/trigger)하는지, 그리고 Proxy 객체가 렌더링에 미치는 영향을 깊이 이해하게 되었습니다.
- • TanStack Query가 내부적으로 키(Key)를 기반으로 상태를 관리하는 원리를 파악하고, 프레임워크와 외부 라이브러리를 혼용할 때 발생할 수 있는 라이프사이클 충돌 문제를 경험했습니다.
- • 단순히 동작하는 코드를 짜는 것을 넘어, 상태 관리 도구(Pinia, React Query 등)의 내부 동작 방식을 정확히 알고 원시값과 참조값을 구분하여 사용해야 함을 체감했습니다.









