Spring MVC : 세션 관련 찾아보기

     

    Tomcat 서버 구조

     

     

    디버깅 모드로 찾아본 결론

    초기 접속 시 세션 확인 

    • 초기 접속 시, 세션 확인 
      1. 사용자 요청은 각 Port에 맞게 Adapter를 통해 들어온다. 이 때, Request / Response 객체는 각각 생성된다. 그리고 해당 Adapter에서 Request 객체에 SessionId가 발급되어 등록됨. 
      2. Catalina 엔진에서 세션을 요청함. 이 때, Context.getManager()를 통해 요청한다. Context는 Servlet Container(Tomcat)이고, Manager는 ManagerBase다.
      3. ManagerBase에서 현재 Request 객체가 가진 SessionID로 저장된 Session이 있는지 확인한다. 없으면 Null이 반환되고, 있으면 Session이 반환된다.
    • SessionId는 요청이 들어올 때 마다 생성되지만, SessionId가 생성된다고 항상 세션이 생성되거나 저장되어있는 것은 아니다.

     

    Controller에서 세션 요청 시

    • Controller에서 세션 요청 시
      1. Controller에서 request.getSession(True)로 세션을 요청한다. 이 때, Request 객체는 요청마다 생성되는 객체이고 각 Request 내부에는 SessionId가 저장되어있다. 
      2. Request 객체는 서블릿 컨테이너 내부의 Manager를 불러와서, Manager의 ConcurrentHashMap에 세션이 저장되어있는지를 확인한다. 여기서 찾아지면 Session을 Return 해준다. 
      3. 만약에 세션이 없고, 새롭게 세션을 생성하라는 정책인 경우 manager.createSession을 통해서 세션을 만든다. 이 때, 빈 세션을 만들고 그곳에 세션 ID를 설정해준다. 그리고 그 세션을 ConcurretnHashMap에 추가해준 뒤에 반납해준다. 

     

     

    디버깅 모드 탐사 과정 

    스프링을 켠 후, localhost:8080으로 접근했을 때의 디버깅 모드 촬영이다.

    CoyoteAdapter.java

    처음 HTTP 요청이 들어오면 CoyoteAdapter로 들어온다. CoyoteAdapater에서 setRequestedsessionId를 이용해서 값을 셋팅한다. 이 때, 이미 JSESSIONID가 존재하는 것을 확인할 수 있다. 

    Request.java

    Request 객체로 넘어오면 딱히 어떤 작업을 하지는 않는 것으로 보인다. 

    쭉쭉 디버깅을 하다보면 Catalina.Connector에서 Request 객체를 호출하면서, 세션을 가져오려고 한다. 

    Request.java

    Conext.getManager()를 통해서 세션 관련 매니저를 호출한다. 이 때, Context는 Tomcat이다. 정확히는 아직까지는 알 수 없지만, ServletContainer가 어떤 Wrapping 클래스로 감싸져서 Context 형식으로 되는 거 같았다. 이건 나중에 Servlet Container를 좀 더 정확하게 볼 때 공부해보고자 한다. 

     

    manager.findSession()를 이용해서 SessionId에 대한 Session을 찾아오려고 한다. 아마 SessionId가 있는 경우, Request 객체에 찾아온 Session을 넣어주면서 Stateful하게 처리가 될 것 같다. 

    ManagerBase.java

    findSession으로 넘어오면, ManagerBase로 넘어온다. ManagerBase는 내부적으로 Sessions라는 ConcurrentHashMap을 가지고 있는 것을 볼 수 있다. SessionId를 Key로 해서, Session을 Concurrent HashMap에서 저장하는 것이다. 

    ManagerBase.

    처음에 넘어오면 SessionId는 있으나, Sessions의 크기가 0인 것을 볼 수 있다. 즉 SessionId는 세션이 있건 없건 항상 생성되는 것이고, 이 값은 Request 객체에 넣어져서 요청 → 응답동안 유지가 된다. 만약에 추후 Session이 만들어지는 상황이 생기면, 세션을 하나 만들고 이 SessionId를 셋팅하게 될 것이다. 

     

    ManagerBase.java

    findSession을 하면 Map에 sessionId에 해당되는 세션을 찾아서 Return한다. 그렇지만 아직까진 아무런 세션이 없기 때문에 Null값이 리턴된다. 

    Request.java

    다시 Request 클래스로 돌아온다. 이 때, 세션 생성 설정을 하지 않다고 되면, Request에는 특정한 세션값이 설정되지 않은 채 반환된다. 

     

    Request.java

    위의 코드에서 좀 더 아래로 내려와보면 세션을 생성하는 부분도 존재한다. manager.createSession(sessionId)로 세션을 생성한다. 앞서 이야기한 것처럼 처음에 접속할 때 받았던 SessionId를 바탕으로 세션을 생성하는 것이다. 나중에 세션이 만들어지고 나면 response에 현재 세션 쿠키 값을 저장한다는 것도 같이 볼 수 있다. (addSessionCookieInternal)

    ManagerBase

    createSession 메서드로 넘어오면 다음과 같이 createEmptySession()을 통해서 빈 세션을 생성한다. 

    ManagerBase

    그리고 빈 세션에 setId를 통해 SessionId를 저장한다. 

    ManagerBase

    setId 메서드를 디버그로 타고 오면 ManagerBase 클래스의 add()로 넘어오게 된다. add는 Session을 받아서 Sessions에서 값을 추가하는 것을 볼 수 있다. 즉, 새로운 세션을 생성하는 것은 다음과 같은 순서대로 진행된다는 것이다

    1. 빈 세션을 만든다.
    2. 빈 세션에 요청이 들어오면서 시작되었던 세션 ID를 셋팅한다.
    3. 만들어진 세션을 sessions(ConcurrentHashMap / ManagerBase가 관리)에 넣는다.

     

     

    https://junhyunny.github.io/information/server/tomcat-session-management/

    댓글

    Designed by JB FACTORY