Conversation
Walkthrough이번 변경사항은 로그인 불안정성 문제를 추적하고 디버깅하기 위한 기반 시설을 구축하는 작업입니다:
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/src/lib/zustand/useAuthStore.ts`:
- Around line 123-131: In onRehydrateStorage, avoid mutating the incoming state
directly; instead update the store via its actions or setState so subscribers
are notified: call the existing action(s) (e.g.,
setUserRole(parseUserRoleFromToken(state.accessToken)) and setInitialized(true))
or invoke store.setState({ userRole: parseUserRoleFromToken(state.accessToken),
isInitialized: true }) rather than assigning to
state.userRole/state.isInitialized directly; keep the authDebugLog call but
perform updates through setUserRole/setInitialized or store.setState to ensure
Zustand notifies subscribers.
In `@apps/web/src/utils/authDebug.ts`:
- Around line 41-43: The in-memory window.__AUTH_DEBUG_LOGS__ is lost on
full-page navigations (e.g., redirectToLogin in axiosInstance.ts); modify
apps/web/src/utils/authDebug.ts to mirror the last N events into sessionStorage
and restore them on module initialization: on every push to
window.__AUTH_DEBUG_LOGS__ write a truncated JSON array (limit N) to a fixed
sessionStorage key (e.g., "__AUTH_DEBUG_LOGS_SESSION__"), and when the module
loads, hydrate window.__AUTH_DEBUG_LOGS__ from that sessionStorage key if
present; ensure serialization/deserialization with try/catch to avoid exceptions
and keep the same push logic so existing callers need no change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 356f9cf0-35d4-4f81-bb55-3721e3286c74
📒 Files selected for processing (5)
apps/web/LOGIN_INSTABILITY_INVESTIGATION.mdapps/web/src/lib/zustand/useAuthStore.tsapps/web/src/middleware.tsapps/web/src/utils/authDebug.tsapps/web/src/utils/axiosInstance.ts
| onRehydrateStorage: () => (state) => { | ||
| // hydration 완료 후 isInitialized를 true로 설정 | ||
| if (state) { | ||
| authDebugLog("store.rehydrate.complete", { | ||
| hasToken: !!state.accessToken, | ||
| isAuthenticated: state.isAuthenticated, | ||
| }); | ||
| state.userRole = parseUserRoleFromToken(state.accessToken); | ||
| state.isInitialized = true; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Zustand persist middleware, does mutating statedirectly insideonRehydrateStoragenotify subscribers, or shouldsetState / store actions be used instead?
💡 Result:
Directly mutating the state object you receive in onRehydrateStorage will not notify Zustand subscribers. Zustand only notifies subscribers when the store’s setState runs (it updates the internal state reference and then calls all listeners.forEach(...)).[1]
So inside onRehydrateStorage, you should update via store actions (which call set) or call store.setState(...)—not by mutating state in-place.[2][3]
Sources:
[1] Zustand core setState implementation calls listeners only from setState (src/vanilla.ts) (github.com)
[2] Persist middleware describes onRehydrateStorage as a hook for custom logic around rehydration (zustand.docs.pmnd.rs)
[3] Example showing using an action inside onRehydrateStorage works (GitHub issue #830) (github.com)
Citations:
- 1: https://github.com/pmndrs/zustand/blob/main/src/vanilla.ts
- 2: https://zustand.docs.pmnd.rs/middlewares/persist?utm_source=openai
- 3: Example in persist is broken pmndrs/zustand#830
Zustand 하이드레이션 완료 상태를 구독자에게 올바르게 알려주세요.
onRehydrateStorage 콜백 내에서 state 객체를 직접 변경하면 Zustand의 구독자 알림이 작동하지 않습니다. 현재 코드처럼 state.userRole과 state.isInitialized를 직접 대입하면, 이 값들을 구독하는 컴포넌트가 하이드레이션 완료를 감지하지 못해 UI가 업데이트되지 않을 수 있습니다.
하이드레이션 로직을 다음 중 하나로 개선해주세요:
- store 액션 활용: 기존 액션 함수(예:
setUserRole,setInitialized)를onRehydrateStorage내에서 호출 setState경로 사용:store.setState()를 통해 상태 업데이트
이렇게 하면 Zustand가 올바르게 모든 구독자에게 변경을 알릴 수 있고, 로그인 안정성 조사 시 상태 전이를 명확하게 추적할 수 있습니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/web/src/lib/zustand/useAuthStore.ts` around lines 123 - 131, In
onRehydrateStorage, avoid mutating the incoming state directly; instead update
the store via its actions or setState so subscribers are notified: call the
existing action(s) (e.g., setUserRole(parseUserRoleFromToken(state.accessToken))
and setInitialized(true)) or invoke store.setState({ userRole:
parseUserRoleFromToken(state.accessToken), isInitialized: true }) rather than
assigning to state.userRole/state.isInitialized directly; keep the authDebugLog
call but perform updates through setUserRole/setInitialized or store.setState to
ensure Zustand notifies subscribers.
| if (typeof window !== "undefined") { | ||
| window.__AUTH_DEBUG_LOGS__ = window.__AUTH_DEBUG_LOGS__ ?? []; | ||
| window.__AUTH_DEBUG_LOGS__.push(payload); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Do JavaScript globals attached to windowsurvive a full-page navigation triggered bywindow.location.href, or are they reset with the new document?
💡 Result:
They’re reset.
A navigation triggered by window.location.href loads a new document, which gets a fresh Window (global object) and JavaScript realm, so any globals you previously attached (e.g. window.myVar = ...) won’t be there in the new page. What stays “the same” is the stable reference (WindowProxy) that forwards to whichever document’s Window is currently active. (stackoverflow.com)
One important exception: if the user later returns via Back/Forward Cache (bfcache), the browser may restore the prior page from memory and preserve its JS state, including globals—but that’s a page restoration, not a normal full reload. (developer.mozilla.org)
Citations:
- 1: https://stackoverflow.com/questions/16092835/windowproxy-and-window-objects?utm_source=openai
- 2: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching?utm_source=openai
/login 리다이렉트 순간에 로그가 사라지는 문제
현재 debug buffer가 window 메모리에만 보관되어 있어서, axiosInstance.ts의 redirectToLogin처럼 window.location.href로 전체 페이지 네비게이션이 발생하면 __AUTH_DEBUG_LOGS__ 전체가 초기화됩니다. 웹 브라우저에서 새 문서가 로드될 때 새로운 Window 객체와 JavaScript realm이 생기기 때문에, 이전에 부착한 전역 변수들이 모두 리셋되는 것입니다.
이번 PR이 정확히 해결하려는 "갑작스러운 /login 리다이렉트" 시나리오에서 오히려 가장 필요한 로그를 건지지 못하게 되므로, 다음과 같이 개선하면 좋겠습니다:
- 마지막 N개 이벤트를
sessionStorage에 미러링해두기 - 새 문서 로드 후 복구 로직 추가하기
- 리다이렉트 직전의 이벤트 타임라인을 보존할 수 있게 하기
이렇게 하면 /login 페이지에서도 직전의 인증 관련 로그를 확인할 수 있어서, 디버깅이 훨씬 더 효과적이 될 것입니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/web/src/utils/authDebug.ts` around lines 41 - 43, The in-memory
window.__AUTH_DEBUG_LOGS__ is lost on full-page navigations (e.g.,
redirectToLogin in axiosInstance.ts); modify apps/web/src/utils/authDebug.ts to
mirror the last N events into sessionStorage and restore them on module
initialization: on every push to window.__AUTH_DEBUG_LOGS__ write a truncated
JSON array (limit N) to a fixed sessionStorage key (e.g.,
"__AUTH_DEBUG_LOGS_SESSION__"), and when the module loads, hydrate
window.__AUTH_DEBUG_LOGS__ from that sessionStorage key if present; ensure
serialization/deserialization with try/catch to avoid exceptions and keep the
same push logic so existing callers need no change.
개요
로그인 불안정(간헐적 로그아웃/401/인증 상태 튕김) 이슈의 원인 분석을 위해 인증 흐름 디버그 계측을 추가했습니다.
기능 로직 변경 없이, 디버그를 켠 경우에만 타임라인 로그를 수집합니다.
변경 사항
localStorage.setItem("authDebug", "1")또는NEXT_PUBLIC_AUTH_DEBUG=true일 때만 동작window.__AUTH_DEBUG_LOGS__제공setAccessToken,clearAccessToken,refreshStatus,isLoading,isInitialized전이 로그 추가주요 파일
apps/web/src/utils/authDebug.tsapps/web/src/utils/axiosInstance.tsapps/web/src/lib/zustand/useAuthStore.tsapps/web/src/middleware.tsapps/web/LOGIN_INSTABILITY_INVESTIGATION.md검증
pnpm --filter @solid-connect/web run lint:checkpnpm --filter @solid-connect/web run typecheck:cici:check + next build통과후속 분석 절차
window.__AUTH_DEBUG_LOGS__+ HAR 수집