[JWT] 🔐Redis를 활용한 로그아웃 및 블랙리스트 처리
2025. 7. 30. 17:48

0️⃣문제 배경 (JWT의 한계와 Redis 도입의 필요성)

JWT는 서버에 저장하지 않는 토큰 기반 인증 방식이기 때문에 한번 발급되면 유효기한이 끝날 때까지 유효
즉, 사용자가 로그아웃을 해도 서버는 그 토큰이 유효한지 알 수 없음
이를 해결하기 위해서, Redis에 무효화된 토큰 목록(블랙리스트!)를 저장해두고 인증 요청시마다 체크하면
서버는 특정 토큰을 무효화 된 것으로 간주할 수 있음

1️⃣구현 방식 (로그아웃시)

1. 사용자가 로그아웃 요청을 보냄

2. 서버는 해당 jwt를 Redis의 블랙리스트에 저장

  • TTL : 토큰 만료시간까지 설

3. 이후 사용자가 다시 요청하면

  • 서버는 Redis에 해당 토큰이 존재하는지 확인
  • 존재하면 토큰을 무효 처리 (인증 거부. 로그아웃 처리)

✍🏻예시코드

// 로그아웃 시 Redis에 블랙리스트 등록
public void logout(String token) {
    long expiration = jwtUtil.getRemainingTime(token); // JWT 남은 유효시간(ms)
    redisTemplate.opsForValue()
        .set("blacklist:" + token, "logout", expiration, TimeUnit.MILLISECONDS);
}

// 인증 필터에서 확인
public boolean isBlacklisted(String token) {
    return redisTemplate.hasKey("blacklist:" + token);
}

2️⃣보완 전략

  • 메모리 이슈 : 토큰이 많아지면 Redis에 부담이 생김
    >> Redis의 Eviction 정책 (ex. LRU, LFU)을 설정하여 메모리 초과시 적절히 제거하도록 설정 필요
  • 자동 삭제 : TTL을 설정했기 때문에, 토큰 만료 시 자동으로 삭제됨
  • 관리 전략
    • AccessToken : 로그아웃 시, Redis 블랙리스트에 등록하여 서버가 무효화 판단
    • RefreshToken : 별도 저장소(db나 redis)에 관리하여 사용자 id 기반으로 매핑 저장

3️⃣RefreshToken을 redis에 저장하기

로그인 시, 발급한 RefreshToken을 Redis에 저장하고, 사용자 id와 매핑하여 유효성을 직접 확인해야 함
RefreshToken 탈취나 중복 사용을 방지하기 위한 보안 강화 전략임

✍🏻예시코드

// 로그인 시 RefreshToken 저장
redisTemplate.opsForValue().set("refresh:user:1001", refreshToken, 7, TimeUnit.DAYS);

// RefreshToken 유효성 검증
String storedToken = redisTemplate.opsForValue().get("refresh:user:1001");
if (!refreshToken.equals(storedToken)) {
    throw new RuntimeException("Invalid refresh token");
}

✅Redis 활용 요약 및 기대효과

  • 서버 무효화 : Redis를 활용하여 JWT를 블랙리스트에 등록함으로써 서버 차원의 토큰 무효화가 가능해짐
  • 세션 관리 : JWT는 stateless하지만, Redis를 통해 세션 기반 제어가 가능해짐 (강제 로그아웃, 만료 제어 등)
  • 확장성 : 로그인 이력 관리, RefreshToken 갱신, 토큰 재사용 방지, 강제 로그아웃 등의 기능으로 보안성을 강화하며 인증 전략도 유연하게 확장 가능해짐
LIST