[Spring] Redis 기반 세션 스토리지 구축 (1)- 도입배경, 설계

1. 도입배경

  • 프로젝트(웹소설) 진행 중 다음과 같은 고려 사항이 발생했습니다.
  1. 잦은 사용자 인증으로 MainDB 오버헤드가 증가했습니다.
  2. MainDB의 디스크 I/O 속도가 느려 비효율적이었습니다.
  • 이에 대한 대안을 찾던 중, 다른 개발자들이 Redis를 세션 스토어로 사용하는 것을 알게 되어 이를 프로젝트에 적용해 보았습니다.

2. 왜 Redis 를 session store 로 사용하는가?

1) 인메모리 DB(빠른 입출력 속도)

  • Redis는 메인 메모리에서 동작하는 DB로 있어 읽기/쓰기 속도가 빠릅니다.
  • 세션 인증은 빠른 응답 속도가 중요하기 때문에, HDD나 SSD(SSD가 빠르더라도 RAM보다는 느림)를 사용하는 DB보다 Redis를 사용하는 것이 더 효율적입니다.
  • 또한, WAS 인스턴스가 여러 개일 경우에도 메모리에 있는 Redis를 공유하면 되므로 확장성이 뛰어납니다.

2). MainDB 오버헤드 감소(리소스 효율성 측면)

  • MainDB는 세션 외에도 많은 요청으로 인해 오버헤드가 큰 상황입니다.
  • 특히 세션은 로그인한 모든 유저가 요청하는 부분이기 때문에 session store를 MainDB에 두면 리소스 낭비가 커집니다.

3). 프로젝트 요구사항(잦은 인증요청)

  • JWT 기반 로그인을 고려할 수도 있지만, 프로젝트(웹소설) 특성상 잦은 사용자 요청이 요구됩니다.
  • 구매 기록, 결제 기록 인증이 자주 이루어져야 하기 때문에 JWT보다는 세션 기반 로그인을 선택하는 것이 적합했습니다.

3. 설계

  • 세션 관련 라이브러리는 사용 중인 Spring Session과 Spring Security를 사용했습니다.
  • 다중 인스턴스 환경에서도 사용할것을 고려하여 전체적인 흐름을 설계하였습니다.

전체적인 흐름

1) 로그인 과정

  1. 클라이언트에서 유저 인증 정보를 WAS로 전송합니다 (실제 프로젝트에서는 OAuth 방식으로 다소 다릅니다).
  2. WAS에서 인증을 처리하며 DB에서 유저 정보를 확인합니다.
  3. 인증 실패 시 BAD_REQUEST를 반환합니다.
  4. 인증 성공 시 SecurityContext에 인증 정보를 저장합니다.
  5. Spring Session이 동작하여 SessionRepositoryFilter가 HttpSession을 가로채 Redis 기반 세션으로 교체합니다.
  6. 세션 ID가 생성되어 Redis에 저장되고, 생성된 세션 ID는 세션 쿠키(JSESSIONID)에 담겨 클라이언트로 전송됩니다.

2). 요청 세션 인증 처리

  1. 클라이언트의 요청에 세션 쿠키(JSESSIONID)가 자동으로 포함되어 전송됩니다.
  2. WAS는 해당 세션 쿠키를 처리하며, JSESSIONID로 Redis에서 세션 정보를 조회합니다.
  3. 세션 정보가 유효하지 않을 경우 예외 처리(로그인 페이지로 이동)됩니다.
  4. 유효한 경우, 요청을 정상적으로 처리합니다.