스프링 컨트롤러와 request scope관한 이메일이 왔습니다.

...

제가 느끼고 있는 궁금증은 Controller 사용시 bean scope에 관한 부분입니다.

몇번의 프로젝트에서  SpringMVC를 이용하여 프로젝트를 했었는데요.
하나의 Controller에서 요청을 처리를 하기 위해 MultiActionController를 사용했습니다.
 
BaseController를 정의해서 BaseController가 MultiActionController를 상속받도록 만들었고,

모든 Controller는 BaseController를 상속 받아 쓰는 형식으로 구조를 잡았습니다.
 
BaseController에는 handleRequestInternal() 메소드를 오버라이드 해서 모든 request 값을

파싱하여 Map에 담도록 해놓았구요. (map에서 값을 꺼내 요청을 처리하도록 말이죠.)
 
테스트를 위해 Controller 내에서 sleep() 을 준 뒤, 몇개의 요청을 날려보면
가장 나중에 요청된 정보로 앞의
정보들이 변경되더군요.
아마도 scope이 singleton이라 그런것 같더군요.
그래서 빈 설정시에 Controller에 대한
scope을 모두 request로 바꿔줬습니다.
 
<bean id="memberController" class="MemberController"
scope="request">
 
이렇게 바꾸어주니 이전과 같은 현상은 발생하지 않더군요.
과연 이렇게 하는 것이 맞는 것인지, 아니면 BaseController를 scope="request"로 만들면 그걸

상속받는 다른 빈도 request가 되는 것인지 정확한 판단이 서질 않더군요.
제가 알기로는 Spring에서 Controller 이용시 threadsafe 한 설계는 개발자의 몫이라고
들었습니다.
어디를 봐도 정확한 가이드가 나와있지 않아서 혼자 헤매다 이렇게 메일을 드리게 되었습니다.
...


그리고 다음과 같이 답변해드렸습니다.

[#M_ more.. | less.. |

흠.. 일단 MemberController에 request를 붙이는 것은 아닌거 같습니다.
때네세요. request scope는 그런 용도가 아닙니다. 컨트롤러 객체를 매번 생성하는 것은 시스템의 효율이 떨어집니다.

위에서 발생한 문제는 짐작하신 내용이 맞는거 같습니다.
BaseController가 Threadsafe하지 않아서 생기는 문제 같습니다.

일단은.. BaseController의 이름은 BaseMultiActionController(BMAC)가 되는게 좋겠구요.

먼저 문제의 원인을 살펴보죠.

MultiActionController
의 handleRequestInternal을 오버라이딩해서 request 파라미터 값들을 맵핑해서 맵에다가 담아두고 그것들을
BMAC의 하위 클래스들에거 써내서 사용한다는 말씀이지요? 그 맵은 당연히 멤버변수겠지요? 이 때 그 map 객체는 어떻게
생성하나요?

class BMAC extends MAC {
   protected Map paramMap = new HashMap();
}

이렇게 되어 있나요? 자 이랬을 때, MAC 객체를 싱글톤으로 등록해두면, paramMap 객체도 한 번만 생성하겠죠. 그래서 원하는 결과를 얻지 못한 것입니다.

대신 request라는 scope은 매 요청이 들어올 때마다 새로운 객체를 만들어서 제공해주는 scope인데, 컨트롤러 객체를 그런식으로 생성하는 건 좀 비효율적이죠.

이렇게 하시는건 어떨까요? map 을 bean으로 등록하고 컨트롤러는 싱글톤으로 등록하고 해당 map 객체를 request scope의 빈으로 등록하시는 겁니다.

그러면
1. 컨트롤러는 싱글톤이라 효율적입니다.
2. map은 매 요청마다 새로 만들어서 가져오기 때문에 원하는 결과를 얻을 수 있습니다.

<bean id="memberController" class="whiteship.MemberController">
    <property name="paramMap" ref="paramMa" />
</bean>

<bean id="paramMap" class="java.util.HashMap" scope="request" />

이런식으로하면 되겠죠?

_M#]
request scope 빈을 써본지가 까마득한데 이런 경우에 유용하게 쓸 수 있겠네요. 내용 공유를 허락해주셔서 감사합니다.