Spring MVC : 세션 관련 찾아보기
- Spring/Spring MVC
- 2022. 5. 18.
Tomcat 서버 구조
디버깅 모드로 찾아본 결론
초기 접속 시 세션 확인
- 초기 접속 시, 세션 확인
- 사용자 요청은 각 Port에 맞게 Adapter를 통해 들어온다. 이 때, Request / Response 객체는 각각 생성된다. 그리고 해당 Adapter에서 Request 객체에 SessionId가 발급되어 등록됨.
- Catalina 엔진에서 세션을 요청함. 이 때, Context.getManager()를 통해 요청한다. Context는 Servlet Container(Tomcat)이고, Manager는 ManagerBase다.
- ManagerBase에서 현재 Request 객체가 가진 SessionID로 저장된 Session이 있는지 확인한다. 없으면 Null이 반환되고, 있으면 Session이 반환된다.
- SessionId는 요청이 들어올 때 마다 생성되지만, SessionId가 생성된다고 항상 세션이 생성되거나 저장되어있는 것은 아니다.
Controller에서 세션 요청 시
- Controller에서 세션 요청 시
- Controller에서 request.getSession(True)로 세션을 요청한다. 이 때, Request 객체는 요청마다 생성되는 객체이고 각 Request 내부에는 SessionId가 저장되어있다.
- Request 객체는 서블릿 컨테이너 내부의 Manager를 불러와서, Manager의 ConcurrentHashMap에 세션이 저장되어있는지를 확인한다. 여기서 찾아지면 Session을 Return 해준다.
- 만약에 세션이 없고, 새롭게 세션을 생성하라는 정책인 경우 manager.createSession을 통해서 세션을 만든다. 이 때, 빈 세션을 만들고 그곳에 세션 ID를 설정해준다. 그리고 그 세션을 ConcurretnHashMap에 추가해준 뒤에 반납해준다.
디버깅 모드 탐사 과정
스프링을 켠 후, localhost:8080으로 접근했을 때의 디버깅 모드 촬영이다.
처음 HTTP 요청이 들어오면 CoyoteAdapter로 들어온다. CoyoteAdapater에서 setRequestedsessionId를 이용해서 값을 셋팅한다. 이 때, 이미 JSESSIONID가 존재하는 것을 확인할 수 있다.
Request 객체로 넘어오면 딱히 어떤 작업을 하지는 않는 것으로 보인다.
쭉쭉 디버깅을 하다보면 Catalina.Connector에서 Request 객체를 호출하면서, 세션을 가져오려고 한다.
Conext.getManager()를 통해서 세션 관련 매니저를 호출한다. 이 때, Context는 Tomcat이다. 정확히는 아직까지는 알 수 없지만, ServletContainer가 어떤 Wrapping 클래스로 감싸져서 Context 형식으로 되는 거 같았다. 이건 나중에 Servlet Container를 좀 더 정확하게 볼 때 공부해보고자 한다.
manager.findSession()를 이용해서 SessionId에 대한 Session을 찾아오려고 한다. 아마 SessionId가 있는 경우, Request 객체에 찾아온 Session을 넣어주면서 Stateful하게 처리가 될 것 같다.
findSession으로 넘어오면, ManagerBase로 넘어온다. ManagerBase는 내부적으로 Sessions라는 ConcurrentHashMap을 가지고 있는 것을 볼 수 있다. SessionId를 Key로 해서, Session을 Concurrent HashMap에서 저장하는 것이다.
처음에 넘어오면 SessionId는 있으나, Sessions의 크기가 0인 것을 볼 수 있다. 즉 SessionId는 세션이 있건 없건 항상 생성되는 것이고, 이 값은 Request 객체에 넣어져서 요청 → 응답동안 유지가 된다. 만약에 추후 Session이 만들어지는 상황이 생기면, 세션을 하나 만들고 이 SessionId를 셋팅하게 될 것이다.
findSession을 하면 Map에 sessionId에 해당되는 세션을 찾아서 Return한다. 그렇지만 아직까진 아무런 세션이 없기 때문에 Null값이 리턴된다.
다시 Request 클래스로 돌아온다. 이 때, 세션 생성 설정을 하지 않다고 되면, Request에는 특정한 세션값이 설정되지 않은 채 반환된다.
위의 코드에서 좀 더 아래로 내려와보면 세션을 생성하는 부분도 존재한다. manager.createSession(sessionId)로 세션을 생성한다. 앞서 이야기한 것처럼 처음에 접속할 때 받았던 SessionId를 바탕으로 세션을 생성하는 것이다. 나중에 세션이 만들어지고 나면 response에 현재 세션 쿠키 값을 저장한다는 것도 같이 볼 수 있다. (addSessionCookieInternal)
createSession 메서드로 넘어오면 다음과 같이 createEmptySession()을 통해서 빈 세션을 생성한다.
그리고 빈 세션에 setId를 통해 SessionId를 저장한다.
setId 메서드를 디버그로 타고 오면 ManagerBase 클래스의 add()로 넘어오게 된다. add는 Session을 받아서 Sessions에서 값을 추가하는 것을 볼 수 있다. 즉, 새로운 세션을 생성하는 것은 다음과 같은 순서대로 진행된다는 것이다
- 빈 세션을 만든다.
- 빈 세션에 요청이 들어오면서 시작되었던 세션 ID를 셋팅한다.
- 만들어진 세션을 sessions(ConcurrentHashMap / ManagerBase가 관리)에 넣는다.
https://junhyunny.github.io/information/server/tomcat-session-management/
'Spring > Spring MVC' 카테고리의 다른 글
Thymeleaf : 정적 리소스, URL 제대로 알고 사용하자 (0) | 2022.02.18 |
---|---|
Spring MVC : Pageable 파라미터 받기 (0) | 2022.02.06 |
타임리프 : 상대경로 / 절대경로 표현 (0) | 2022.02.03 |
Spring MVC : 파일 업로드 및 다운로드 구현해보기 (0) | 2022.01.08 |
Spring MVC : @Value 어노테이션 (0) | 2022.01.08 |