[Spring][JPA] 세션 로그인 구현 - DB에 세션 저장 방식

jhkim·2023년 3월 15일
1

JSESSIONID

톰캣 컨테이너에서 세션을 유지하기 위해 발급하는 키.

https://junjunrecord.tistory.com/95
JSESSIONID에 대해 잘 설명된 글이 있어서 첨부함!


원래 DB가 아닌 서버에 로그인 세션을 저장하는 방식으로 구현했다(기본 동작 방식).
WAS의 메모리에서 저장되고 호출된다.
스프링부트와 같은 내장 톰캣(WAS)를 사용하는 구조에서는 어플리케이션을 실행할 경우 WAS또한 재실행된다. 따라서 WAS의 메모리도 초기화되므로, 웹서버를 재실행하면 세션 정보가 사라져 있을 것이다.

한 대의 WAS가 구동될 경우 문제가 없겠지만, 두 대 이상의 WAS가 구동되면?
=> ❗톰캣 간에 세션 정보를 공유해야 함 ❗



이를 위해서 두 가지 방법이 있다.

  • MySQL 등의 DB를 세션 저장소로 사용
  • Redis 등 인메모리 DB를 세션 저장소로 사용

사용자가 많지 않아 로그인이 잦지 않으므로 MySQL을 사용하도록 했다.
로그인 요청이 잦을 경우,
로그인 세션을 확인할때마다 DB에 접근해야 하므로❗성능 문제가 발생할 수 있다.


로그인 요청이 많이 없는 백오피스 서비스 등에서는 사용해도 괜찮지만, 실제 사용자들에게 서비스할 경우 Embedded Redis와 같은 방식이 아닌 외부 메모리 서버가 필요하다.

아무튼 나는 db에 저장할 거니까
세션 정보를 DB에 저장하도록 spring-sessoin-jdbc dependecy를 추가하고,
application.yml에서 sesson.store-type을 jdbc로 설정해줬다.

이 설정을 적용하면
Spring boot는 이 설정을 읽고 @EnableJdbcHttpSession방식과 동일하게 작동한다.
즉, SpringSessionRepositoryFilter 빈을 생성하여
HttpServletRequest를 전부 이 Filter가 가로채고
SessionRepositoryRequestWrapper로 래핑한다.

왜 래핑을 할까?

여기서 왜 래핑을 하는지 궁금해서 찾아봤는데, 찾아본 결과
요청이 세션 정보를 얻어올 때 getSession을 하게 된다.
래핑하면서 이 getSession을 오버라이딩하여, 세션 저장소에서 세션정보를 가져올 수 있도록 하는 것이 래핑의 목적이다.


(생성된 SpringSessionRepositoryFilterConfiguration 빈)



jpa로 인해 자동으로 두 개의 테이블이 생성됐다.

로그인을 하면 크롬 개발자 도구를 통해


이처럼 session이 생긴 것을 확인할 수 있다.

Session

session은 일종의 저장공간으로, 클라이언트 한 명당 하나의 Session이 서버에 생성된다. 즉 session은 접속한 클라이언트만의 고유 공간이라고 생각하면 편하다.
사용자가 추가로 서버에 접속하면 서버는 새로운 Session을 생성한다.
따라서 Session을 이용한 로그인 처리 방법은 서버에 부담을 주게 되므로 토큰을 이용하여 로그인처리를 구현하기도 한다.

세션 정보는 이처럼 DB의 spring_session 테이블을 통해 유지되고,

이처럼 로그인하며 addattruibute하면

spring_session_attribute에 내가 addattribute했던 값들이 저장된다.
spring session은 고유한 키값을 가지며, 이를 통해 session attribute를 참조한다.

결론적으로 나는 Session을 통해 이 클라이언트가 아까 접속한 클라이언트와 동일한지 확인하고, 그들이 로그인했는지에 대한 정보는 Session_attribute에 저장된 USER ID들을 보고 확인한다.

테스트해본 결과 백엔드 서버를 재실행해도 세션 정보가 유지되어,
로그인이 풀리지 않는다! (서버에 비종속적)



그렇다면 새 클라이언트가 연결될 때마다 자동으로 Session이 생성되어야 하는 것 아닌가?

내가 이해한 바에 따르면 새 클라이언트가 연결될 때마다 Session이 생성되고,
브라우저가 새 요청을 보낼 때마다 쿠키에 저장된 session id를 가지고
서버한테 "야 너 이 id가진 세션 있냐..?있으면 줘봐"한다
그리고 그 session을 뒤적여서 로그인된 정보를 찾아간다.

그런데 나의 경우는 로그인을 해야만 Session이 생성되고,
로그인 전에는JSESSION만 존재했다.
왜인지 더 고민해봐야겠다..아 왜지 진짜...

이후에 분산시스템을 구현하면,
세션 정보를 Redis에 보관하고 여러 개의 서버가 해당 Redis 서버를 참조하여 세션 정보를 가져오는 방식으로 구현해야겠다.


[참고]
https://www.baeldung.com/spring-session-jdbc
https://yousrain.tistory.com/8 (왜 래핑할까)

0개의 댓글