나만의 개발 로그 | 고민 로그
Redis를 활용한 AccessToken BlackList 저장(로그아웃 기능) 본문
1. 왜 블랙리스트 기반 로그아웃이 필요한가?
JWT는 Stateless 구조이기 때문에 한 번 발급된 토큰은 만료되기 전까지 서버가 강제로 폐기할 수 없다.
따라서 로그아웃 시 다음과 같은 문제가 발생한다:
- 단순히 프론트에서 로컬스토리지/쿠키를 지우는 것은 보안상 완전한 로그아웃이 아님.
- 악의적인 사용자가 토큰을 복사해 두었다면 재사용 가능.
- 이를 막기 위해선 서버에서 강제로 토큰을 무효화시킬 방법이 필요함 → 블랙리스트 방식 사용.
따라서 만약 프론트엔드에서 로컬스토리지를 비우는 방식으로 처리하는 것이 아니라
백엔드 단에서 로그아웃 기능을 구현한다면 어떻게 될까 싶어서 블랙리스트 기반으로 구현을 했다.
2. 왜 Redis를 AccessToken 저장소로 사용했나?
- Redis는 인메모리 기반 저장소이기 때문에 I/O 부하가 적고 조회 속도가 빠름.
- 블랙리스트 조회는 매 요청마다 Filter에서 수행되므로, 성능이 중요함.
- 일반 RDBMS에 저장하면 I/O 병목 발생 가능성 있음.
- Filter는 모든 요청의 초입에 실행되므로, 이 단계에서의 처리는 반드시 경량화되어야 한다고 판단했음.

key값으로 token을 넣었다.
이후 기존 Filter단계에서 AccessToken이 블랙리스트에 저장돼있는지 여부를 한번 더 체크하게 만들었다.
또한 TTL을 설정하여 Redis가 자동으로 만료된 블랙리스트 항목을 삭제하게 했으므로, 별도 GC(정리)가 필요 없게 했다.
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
String accessToken = jwtUtil.resolveAccessToken(request);
if (accessToken != null) {
Object blackList = redisDao.getBlackList(accessToken);
if (blackList != null) {
if (blackList.equals("logout")) {
throw new IllegalArgumentException("로그아웃된 토큰입니다.");
}
3. Refresh Token도 해당 사항 고려
- 로그아웃 시에는 RefreshToken도 폐기해야 함.
- Redis에 저장된 RT도 함께 제거 → 재발급 방지.
'웹 개발' 카테고리의 다른 글
| Redis를 활용한 Cache 기능으로 조회 성능 개선 (1) | 2023.04.21 |
|---|---|
| AOP 활용하여 컨트롤러 메소드 실행시간 측정 (1) | 2023.04.14 |
| JPA 기본 (0) | 2023.04.06 |
| Postman 테스트? NO! 테스트 코드를 활용하자! (0) | 2023.02.17 |
| Lombok @NoArgsConstructor(force = true) (1) | 2023.02.16 |
Comments