fix: resolved auto-logout from silent-refresh · Sungkyunkwan-2/payment-system-project@d6e0032
+ .body(Map.of("success", true, "message", "토큰 재발급 성공"));
github.com
1. 문제 상황 (Issue Description)
- 현상: 액세스 토큰 만료 시
/api/auth/refresh를 통한 토큰 재발급은 성공(HTTP 200)하나, 직후 재시도되는 원래 API 요청이 계속해서 인증 실패(HTTP 401/403)를 일으키며 최종적으로 강제 로그아웃됨. - 영향: 사용자가 로그인 후 일정 시간(토큰 만료 시간)이 지나면 작업 중 세션이 끊김.
2. 원인 분석 (Root Cause Analysis)
이번 이슈의 핵심은 "프런트엔드 저장소의 키(Key) 불일치"와 "토큰 관리 함수의 부재"였다.
- 발단:
SecurityConfig및JwtAuthenticationFilter적용으로 보안 강화. - 전개:
api-handler.js에 401 에러 대응 로직을 추가했으나, 내부적으로 사용되는 토큰 획득 함수(getToken)가 정의되지 않음. - 위기: AI가 임의로 생성한
getToken함수가localStorage에서accessToken이라는 키를 조회하도록 설정됨. - 절정 (결정적 원인): 실제 로그인 시 토큰이 저장되는 키 이름은
authToken이었음. - 결과: 재발급받은 새 토큰을 엉뚱한 방(
accessToken)에 저장하니, 다음 요청 시getToken이 여전히 비어있거나 만료된 방(authToken)을 참조하게 되어 인증 실패가 반복됨.
3. 해결 방안 (Resolution)
[Step 1] 백엔드: Refresh 엔드포인트 구현 및 보안 설정
SecurityConfig에서/api/auth/refresh를permitAll()에 추가하여 만료된 토큰 상태에서도 접근 가능하도록 설정.AuthController에서 쿠키의 리프레시 토큰을 검증하고, 새 액세스 토큰을Authorization헤더에 담아 반환하도록 구현.
[Step 2] 프런트엔드: 토큰 관리 함수 단일화 및 키 일치
api-handler.js 상단에 실제 사용 중인 저장소 키(authToken)를 명시적으로 사용하는 관리 함수를 정의함.
// 토큰 관리 유틸리티 (Key 이름: authToken)
const TOKEN_KEY = 'authToken';
function getToken() {
return localStorage.getItem(TOKEN_KEY);
}
function setToken(token) {
localStorage.setItem(TOKEN_KEY, token);
}
[Step 3] 프런트엔드: 재시도(Retry) 로직 보완
401 응답 시 세션을 끊기 전, 재발급을 시도하고 성공 시 저장소를 업데이트한 후 원래 요청을 다시 호출하도록 수정.
4. 결과 확인 (Verification)
- 검증: 네트워크 탭 확인 결과, 다음의 시퀀스가 정상 작동함.
GET /api/me→ 401 Unauthorized (액세스 토큰 만료)POST /api/auth/refresh→ 200 OK (새 토큰 발급 및authToken저장소 갱신)GET /api/me(Retry) → 200 OK (갱신된 토큰으로 자동 재시도 성공)
5. 교훈 및 방지 대책 (Lessons Learned)
- 명시적 환경 확인: 로컬 저장소(Local Storage)나 쿠키를 사용할 때는 반드시 개발자 도구를 통해 실제 저장되는 Key 이름을 먼저 확인해야 함.
- 추측 기반 개발 지양: 시스템의 공통 라이브러리(api-handler 등)를 수정할 때는 다른 모듈(login, auth 등)과의 의존성 및 함수 정의 여부를 먼저 파악해야 함.
'Projects > [Spring] Payment System Project(02FEB26~' 카테고리의 다른 글
| Troubleshooting: 로그인 성공 후 페이지 튕김 및 API 응답 검증 오류 해결 (0) | 2026.02.10 |
|---|---|
| [결제 시스템 프로젝트] 로그인 시 StackOverFlowError 해결하기 (0) | 2026.02.06 |