-
웹 스코프와 프록시스프링/스프링 기본이론 2023. 2. 2. 14:58
웹 스코프 종류
request : HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프로 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.
session : HTTP Session과 동일한 생명주기를 가지는 스코프
application : 서블릿 컨텍스트와 동일한 생명주기 가지는 스코프
websocket : 웹 소켓과 동일한 생명주기를 가지는 스코프
웹 스코프중에 제일 많이 쓰이는 request에 대해서 알아볼 것이다. 나머지는 비슷하기도 하고, request가 가장 많이 쓰이는 것이기 때문이다.
스코프의 로그를 관찰하기 위해 MyLogger를 만들어준다.
@Component @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) public class MyLogger { private String uuid; private String requestURL; public void setRequestURL(String requestURL) { this.requestURL = requestURL; } public void log(String message) { System.out.println("[" + uuid + "]" + "[" + requestURL + "] " + message); } @PostConstruct public void init() { uuid = UUID.randomUUID().toString(); System.out.println("[" + uuid + "] request scope bean create: " + this); } @PreDestroy public void close() { System.out.println("[" + uuid + "] request scope bean close: " + this); } }
uuid라는 랜덤 변수를 만들어주고, request를 통해 하나의 스코프로 동작하는지 확인할 것이다. 그리고 @PostConstruct와 @PreDestroy도 잘 작동하는지 확인할 수 있다.
스코프와 프록시
@Scope 안에 proxyMode = scopeProxyMode.TARGET_CLASS라는 부분이 있는데, 우리가 등록한 MyLogger 클래스가 아니라 스프링 컨테이너에 별도로 생성된 프록시 객체가 등록된 것이다. 이후에 조회를 하더라도 프록시 객체가 등록된다.
프록시 객체는 실제 요청이 오면 그때 내부에 진짜 빈을 요청하는 위임 로직이 들어있다.
아래의 myLoggic.logic()은 프록시 객체의 메서드를 호출한 것이고, 프록시 객체가 진짜 request를 호출하는 것이다. 하지만 싱글톤이랑 다른 개념이기 때문에 특별한 스코프는 꼭 필요한 곳에서 최소화해서 사용해야지 유지보수가 된다.
request는 여러 사용자가 동시에 요청을 할 지라도 uuid를 만들어서 다른 빈을 주는 것이고, 모든 사용자는 각각 다른 빈을 사용해서 웹 스코프를 사용하게 된다.
RequestMapping("log-demo") @ResponseBody public String logDemo(HttpServletRequest request) { String requestURL = request.getRequestURI().toString(); myLogger.setRequestURL(requestURL); myLogger.log("controller test"); logDemoService.logic("testId"); return "OK"; }
log-demo url로 들어가면 요청당 하나의 웹 스코프를 사용하는 것을 확인할 수 있다.
콘솔 결과창
[d9a4ef04-ab5f-4001-8c48-d53200c240d1] request scope bean create: hello2.core.common.MyLogger@37c29317 [d9a4ef04-ab5f-4001-8c48-d53200c240d1][/log-demo] controller test [d9a4ef04-ab5f-4001-8c48-d53200c240d1][/log-demo] service id = testId [d9a4ef04-ab5f-4001-8c48-d53200c240d1] request scope bean close: hello2.core.common.MyLogger@37c29317
요청이 시작할때부터 끝날때까지 하나의 uuid가 계속 유지되는 것을 확인할 수 있다.
[0b7b5b5d-7389-411f-ad54-18edcfa427e3] request scope bean create: hello2.core.common.MyLogger@4e87944d [0b7b5b5d-7389-411f-ad54-18edcfa427e3][/log-demo] controller test [0b7b5b5d-7389-411f-ad54-18edcfa427e3][/log-demo] service id = testId [0b7b5b5d-7389-411f-ad54-18edcfa427e3] request scope bean close: hello2.core.common.MyLogger@4e87944d // user1 [a6100aa7-f124-47e4-a5ae-df763d873a8d] request scope bean create: hello2.core.common.MyLogger@7a366700 [a6100aa7-f124-47e4-a5ae-df763d873a8d][/log-demo] controller test [a6100aa7-f124-47e4-a5ae-df763d873a8d][/log-demo] service id = testId [a6100aa7-f124-47e4-a5ae-df763d873a8d] request scope bean close: hello2.core.common.MyLogger@7a366700 // user2
여러번 실행하면 사이클마다 uuid가 달라지는 것을 확인할 수 있다.
이렇게 로그를 출력하는 것은 스프링 인터셉터나 서블릿 필터같은 곳에서 하는게 좋은데, 일단은 이렇게 간단하게 구현한 것이다.
'스프링 > 스프링 기본이론' 카테고리의 다른 글
프로토타입 스코프 (0) 2023.02.01 어노테이션을 직접 만들기 (0) 2023.02.01 빈 생명주기 콜백 (0) 2023.02.01 빈이 2개 이상일 경우에 의존관계 주입 (0) 2023.02.01 의존관계 자동 주입 (0) 2023.01.31