티스토리 뷰

로그인 기능을 구현하다가 예상치 못한 문제가 하나 생겼다.
로그인은 정상적으로 성공했고, 상태도 잘 저장되었지만 router.push()가 작동하지 않았다. 상태 저장도 되고, 콘솔에도 데이터가 잘 찍히는데 페이지 이동이 일어나지 않았다.

문제 상황

- 로그인 API 요청을 보낸 뒤, 응답으로 받은 사용자 정보를 Zustand에 저장하고 그 직후 router.push()를 호출했는데 페이지가 이동하지 않았다.

- 아무런 에러도 없고, 상태도 잘 저장되었는데 라우팅만 반응이 없었다.

재현 조건

- 상태 저장 없이 router.push()만 실행하면 잘 작동했다.
-상태 저장을 한 다음 줄에 라우팅 코드를 넣으면 작동하지 않았다.
 >> 상태 저장과 라우팅이 한 번에 일어날 때 문제가 발생했다.

검색

1. router.push가 항상 동작하지는 않음

먼저 Next.js의 router.push()가 어떤 조건에서 실패할 수 있는지 찾아봤다. 공식 문서를 보니 이런 문장이 있었다.

If you're attempting to access the router or trigger a navigation action (router.push) before hydration, it may be skipped or fail silently.
(출처: Next.js Router Docs)

클라이언트에서 hydration이 끝나기 전에 router.push()를 호출하면, 아무 반응 없이 무시될 수도 있다는 얘기.
여기서 ‘타이밍 문제’라는 키워드가 머릿속에 떠올랐다. 혹시 상태가 완전히 반영되기 전에 라우팅을 시도하고 있는 건 아닐까?

2: Zustand 상태도 즉시 반영되지 않을 수 있음

Zustand는 상태 저장을 비동기로 처리할 수 있다. 특히 나는 persist 미들웨어를 사용하고 있었는데, 이 경우 상태가 로컬 스토리지에서 복원(hydration)되기까지 시간이 걸린다고 한다.

공식 문서에서도 : 

Zustand is asynchronous and can delay hydration, which can cause UI to render with incomplete state.
(출처: Zustand Persisting Store Data)

상태 저장은 되지만 그 값이 렌더링되기까지 시간이 걸릴 수 있고, hydration이 끝나기 전에는 상태를 읽었을 때 undefined가 나올 수도 있다는 뜻.

해결 방법 1: onSuccess에서 라우팅 처리

React Query를 사용하고 있어서, login 함수가 성공했을 때 실행되는 onSuccess 안에서 상태 저장과 라우팅을 함께 처리해봤다. 이렇게 하면 상태 저장 → 라우팅 순서를 명확히 보장할 수 있어서 타이밍 이슈를 줄일 수 있다.

이 방식으로 처리한 이후에는 라우팅이 잘 작동했다.

해결 방법 2: hydration 여부를 체크하고 라우팅

만약 상태가 persist 되어 있고, 페이지를 새로고침한 뒤에도 라우팅이 필요하다면, hydration이 끝났는지 먼저 확인하는 게 좋다.
급하게 해결해서 집에 가서 공식문서를 찬찬히 읽어 봤는데, 공식 문서에서는 hasHydrated를 추천하고 있었다.

onRehydrateStorage: () => (state) => { state?.setHasHydrated(true); };

 

그리고 컴포넌트 안에서는 아래처럼 hydration 완료 여부를 감지해서 라우팅을 시도할 수 있다.

useEffect(() => { if (authStore.hasHydrated && authStore.accessToken && authStore.role) { router.push(`/content-management/${authStore.role}`); } }, [authStore.hasHydrated, authStore.accessToken, authStore.role]);

이 방식은 특히 로그인 상태가 persist된 경우(예: 새로고침 이후)에도 안전하게 라우팅할 수 있어서 유용할 듯.

정리

Zustand와 Next.js를 같이 사용할 때는 상태 저장 이후의 비동기 타이밍에 특히 주의할 필요가 있다.
persist 미들웨어를 쓰고 있다면 상태가 완전히 복원되기 전에 라우팅을 시도하면 문제가 생길 수 있다.

React Query의 onSuccess를 활용해 상태 저장 후 라우팅 순서를 보장하거나, hasHydrated를 이용해 hydration 완료 여부를 확인한 뒤 라우팅하는 방식으로 해결할 수 있다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함