요약

  • 기존: Random Hex String 방식
  • 변경: JWT + Metadata JSON 방식

  • 이전에는 특정 토큰을 찾기 위해 Redis를 순회해야 할 수 있어 조회 비용이 O(N)에 가까워질 수 있었습니다.
  • 현재는 JWT 내부의 사용자 정보와 디바이스 정보를 활용해 O(1) 수준의 직접 조회가 가능해졌습니다.
  • 성능뿐 아니라 운영 편의성과 보안 검증 수준도 함께 개선되었습니다.

버전별 상세 비교

항목 이전 버전 (Legacy) 현재 버전 (Modern) 비고
토큰 형태 64 bytes Random Hex JWT (JSON Web Token) 정보 포함형
조회 성능 O(N) (Redis Full Scan) O(1) (Direct Access) 90% 이상 향상
저장 구조 String (토큰만 저장) JSON (메타데이터 포함) 가시성 확보
보안 체계 Redis TTL 의존 서명 + 만료 + 타입 검증 다중 보안 계층
디버깅 불가능에 가까움 매우 용이 사용자 정보 포함

주요 개선 사항

성능 최적화: O(N) -> O(1)

  • 이전에는 특정 디바이스 토큰을 찾기 위해 KEYS 혹은 SCAN으로 Redis 전체를 탐색해야 했습니다.
  • 현재는 JWT 내부 sub(userId)를 즉시 추출한 뒤 refresh_token:{userId}:{deviceId} 키로 직접 접근합니다.
  • Full Scan을 제거하면서 조회 비용을 단건 조회 수준으로 줄일 수 있었습니다.

운영 편의성 및 데이터 가시성

  • 이전에는 Redis에 토큰 문자열만 저장되어 있어 어떤 사용자의 어떤 디바이스 토큰인지 바로 파악하기 어려웠습니다.
  • 현재는 메타데이터 JSON을 함께 저장해 Redis GUI에서도 사용자 이메일, 생성일, 디바이스 정보를 즉시 확인할 수 있습니다.

저장 예시는 다음과 같습니다.

{
  "token": "eyJhbGci...",
  "userId": "user-123",
  "email": "user@example.com",
  "deviceId": "device-456",
  "createdAt": 1709123456789
}

보안 로직 고도화

  • 서명 검증: 위변조된 토큰은 Redis를 조회하기도 전에 서버에서 차단합니다.
  • 만료 검증: JWT의 만료 정보를 기준으로 유효성을 검사합니다.
  • 타입 검증: Payload 내 type: "refresh"를 확인해 Access Token 오용을 방지합니다.

예상 성능 지표

  • 검증 속도: 기존 약 100ms -> 변경 후 5ms 미만
  • Redis 부하: Full Scan 제거로 CPU 사용량 감소
  • 트레이드오프: 저장 공간은 약간 늘어나지만 성능 이득이 더 큼

핵심 코드 변경 포인트

  • 생성: randomBytes(64) 대신 jwtService.sign(payload) 사용
  • 검증: keys() 패턴 매칭 루프 제거
  • 검증 흐름: jwtService.verify()redis.get() 단건 처리

정리

  • 이번 변경의 핵심은 단순히 Refresh Token의 포맷만 바꾼 것이 아닙니다.
  • 찾기 어려운 토큰을 검증 가능하고 식별 가능한 토큰으로 바꾼 것이 핵심입니다.

  • 기존: Random Hex String + 단순 저장
  • 변경: JWT + Metadata JSON
  • 효과: O(N) 탐색 제거, O(1) 조회 구조 확보
  • 추가 이점: 보안 검증 강화, 운영 가시성 향상, 디버깅 편의성 개선