ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring session 아키텍처
    spring/session 2021. 2. 22. 12:35

    현재 프로젝트는 session을 was의 메모리에서 관리하고 있다. 이 방법은 내가 지정한 방법이 아니라, tomcat이 기본으로 실행하고 있는 방법이다. 요청에 대한 getSession()이 호출되는 시점에 쿠키 설정부터 쿠키와 세션을 저장하기까지 was가 다 해준 것이다.

     

    구현은 편리하지만, 서버 확장 시 큰 문제가 생긴다. 논리적으로 동일한 서버지만 물리적으로 다른 서버라면 세션의 동기화가 필요하다. 또한, was의 메모리를 직접 할당해 세션을 관리하므로 공간적 제약도 고려해야 한다. 결국 세션 저장소를 분리하기로 했고, Filter로 spring session을, 저장소로 redis를 사용하기로 했다.

     

    boot를 이용한 프로젝트에서 의존성을 추가하고, application.yml에 필요한 정보를 입력한 뒤 redis서버만 준비하면 이 모든 복잡해 보이는 일이 마법처럼 예측한 대로 잘 동작한다. was를 내렸다 다시 띄워도 기본 로그인 정보를 유지하고 있다!(추가한 코드는 10줄 안팍)

     

     

    Filter 추가

    우선 gradle에 org.springframework.session:spring-session-data-redis 의존성을 추가하기만 해도 SessionRepositoryFilter가 등록된다. SessionRepositoryFilter의 주기능은 단순하다. 단지, request와 response를 한번 감싸주기만 한다.

    SessionRepositoryRequestWrapper는 세션관련 api를 오버라이딩해서 동일한 메서드를 호출했을 때 커스터마이징한 결과를 응답할 수 있게 해준다.

    또한 내부적으로 Session을 상속한 제네릭스타입인 SessionRepository를 갖고 있는데 이를 이용해

    세션의 CRUD를 관리하게 된다.

     

     

    인증 완료 후 redis와 통신하는 과정

    사실 SessionRepositoryFilter가 하는 역할이 하나 더 있다.

    Filter는 Chain형식으로 다음 Filter를 호출하는데 이는 callstack에 Filter가 쌓임을 의미한다. 즉, Filter가 종료되는 시점은 호출되는 시점의 역순이며 SessionRepositoryFilter가 종료되는 시점은 SessionRepositoryFilter 이후 실행된 Filter가 모두 종료된 이후 시점이라는 것이다.

     

    종합적으로 보면 SessionRepositoryFilter는 최초로 request를 잘 감싸주기만 하고, 인증 로직은 전혀 다른 Filter인 spinrg security의 Filter가 처리한 뒤 그 결과를 ThreadLocal저장소에 저장하기만 한다면, 그 세션 저장은 SessionRepositoryFilter가 끝나기 직전 commitSession()을 호출함으로써 처리된다는 걸 알 수 있다.

     

    여기서 왜 request를 Wrapper 클래스로 감싼 형태를 다음 Filter로 넘기는지 알 수 있다. 그 이유는, 요청이 세션 정보를 얻을 때 getSession()을 호출하게 되는데 Wrapper에서 이 getSession()을 오버라이딩함으로써 커스터마이징한 세션 저장소에서(redis) 세션정보를 가져올 수 있게끔 하기위함이다. 즉, was에서 기본으로 제공하는 세션관리 방식을 커스터마이징한 것이다!

     

    이 과정을 단계 별로 풀어보면

    1) SecurityContextHolder에서 ThreadLocal의 인증객체 요청

    2) 인증객체가 없는 경우 request의 쿠키ID를 이용해 추상화된 api로 세션 저장소에서 세션 가져오기

    3) Wrapper클래스로 감싸진 request는 커스터마이징한 세션저장소(redis)를 이용해 쿠키ID를 key로 갖는 세션을 외부 저장소에서 가져옴

     

     

    결론

    잘 추상화된 API와 객체(Filter)의 역할분담이 잘 설계되어 있다면 외부 코드의 수정없이 구현체를 갈아치우는 작업을 편리하게 할 수 있었다.

     

    'spring > session' 카테고리의 다른 글

    Spring Session과 SameSite  (2) 2021.03.24

    댓글

Designed by Tistory.