스프링

request 웹 스코프와 프록시

salmon16 2023. 7. 26. 17:10

웹 스코프는 웹 환경에서만 동작한다 그중 request 웹 스코프에 대해 알아보자.

 

Request 웹스코프는 HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프이며 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.

다음 그림을 보자

클라이언트 A와B는 싱글톤인 Controller와 Service빈을 공통으로 가지고 request scope빈은 개별로 다른 인스턴스를 HTTP 요청을 할 시에 할당되어 가진다.

 

request빈의 특징은 HTTP가 들어오고 나갈 때까지 유지되는 것이기 때문에 클라이언트 A가 Controller에서 request scope빈을 요청하고 그 후 Service에서 resquest scope빈을 요청을 또 하더라도 같은 인스턴스의 전용 request scope빈이 할당된다.

 

request빈은 UUID를 통해서 구분할 수 있다. UUID는 네트워크 상에서 고유성이 보장되는 id를 만들기 위한 표준 규약이다.

 

request scope 빈도 prototype scope 빈과 같게 싱글톤과 함께 사용하면 문제가 발생할 수 있다.

싱글톤에서 request scope 빈을 주입받으려고 하는 시점에는 HTTP request 요청이 없는 경우에 request scope빈도 생성되지 않아서 에러가 발생한다 이를 해결하기 위한 방법을 알아보자.

 

request scope빈 주입 시 에러 해결 방법

첫 번째로 prototype scope빈 해결방식과 같은 ObjectProvider을 사용하는 것이다.

public class LogDemoService {
	@Autowired
    final ObjectProvider<MyLogger> myLoggerProvider;
    public void logic(String id) {
        MyLogger myLogger = myLoggerProvider.getObject();
    }
}

위 코드에서 MyLogger는 request scope이다.

이렇게 하면 HTTP 요청이 들어오면 getObject()메서드를 통해서 할당받을 수 있다.

프록시 사용

두 번째 방법으로 프록시를 이용하는 것이다.

프록시를 사용하려면 @Scope에 옵션을 추가해 주어야 한다.

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)

proxyMode 부분을 추가해 주어야 한다. 적용대상이 인터페이스 이면 CLASS부분을 INTERFACES로 바꿔주면 된다.

이렇게 하면 MyLogger의 가짜 프록시 클래스를 만들어 다른 클래스에 HTTP요청이 없어도 주입시켜 준다.

프록시는 CGLIB라는 바이트코드 조작하는 라이브러리를 사용해서 만들어진 가짜 프록시 객체이다.

public class LogDemoService {
    final MyLogger myLogger;
    public void logic(String id) {
        myLogger.log("service id = " + id);
    }
}

프록시를 이용하면 MyLogger타입으로 바로 주입 받을 수 있다.

가짜 프록시 객체는 요청이 오면 그때 내부에 진짜 빈을 요청해서 넣어준다.

클라이언트는 가짜 프록시인지 진짜 request scope빈인지 구별할 수 없다.

그래서 클라이언트는 싱글톤 처럼 사용하는데  싱글톤과는 다르게 동작하기 때문에 주의해서 사용해야 한다.

 

출처 : 인프런 스프링 핵심 원리 - 기본 편  김영한