제목을 보고 의아할 수 있다. 전혀 연관 없는 두 개념이 왜 함께 제목에 적혀있는지 의문이 들 수 있지만, 제목을 위와 같이 지을 수 밖에 없었던 이유를 글을 보면서 이해하도록 하자.
세션 속성 삭제로 인한 NULL 데이터 전달
세션 속성 삭제라는 큰 주제로 이 글을 시작하겠다. 필자는 특정 조건에 대하여 모달을 팝업하는 개발을 진행하였다. 조건을 통해 분기를 태우던 중 위에서 언급한대로 이전에 설정해둔 세션이 NULL 데이터로 넘어오는 현상을 맞이하였다. NULL이 어디에서 발생했는지 알아보기 위해 직접 로그를 파악해보았다.
file 세션에 null 데이터가 인식되는 것을 알 수 있다. 왜 발생했는지 프로젝트의 전체적인 흐름을 파악해가며 이해해보자.
org.egovframe.rte.ptl.mvc
해당 프로젝트는 전자정부프레임워크의 표준 프레임워크를 의존 받는다. 전자정부프레임워크에 따르면 Egov의 MVC는 Spring Web MVC를 채택하여 사용한다. 즉, 현재 프로젝트는 spring web mvc를 사용한다고 볼 수 있다.
이를 통해 알 수 있는 사실은 세션에 대하여 JSESSION ID를 사용한다는 점이다. JSESSION ID는 인증,인가를 위한 식별자로 사용되며 쿠키에 저장되는 특징을 지닌다.
가장 중요한 개념은 JSESSION ID는 클라이언트의 서버 요청 시 모든 요청 헤더에 쿠키 값을 포함시켜 보내고 서버가 이를 식별할 수 있다.
그렇다면, JSESSION ID는 어디서 만들어줄까?
스프링을 하는 개발자라면 알고 있어야 하는 개념으로, JSESSION ID는 톰캣 컨테이너에서 세션을 유지하기 위해 발급한다. HTTP는 Stateless라는 성격을 지닌다. 이에 따라 HTTP SESSION의 생성 주체가 Servlet Container가 되어 JSESSIONID를 생성한다.
JSESSIONID는 HttpServletRequest의 getSession 옵션에 따라 자동으로 생성되는 특징을 지닌다.
본 프로젝트에서는 @SessionAttributes와 @ModelAttributes를 통해 세션을 생성하고 페이지에 세션 속성을 전달한다.
Spring Security Interceptor
클라이언트가 서버에 요청을 가하면 JSESSIONID를 통해 서버가 식별한다고 위에서 언급했다. 중간 과정에서 클라이언트의 모든 요청을 가로채는 역할을 하는 것이 존재하는데, 그게 바로 스프링 시큐리티 인터셉터라는 놈이다.
스프링 시큐리티 인터셉터에 대한 자세한 이야기는 생략하고 제목에서 언급한 두 개념의 관계를 위해 어떤 연관성이 있는지 알아보자.
스프링 시큐리티 인터셉터를 구현하기 위해선 HandlerInterceptor 인터페이스에 존재하는 preHandle, postHandle 등을 구현해야 한다.
본 프로젝트에서는 SessionClearInterceptor라는 이름으로 클래스가 구현되어 있었다. 한 가지 특이한 점이 존재한다면, 최종적으로 세션을 파괴하는 것이 아닌 세션의 속성을 삭제한다.
조건에 따라 세션의 속성을 삭제하고, 새로운 세션을 생성하는 로직으로 구현되어 있는데 다른 페이지에서 세션이 유지될 수 있었던 것은 JESSIONID 자체를 삭제하는 것이 아니라, 세션 내부에 존재하는 속성을 삭제하고 새로이 생성했기 때문이다.
즉, 세션은 유지한 채로 페이지 이동 시 속성 값만 재설정하여 세션을 유지한다.
이슈로 맞이하였던 모달을 팝업하고 조건에 따라 분기하는 과정에서 위 두 개념이 사용되었다. 좀 더 자세하게 말하자면, 모달 HIDE 시 발생한 일이다.
앞서 말한 SessionClearInterceptor는 현재 처리 중인 클래스,메소드의 이름과 이전에 처리한 클래스,메소드의 이름을 통해 페이지의 변화가 일어났는지 파악한다. 같은 페이지라면 세션이 유지되고 다른 페이지라면 현재 사용 중인 세션의 속성을 삭제하고 새로이 생성하여 주입한다.
모달 HIDE 시 세션 속성이 SET 되지 않은 이유는 아래와 같다.
모달을 닫는 로직에는 클라이언트에서 서버로 요청하는 Request가 존재하지 않고 인터셉터는 추가적인 요청이 없기 때문에 JESSIONID의 속성을 삭제하고 나서 새로운 속성을 주입하지 않는다. 이와 같은 이유 때문에 JESSION ID가 유지되지 않아 세션에 존재하는 속성을 파악했을 때 NULL 값이 도출된 것이다.
그렇다면, 어떻게 해결할 수 있을까?
현재 도입한 방법으로는 window.location.reload() 를 사용한 것이다. 새로고침을 통해 클라이언트에서 서버로 요청을 보내고 인터셉터가 해당 요청을 가로채어가 세션의 속성을 부여할 수 있도록 하였다.
하지만, 새로고침은 화면의 깜박임을 통해 사용자에게 불편함을 초래할 수 있기 때문에 지양하여야 한다. 더 나은 방식을 고안할 필요가 있다.
'인실리코젠' 카테고리의 다른 글
[인실리코젠] Spring CRUD - 게시글 조회 구현 중 겪은 트러블 슈팅 (0) | 2024.06.17 |
---|---|
[인실리코젠] Spring Security + JWT + JPA (0) | 2024.03.15 |
[인실리코젠] Spring CRUD - 회원 가입 (0) | 2024.02.16 |
[인실리코젠] Spring CRUD 프로젝트 요구 사항 분석 및 데이터베이스 설계 (1) | 2024.02.16 |
[인실리코젠] Web Crawling - Finish (1) | 2024.02.02 |