스프링에서 제공하는 기본 세션
1. HttpSession 은 request를 날린 그 대상만 조작할 수 있는 걸로 알고있는데 맞나요?? 예를들어 HttpSession의 getId 로 sessionID 를 안다고해도 sessionId 로 session을 찾는 방법은 없는걸로 알고 있습니다. 이 사실이 맞나요??
2. 1번이 맞다는 가정하에, 그러면 session 추적해서 session 정보를 바꾸고 싶으면 따로 sessionStore 나 sessionRegistry 같은거라도 만들어서 서버내에 Map<세션아이디, 세션> 형식으로 세션아이디로 세션 추적 가능하게 만들어둬서 세션을 업데이트 하는 방법 사용해도 되는건가요?
3. 만약 로그인 한 유저를 기반으로 session이 생성된다고 한다면, 브라우저 강종하거나, 뭐 다른브라우저에서 또 접속하거나 하면 한 유저에 대해서 여러 sessionId가 생성될 수도 있다고 생각하는데, 그러면
Map<유저id, 세션id리스트> 이런식으로 또 매핑해서 놔두는 방법 사용해도 될까요?
4. 예상 시나리오는 관리자가 어떤 유저의 필드값을 바꾼다면 db에 적용하고, 바뀐 유저의 id로 Map<유저id, 세션id리스트> 에서 sessionId를 추적하고, 추적된 세션아이디들로 Map<세션아이디, 세션>로 세션을 알아내서 모든 세션에 업데이트를 해주는 이 방법 써도 될까요?
이전에 질문 올렸던 글에서 많은 분들이 인터셉터에서 서비스를 의존받아서 디비를 게속 체크하는 것보다 세션 방식을 하는것이 정배라는 느낌? 으로 댓글을 달아주셔서 대충 세션기반으로 하면 이렇게 하면되나 생각해봤는데 제 생각이 틀린생각인지 궁금합니다.
제가 아직 캐시에 관해서는 제대로 공부를 하지 않아서 redis같은것은 아직 다루지 못합니다 ㅠ
근데 만약에 제 방법이 틀린방법이 아니라고해도,
만약에 유저가 엄청 쏟아져서 저 저장소 map들을 꽉 채워버린다면 |
이 저장공간을 어떤식으로 관리해야할지도 모르겟고 얼마나 저장될지도 모르겟고 하네요...
머 어차피 제가 그런걸 고민할 그런 프로젝트는 아니지만 그런 것도 생각은 해보는데 앞이 깜깜하네요
서블릿 한번 공부해봐
일단 서버는 상태를 유지하지 않습니당 그러기위해 세션ID를 부여하고 하나의 리퀘스트에 이 세션아이디를 사용하여 상태를 가져오는거라고 생각하시면 돼요. 세션은 서버에서 유지하는 동시성 맵에 저장되어있는데 이건 찾아보시면 금방 나올거구, 맵은 100만개가 쌓이면 대략 10메가가 안됩니당 말씀하신 타격이 올정도면 10억명정도 로그인해야겠네용
그 무상태를 극복하기 위해 사용하는게 세션아닌가요?? 일단 타격의 면에서는 그런 정보가있었군요 감사합니다.
어제 이거때문에 다시 댓글 다시 작성하려 했는데 뭔 이상한 인증 6글자때문에 열받아서 못달았네요... 말씀하신대로 서버는 상태를 유지하지 않기에 그걸 극복하기 위해 세션 ID를 사용하여 상태를 저장합니다! 요청에 JSESSIONID 쿠키가 포함되어 있으면 이를 참고하여 해당 세션에서 꺼내어 이 요청에서 사용합니다!
추가로 그럼 세션을 동시성맵에 계속 쌓는건가? 라는 의문은 저도 궁금해서 찾아봤는데
https://github.com/spring-projects/spring-session
에서 확인가능하네요!
찾아본 내용으로는 DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800 으로 30분동안 지속은 하지만, findById로 찾을 경우에 시간이 만료되었는지 체크 후 삭제합니다. 하지만 말씀하신 대로 findById를 실행할 때만 해당 ID를 검증하고 이외에 다른 아이디로 계속 로그인한다면 Map 데이터는 축적된다고 스프링에서 따로 주기적으로 처리하는 로직을 만들라는 얘기도 있네요. 앞서 말씀드린 것 처럼 타격은 거의 미미하나, 필요하다면 구현할 수도 있을거 같습니다.
결론적으로 2, 3번은 실제 구현체인 SessionRepository를 구현한다면 가능은 할거 같습니다. 하지만 이로 인한 부하는 추가로 고민해보셔야 할 거 같고, 모놀리식이라면 스프링 세션에 이러한 데이터를 구현하는 것보다 캐시에 Map<유저 ID, List> 로 해보면 어떨까 싶어요. 이러면 자연스럽게 4번도 sessionRepository에 있는 deleteId로 캐시에 Map<유저 ID, List> 가져와 해당 유저의 JSESSIONID 를 모두 삭제해준다면 로그인한 회원은 현재 로그인된 유저의 세션으로 접근하지 못하지 않을까 싶습니당
위 방식은 저도 구현해본건 아니라 말씀하신 방식을 이런식으로 하면 어떨까하는 제안이라 참고만 해주세요!
1. 아마 톰캣일거 같은데 session의 id와 세션 내부에 저장된 데이터(VO같은) 내부의 id는 다름. 세션의 id는 클라이언트가 페이지를 접속하자마자 생기는 JSESSIONID를 말하는것일텐데, 이 세션 객체는 서버의 톰캣 프로세스가 할당된 메모리 내부에 존재하고, 이걸 건드리는 건 따로 제공되지 않음. 보통은 질문 2와 같이 Sptring-session-core를 사용한다면 SessionRegistry로 다루고, 그렇지 않다면 HttpSessionListener를 구현해서 동시성 맵 객체에 담아두도록 재정의 한 후 관리함.Spring-session-core와 redis-data-
어쩌구 라이브러리를 활용해서 톰캣에서 관리하던 세션객체를 레디스에서 관리하도록 많이 설정함. 하나 이상의 서버에서 세션을 관리하는 경우 서버의 메모리 상에만 세션객체가 존재하기 때문에 서버 A로 붙어있던 클라이언트가 임의의 이유로 서버 b로 붙게되면, 서버 b에는 세션이 없기에 다시 인증/인가를 해야함. 그래서 이 문제 해결을 위해 Redis에 세션 키 값을 넣고 관리함. 문제에 대한 답은 없이 주저리주저리 잡설이 길었네. 틀린거 있으면 언제든지 말해줘들.