JAVA/Spring MVC

Spring MVC에서의 빈 관리 (SessionScope)

kooby 2020. 4. 27. 18:42

session이 뭘까? 

브라우저가 최초로 서버에 요청을 하게 되면 브라우저당 하나씩 메모리 공간을 서버에서 할당하게 된다. 이 메모리영역은 브라우저당 하나씩 지정되고 요청이 새롭게 발생하게 되더라도 같은 메모리 공간을 사용하게 된다.

이러한 공간을 session이라고 한다. session은 브라우저가 종료될 때까지 서버에서 사용이 가능하다.

 

SessionScope는 브라우저가 최초 요청을 발생시키고 브라우저를 닫을 때 까지의 영역을 가리킨다. SessionScope에서는 Session영역에 저장되어 있는 데이터나 객체를 자유롭게 사용할 수 있다. 

 

 

 

1. HttpSession

 

 

Session은 새로운 요청이더라도 브라우저만 유지되면 보존되는 공간이다.

Request였다면 새로운 요청을 할 때마다 새로운 객체가 생성되어 위와 같이 정의한다면 sessionScope메소드의 Request객체와 result메소드의 Request객체는 달랐을 것이다. (그래서 브라우저에게 요청하기 전에 서버단에서 데이터를 사용하기 위해서 forward를 이용함으로써 같은 객체를 사용할 수 있었다!)

 

Session은 같은 웹 브라우저 내에서의 요청이라면 sessionTest.jsp에서 사용하는 객체나 result.jsp에서 사용하는 객체가 같을 것이다.

 

또 한가지, SpringMVC에서는 HttpSession이라는 클래스를 제공한다. 위에 주석처리 되어 있는 코드를 보면 우리는 JSP Servlet를 이용할 때에도, Request를 이용하여 데이터를 사용할 때에도 이와 같은 방법으로 request.getSession()을 통해 세션을 가지고 왔고 그 세션에 저장되어 있는 객체를 getAttribute를 이용하여 가져와서 사용하였다.

HttpSession을 이용하면 조금 간단하게 매개변수로 session을 받아와서 사용할 수 있다. 

 

 

 

 

2. Redirect와 Forward

 

그렇다면 Redirect와 Forward는 Session객체에 영향을 줄까? 결론부터 말하면 영향을 주지 않는다. 브라우저만 바뀌지 않으면 session영역은 유지되기 때문이다.

 

 

위와 같이 Redirect요청을 반환하는 메소드 한개와 Forward요청을 반환하는 메소드 한개를 각각 정의 한후 result메소드에는 session에 저장된 data1을 출력할 수 있도록 해보았다.

결과는 아무 영향을 받지 않고 각각의 결과를 잘 출력하는 것을 볼 수 있었다. 

 

 

 

 

3. @SessionAttribute

 

Session영역에 저장되어 있는 객체를 사용할 때 메소드의 매개변수로 @SessionAttribute를 설정하면 Session영역에 설정되어 있는 빈을 주입받을 수 있다. 

 

 

@SessionAttribute("빈이름")은 빈이름으로 만들어져있는 객체를 주입받는것이지 새로운 객체를 주입하여 빈 이름으로 session에 저장되는 것은 아니다. @ModelAttribute랑은 좀 다르다!

"data1"이라는 이름으로 등록되어 있는 session객체를 찾아서 DataBean1 bean에 넣어주는 것이다. 

getAttribute대신 매개변수로서 받을 수 있다고 간단하게 생각하면 될 것 같다. 

 

 

 

 

4. @SessionAttributes

 

3번의 @SessionAttribute와는 조금 다르다..! 

@ModelAttribute의 경우 @ModelAttribute를 통해 주입 받는 빈은 자동으로 Request영역에 저장이 되고 Request 영역으로부터 주입을 받게 된다. 이때 @ModelAttribute를 통해 주입을 받는 빈을 @SessionAttributes로 지정해주면 Request영역이 아닌 Session영역에 저장이 되고 Session영역으로부터 주입을 받을 수 있다.

 

여기서 주의할 점은 @ModelAttribute를 활용하여 객체를 생성해 반환하는 메소드를 반드시 작성해 주어야 한다는 것이다.

 

 

위와 같이 @SessionAttributes("session")이라고 등록하고 @ModelAttribute("session")이라고 등록을 하면, @ModelAttribute에서 session이라는 이름으로 세션을 주입하면, 해당 이름과 같은 SessionAttributes를 찾아서 Request영역이 아닌 Session영역에 저장을 해준다.

 

 

이렇게 session이란 이름으로 ModelAttribute를 사용하면 @SessionAttributes에 의해서 Session영역에 저장이 되게 되고, 주소와 매핑되어져 있는 메소드가 실행이 될때 빈 객체에 주입을 해주게 된다. 

 

 

Session영역에 저장된것을 확인하기 위해서 sessionScope를 사용해보았다.

위와 같이 View를 코딩하면 정상적으로 데이터 값이 출력되는 것을 알 수 있었다.

 

 

 

 

5. SessionScope 빈 주입

 

타입을 통한 주입과 이름을 통한 주입을 한번에 예제로 해보도록 하겠다.

 

자바 빈 설정파일에 위와 같이 빈을 두개 설정해주었다. 한개는 타입을 기반으로 사용하기 위해 빈을 설정해주었고, 한개는 byname이라는 이름을 기반으로 사용하기 위해 빈을 설정해주었다.

 

타입을 통한 주입

 

 

이름을 통한 주입

 

타입을 통한 주입은 @Autowired를 사용하여 빈을 주입해주었고, 이름을 통한 주입은 @Resource(name="")을 사용하여 빈을 주입해주었다. 두가지 사용법은 동일하다. 

주입된 빈은 주입만 이루어진 것이므로 session영역에는 저장되지 않는다. View에서 사용하려면 Model을 이용해야 한다.

 

 

 

xml 파일에 빈을 등록할때는 위와 같이 해주면 되겠다.

 

 

 

 

 

 

이번에는 컴포넌트 어노테이션을 이용해서 주입을 할때에는 session을 어떻게 사용하는지 해보자.

 

 

@Component와 @SessionScope를 빈 클래스에 위와 같이 선언해준다. 그리고 컴포넌트 스캔을 설정해주면 된다.

 

 

자바 빈 설정파일의 ComponentScan
servlet-context.xml의 ComponentScan

 

자바 빈 설정파일과 xml의 컴포넌트 스캔 등록방법은 다음과 같다. bean객체가 있는 패키지를 등록해주면 된다.

@Component는 기본적으로 타입을 통한 객체 자동주입이 때문에 위의 @Autowired를 사용한 예제와 똑같이 해주면 된다.

 

 

 

 

 

 

그. 런 .데.

 

 

xml파일에서 빈을 등록해주면, 오류가 난다... 왜그럴까?

SessionScope는 웹 브라우저가 최초 요청을 보낼 때 빈 객체가 주입되게 된다. 그런데 xml방식같은 경우에는 서버가 가동될 때 무조껀 주입을 먼저 시도하려고 한다. xml을 로딩할 때 객체가 바로 생성되도록 한다는 뜻이다. 그래서 오류가 난다.

 

타입을 통한 자동주입(@Autowired)를 할 때, @Lazy를 해주면 (xml파일에 lazy-init="true"해주어도 되겠다.) 로딩과 동시에 객체를 바로 생성하지 않고, 객체를 가져올 때 주입을 시도한다.

즉, @RequestScope의 경우 새로운 요청이 발생하였을 때 주입을 시도하기 때문에 오류를 피할 수 있고,

@SessionScope의 경우도 웹 브라우저가 최초 요청을 보낼 때 주입을 시도하기 때문에 오류를 피할 수 있다.