Files
CODE_ASSISTANT/docs/troubleshootings/2026-09-11-stale-auth-refresh-401.md
T
2026-09-16 17:22:14 +09:00

30 lines
2.2 KiB
Markdown

# 저장된 로그인 정보 때문에 sessions·refresh 401 반복
## 증상
- 앱을 열면 로그인 화면 대신 `/api/v1/chat/sessions`를 먼저 호출하고 401이 남음.
- 이어서 `/api/v1/auth/refresh`가 호출되지만 refresh 쿠키가 없어 `REFRESH_TOKEN_MISSING` 401이 남음.
## 원인
`authStore`는 user만 localStorage에 저장하고 실제 토큰은 httpOnly 쿠키로 관리함. 그런데 `ProtectedRoute`가 저장된 user만 보고 보호 화면을 열었음. 쿠키가 이미 사라져도 user가 남아 있으면 `SessionListPage`가 먼저 마운트되어 sessions API를 호출함.
서버 진실값을 확인하려 만든 `useMe()`는 어디에도 마운트되지 않아 실제 로그인 검증에 쓰이지 않았음. `/users/me`의 refresh까지 실패하면 공통 interceptor가 요청을 세션 만료 모달 큐에 넣어 Promise를 끝내지 않으므로, 앱 시작 검증에도 그대로 쓸 수 없었음.
## 수정
| 파일 | 내용 |
| --- | --- |
| `2_frontend/src/shared/components/ProtectedRoute.tsx` | 저장된 user가 있으면 `useMe()` 검증이 끝날 때까지 보호 화면을 열지 않음. 검증 실패 시 user를 지우고 로그인으로 이동 |
| `2_frontend/src/features/auth/api/auth.api.ts` | 앱 시작 `/users/me` 요청에 세션 만료 큐 제외 표시 추가 |
| `2_frontend/src/lib/api/client.ts` | refresh 실패 시 앱 시작 검증 요청은 모달 큐에 넣지 않고 401을 호출자에게 반환 |
| `2_frontend/src/shared/components/ProtectedRoute.test.tsx` | 검증 중 보호 화면 차단과 실패 시 로그인 이동 회귀 검사 |
| `2_frontend/src/lib/api/client.test.ts` | 앱 시작 refresh 실패가 세션 만료 큐에 갇히지 않는 회귀 검사 |
## 검증
- 회귀 검사 RED: 보호 화면이 즉시 열렸고, 초기 `/users/me` 요청은 세션 만료 큐에서 5초 timeout 됨.
- 수정 후 전체 frontend 검사: 47 files, 268 tests 통과.
- `npm run build` 통과.
- 브라우저에서 stale user + 쿠키 없음으로 `/snap` 진입: `/users/me``/auth/refresh``/login?from=%2Fsnap` 이동, localStorage user 제거 확인. `/chat/sessions` 요청은 발생하지 않음.