docs: JWT 401/403 에러 UX 처리 부족 트러블슈팅
- 이고은 사용자 케이스에서 발견 - JWT 만료 시 자동 로그아웃 구현 완료 (6aa8fa4) - 웹 테스트 완료
This commit is contained in:
parent
a80af5eb98
commit
bcf6d3e0dc
@ -0,0 +1,92 @@
|
||||
# 프론트엔드 JWT 401/403 에러 UX 처리 부족
|
||||
|
||||
**날짜**: 2025-12-04
|
||||
**작성자**: Agent
|
||||
**관련 파일**:
|
||||
- `frontend-customer/src/contexts/auth-context.tsx:29-69`
|
||||
- `frontend-customer/src/services/robeing-api.ts`
|
||||
|
||||
---
|
||||
|
||||
## 문제 상황
|
||||
|
||||
이고은 사용자 케이스에서 발견:
|
||||
- JWT 만료 시 모든 API 호출 401 에러
|
||||
- 프론트엔드는 로그인 상태로 표시되나 기능 사용 불가
|
||||
- 에러 메시지만 보고 원인 파악 어려움
|
||||
|
||||
게이트웨이 로그:
|
||||
```
|
||||
INFO: 172.21.0.1:56062 - "POST /api/chat HTTP/1.0" 401 Unauthorized
|
||||
INFO: 172.21.0.1:36836 - "GET /api/preferences/... HTTP/1.0" 401 Unauthorized
|
||||
```
|
||||
|
||||
## 원인 분석
|
||||
|
||||
### JWT 만료 시 자동 로그아웃 없음
|
||||
- `auth-context.tsx:29-69` checkAuthStatus()에서 exp 검증 없음
|
||||
- localStorage에 만료된 토큰이 남아있어도 계속 사용 시도
|
||||
- 사용자는 로그인된 것처럼 보이나 모든 API 실패
|
||||
|
||||
### 401/403 에러 처리 일관성 부족
|
||||
- API 함수마다 에러 처리 제각각
|
||||
- 401 (인증 만료) vs 403 (권한 없음) 구분 없음
|
||||
- 사용자에게 명확한 안내 없음
|
||||
|
||||
## 해결 방안
|
||||
|
||||
### 1. useApiError 훅 생성
|
||||
파일: `frontend-customer/src/hooks/useApiError.ts` (신규)
|
||||
- 401: 토스트("로그인이 만료되었습니다") + localStorage 정리 + 리다이렉트
|
||||
- 403: 토스트("접근 권한이 없습니다")만 표시
|
||||
|
||||
### 2. auth-context JWT exp 검증
|
||||
파일: `frontend-customer/src/contexts/auth-context.tsx:29-69`
|
||||
- checkAuthStatus()에서 `payload.exp * 1000 < Date.now()` 체크
|
||||
- 만료 시 localStorage 정리 + setUser(null)
|
||||
|
||||
### 3. API 에러 처리 통일
|
||||
파일: `frontend-customer/src/services/robeing-api.ts`
|
||||
- 모든 API 함수에서 401/403 시 RobeingAPIError 던지기
|
||||
- 컴포넌트에서 useApiError로 일관 처리
|
||||
|
||||
## HTTP 상태 코드 처리 규칙
|
||||
|
||||
| 코드 | UX 처리 | 로그아웃 |
|
||||
|------|---------|---------|
|
||||
| 401 | 토스트 + 즉시 리다이렉트 | Yes |
|
||||
| 403 | 토스트만 표시 | No |
|
||||
|
||||
## 구현 완료
|
||||
|
||||
**커밋**: 6aa8fa4 (2025-12-04 16:47)
|
||||
|
||||
변경 파일:
|
||||
- `src/hooks/useApiError.ts`: 신규 생성
|
||||
- `src/contexts/auth-context.tsx:40-48`: JWT exp 검증 추가
|
||||
- `src/components/chat-interface.tsx:594-599`: useApiError 적용
|
||||
|
||||
테스트 결과:
|
||||
- 로그인/로그아웃 정상 작동
|
||||
- 비로그인 상태 메시지 전송 시 로그인 다이얼로그 오픈
|
||||
- JWT 만료 시나리오는 시간 경과 후 재검증 필요
|
||||
|
||||
## 교훈
|
||||
|
||||
### 원칙 위반
|
||||
- React 구조 원칙 9번: 에러 처리 일관성 부족
|
||||
- React 구조 원칙 10번: 백엔드 응답 검증 부족
|
||||
|
||||
### 예방책
|
||||
- JWT 발급 시 exp 필드 필수 검증
|
||||
- API 에러는 커스텀 훅으로 중앙화
|
||||
- 401/403 구분하여 명확한 사용자 안내
|
||||
|
||||
### 향후 개선
|
||||
장기: Refresh Token 구조 (Access 15분, Refresh 7일)
|
||||
|
||||
## 참고
|
||||
|
||||
- React 원칙: `DOCS/book/300_architecture/313_React_구조_원칙.md:131-148`
|
||||
- 게이트웨이 인증: `robeing-gateway/app/core/auth.py:14-51`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user