Skip to content

[Feat] 로그아웃 API 구현 및 프론트 연동 #186

Description

@kangcheolung

📌 Description

현재 로그인은 stateless JWT(JwtProvider)만 사용하고, 백엔드에 로그아웃 API가 없습니다.
프론트(AuthProvider.tsx)는 sessionStorage에서 토큰을 지우는 클라이언트 전용 로그아웃만 있고,
서버 쪽 토큰 무효화는 되지 않아 탈취된 토큰이 만료 전까지 계속 유효합니다.

POST /auth/logout
- Authorization: Bearer {token} 필요
- 호출한 토큰을 Redis 블랙리스트에 등록해 만료 전이라도 재사용 불가 처리

무효화 방식: Redis. 토큰의 남은 만료 시간만큼 TTL을 걸어 jti(또는 토큰 해시)를 key로 저장하고,
JwtAuthenticationFilter에서 인증 시마다 블랙리스트 존재 여부를 확인합니다. TTL 만료 시 자동 삭제되어
별도 정리 배치가 필요 없습니다.

✅ To-do

  • docker-compose.yml에 redis 서비스 추가 (postgres/minio 옆에 동일 패턴으로)
  • build.gradlespring-boot-starter-data-redis 의존성 추가 및 application.yml에 redis 접속 설정 추가
  • JwtProviderjti claim 추가 (토큰 고유 식별자)
  • Redis 블랙리스트 등록/조회용 컴포넌트 구현 (RedisTemplate 기반, key=jti, value=userId 등, TTL=토큰 잔여 만료시간)
  • AuthCommandService에 로그아웃 로직 구현 (토큰에서 jti·잔여 만료시간 추출 → 블랙리스트 등록)
  • AuthControllerPOST /auth/logout 추가
  • JwtAuthenticationFilter에서 매 요청마다 블랙리스트 조회 후 걸리면 인증 거부
  • 프론트 app/lib/api.ts에 로그아웃 API 호출 함수 추가
  • 프론트 AuthProvider.tsxlogout()이 백엔드 API를 먼저 호출한 뒤 sessionStorage 토큰 제거하도록 변경
  • 백엔드 API 실패(네트워크 오류, Redis 장애 등) 시에도 클라이언트 토큰은 항상 제거되도록 처리 (로그아웃은 항상 성공해야 함)
  • 로컬 개발 가이드(README 등)에 redis 실행 필요 안내 추가
  • 단위/통합 테스트 작성 (유효 토큰 로그아웃, 로그아웃 후 재사용 시도 시 401, Redis 장애 시 필터 동작)

✅ 완료 기준

  • 로그아웃 호출 후 해당 토큰으로 인증 API 호출 시 401이 반환된다.
  • 프론트에서 로그아웃 버튼 클릭 시 백엔드 로그아웃 API가 호출되고, 이후 세션이 정리된다.
  • 로그아웃 API 실패와 무관하게 프론트 세션은 항상 정리된다.
  • Redis 블랙리스트 항목은 토큰 만료 시점에 자동 삭제된다.

📒 기타

  • 관련 파일: AuthController.java, JwtProvider.java, JwtAuthenticationFilter.java, AuthProvider.tsx, app/lib/api.ts, docker-compose.yml, build.gradle
  • Redis 장애 시 인증 필터 정책(fail-open vs fail-closed)은 구현 시 논의 필요

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions