[실시간 대용량 서비스] AccessToken / RefreshToken 분리 설계와 Redis 화이트리스트

2026. 2. 2. 19:52·Spring/Spring 실습

🤔 왜 인증 구조에 대해 고민했는가

이번 최종 프로젝트는 온라인 교육 플랫폼을 목표로 한 백엔드 서버 구현이었다.

기능 자체는 회원가입, 로그인, 강의 수강, 주문 등 비교적 익숙한 영역이었지만 인증/인가 파트를 제대로 맡아서 해본 적이 없었다는 점과 

프로젝트 초기 설계 단계부터 인증을 어떻게 가져갈 것인가는 단순히 구현하는 것으로 그칠 수 있는 문제가 아니었다.

 

설계 및 여러 교육 플랫폼들을 찾아보며 우리 프로젝트에 필요한 요구사항은 아래와 같았다.

 

  • 다중 디바이스 로그인 가능 (PC / Mobile / Tablet 등...) 
  • 관리자 / 강사 / 수강생 역할 분리
  • 향후 계정 공유 방지, 동시 로그인 제한 정책 확장 가능성
  • API 서버의 수평 확장 고려

이를 통해 세션 기반 인증보다는 Stateless 한 구조가 더 적합하다고 생각했다.

 

🔗 세션 기반 인증을 선택하지 않은 이유

Spring Security를 사용할 때 가장 익숙한 방식은 세션 기반 인증이다.

하지만 이번 프로젝트는 다음과 같은 한계가 있을 것이라고 예상했다.

 

❌ 세션 기반 인증의 한계점

  • 서버 메모리 또는 외부 저장소(Session Storage)에 상태 의존
  • 수평 확장 시 세션 동기화 비용 발생
  • 디바이스 단위 제어가 까다로움
  • 로그아웃 / 강제 만료 정책이 세션에 강하게 결합됨

 

✅ JWT 기반 인증의 장점

  • 인증 요청의 주 경로를 서버 상태 없이 처리 가능
  • 토큰 자체로 사용자 식별 가능
  • API 서버 확장에 유리
  • 모바일 / 웹 클라이언트와의 궁합이 좋음

→ 따라서 AccessToken은 완전히 Stateless 하게 가져가는 방향으로 결정했다.

 

🔍 AccessToken / RefreshToken 분리 설계

JWT를 사용할 때 가장 먼저 부딪히는 문제는 토큰 탈취에 대한 문제였다.

 

위에서 정리한 세션 기반 / JWT 기반 인증의 특징을 고려하고, 교육 도메인의 특성을 고려하여 아래와 같은 구조로 선택을 진행했다.

 

AccessToken

  • 짧은 만료 시간
  • API 요청마다 사용
  • 서버에 저장하지 않음 (완전 무결성)

RefreshToken

  • 상대적으로 긴 만료 시간
  • AccessToken 재발급 용도
  • 서버에서 통제 가능해야 함

일반적인 JWT 설계에서 나는 RefreshToken을 어디에서 관리할 것인가에 대한 고민이 필요했다.

 

👉 RefreshToken을 Redis에 저장한 이유

RefreshToken을 Redis에 저장하는 방식을 선택함으로써 위에서 선택한 고민에 대한 내용에 상충하는 부분이 발생했다.

 

"Stateless가 아닌 것 아닌가?"

 

이는 RefreshToken을 서버에서 관리하고자 하는 의도적인 선택이었다.

 

온라인 교육 플랫폼은 강의 영상과 같은 유료 콘텐츠를 다루는 도메인이다. 

단순히 로그인 성공 여부보다 접속을 통제하고 차단할 수 있는 지점이 필요하다고 판단했다.

  • 계정 공유를 통한 다중 접속
  • 토큰 탈취 후 장시간 접근
  • 로그아웃 이후에도 계속되는 접근

이러한 상황을 고려했을 때 RefreshToken까지 완전히 Stateless로 두는 것은 보안 및 운영 측면에서 제어하기 어려운 구조라고 생각했다.

 

따라서 인증 구조 전체가 Stateless 하지는 않지만, 상태가 필요한 지점을 의도적으로 제한한 구조라고 생각한다.

 

☑️ Redis 화이트리스트 구조 선택

RefreshToken 저장소로 Redis를 선택했고, 단순 저장이 아니라 화이트리스트 방식으로 관리하도록 설계했다. 

 

Redis 구조 예시

key: refresh:{userId}:{deviceId}
value: refreshToken
TTL: refreshToken 만료 시간

 

이 구조를 통해서 위에서 발생할 수 있는 여러 특이사항을 처리할 수 있게 되었는데,

  • 로그아웃 시 즉시 무효화
  • 디바이스별 토큰 관리
  • 특정 디바이스만 강제 로그아웃
  • 동시 로그인 제한 정책 확장 가능

즉, 보안과 운영 관점에서의 제어력을 확보하기 위한 선택이었다.

 

Spring Security에서 지킨 원칙

1. Stateless 우선 설계

→ AccessToken 자체는 서버에 상태를 두지 않고 처리하되, 필요 시 통제할 수 있는 지점을 남김으로써 완전한 stateless아 보안성 사이의 균형을 유지했다.

 

2. 통제 가능한 RefreshToken 정책 

→ RefreshToken 을 서버(Redis)에 저장함으로써 로그아웃 즉시 만료 처리, 디바이스 별 토큰 관리, 세션 공유 차단 같은 보안 요구사항을 만족했다.

→ 이는 모든 RefreshToken을 상태로 저장한다는 점에서 stateless 철학과는 다르지만 통제와 보안 우선의 설계 선택이었다.

 

3. Whitelist를 통한 RefreshToken 관리

→ Redis에 등록된 RefreshToken만 유효하게 처리함으로써 공격자가 탈취한 토큰을 마음대로 재사용하지 못하도록 했다.

→ 이를 통해, 단순 JWT 기반 인증 구조보다 보안적으로 더 강한 제어력을 갖게 됐다.

 

마무리하며..

이번 설계에서는 JWT 기반 인증을 적용하면서도 보안성과 통제력을 높이는 방향으로 선택했다.

그 결과 다음과 같은 장점을 얻을 수 있었다.

 

✓ AccessToken은 무상태 처리로 확장성이 좋고

✓ RefreshToken은 서버에서 관리하며

✓ 디바이스 / 사용자 단위 제어가 가능하다.

 

즉, Stateless 구조의 장점을 살리면서 Stateful한 통제도 활용한 하이브리드 설계가 됐다.

 


https://stark77.tistory.com/110

 

 

[실시간 대용량 서비스] 최종 프로젝트 발제(작성중)

📄 프로젝트 개요본 프로젝트는 자유 주제로 진행된 최종 프로젝트로, 온라인 교육 플랫폼을 목표로 한 백엔드 서버 구현에 초점을 두었습니다. JWT 기반 인증·인가 구조를 중심으로 사용자, 강

stark77.tistory.com

 

 

'Spring > Spring 실습' 카테고리의 다른 글

[실시간 대용량 서비스] 모니터링 시스템 구축은 왜 필요한가 ?  (1) 2026.02.23
[실시간 대용량 서비스] JWT 인증에서 블랙리스트로도 충분한데, 왜 화이트리스트를 선택했을까?  (0) 2026.02.06
[실시간 대용량 서비스] 최종 프로젝트 발제  (0) 2026.01.30
[과제 회고] K사 서버 개발하기  (0) 2026.01.14
[프로젝트 회고] 실시간 채팅 프로젝트  (0) 2025.12.31
'Spring/Spring 실습' 카테고리의 다른 글
  • [실시간 대용량 서비스] 모니터링 시스템 구축은 왜 필요한가 ?
  • [실시간 대용량 서비스] JWT 인증에서 블랙리스트로도 충분한데, 왜 화이트리스트를 선택했을까?
  • [실시간 대용량 서비스] 최종 프로젝트 발제
  • [과제 회고] K사 서버 개발하기
stark77
stark77
하마의 IT 자기개발 이모저모, 백엔드 개발자로 거듭나기
  • stark77
    하마의 개발자 성장일기
    stark77
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 컴퓨터구조와 운영체제
        • 컴퓨터구조
        • 운영체제
      • SQL 기초
      • Spring
        • 백엔드 기초
        • Spring 실습
      • JAVA
        • Java 실습
      • HTML&CSS
        • HTML&CSS 실습
      • Git&GitHub
        • Git&GitHub 실습
      • 내배캠 끄적끄적
        • Today I Learned
      • 유용한 툴 및 사이트 정리
      • 취미
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    jsp
    JPA
    java
    Stomp
    네트워크 기초
    Github
    RestTemplate
    String.format
    웹소켓
    WebSocket
    thymleaf
    BEAN
    for문
    백엔드 기초다지기
    MVC
    객체지향프로그래밍
    다형성
    Spriingboot
    SpringSecurity
    백엔드 기초
    프로세스와 쓰레드
    실시간 데이터 처리
    객체지향
    HTML&CSS
    Java 문법기초
    git
    algorithm
    Til
    Spring
    경합조건과 교착상태
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
stark77
[실시간 대용량 서비스] AccessToken / RefreshToken 분리 설계와 Redis 화이트리스트
상단으로

티스토리툴바