반응형

웹 스코프

  • 웹 환경에서만 동작한다.
  • 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리한다. 따라서 종료 메서드가 호출된다.

 

  • 웹 스코프 종류
  • request
    • HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈인스턴스가 생성되고, 관리된다.
    • 같은 HTTP 요청이면 같은 스프링 빈을 반환한다.
  • session
    • HTTP Session과 동일한 생명주기를 가지는 스코프
  • application
    • 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
  • websocket
    • 웹 소켓과 동일한 생명주기를 가지는 스코프

 

HTTP request 요청 당 각각 할당되는 request 스코프

 

  • 스프링 컨테이너에서 request 스코프 의존성 주입 시 오류가 발생할 수 있다.
    • request 스코프는 요청이 들어와야 생성되는데 스프링 컨테이너가 생성되는 시점에는 해당 빈이 컨테이너에 존재하지 않기 때문이다.
  • 이를 해결하기 위해서 Provider 또는 프록시 방식을 사용할 수 있다.
    • 두 가지 방식의 공통점은 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점이다.

 

  • Provider 사용
    • Provider를 이용해서 의존성 주입 시점을 실제로 요청이 들어와서 request 스코프 빈을 사용하는 시점까지 늦출 수 있다면 적절하게 의존성 주입이 가능하다.
    @Autowired
    private final ObjectProvider<MyLogger> myLoggerProvider;
    MyLogger myLogger = myLoggerProvider.getObject();

 

  • 프록시 방식 사용
    • 애노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체할 수 있다.
      • 이것이 바로 다형성과 DI 컨테이너가 가진 큰 강점
    • 의존성 주입 시점에 request 스코프 빈이 없어도 미리 가짜 프록시 클래스를 의존성 주입해준다. 그리고 실제 사용시점에 실제 객체를 찾는다.
      • CGLIB 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입한다.
    @Component
    @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class MyLogger {}

    • 프록시 객체 동작
    • 가짜 프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.
      • 가짜 프록시 객체는 내부에 진짜 myLogger를 찾는 방법을 알고 있다.
    • 클라이언트가 myLogger.logic() 을 호출하면 사실은 가짜 프록시 객체의 메서드를 호출한 것이다. 가짜 프록시 객체는 request 스코프의 진짜 myLogger.logic() 를 호출한다.
    • 가짜 프록시 객체는 원본 클래스를 상속 받아서 만들어졌기 때문에 이 객체를 사용하는 클라이언트 입장에서는 사실 원본인지 아닌지도 모르게, 동일하게 사용할 수 있다(다형성)
    • 가짜 프록시 객체는 실제 request scope와는 관계가 없다. 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤 처럼 동작한다.

 

  • 주의점
    • 마치 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 결국 주의해서 사용해야 한다.
    • 이런 특별한 scope는 꼭 필요한 곳에만 최소화해서 사용해야하며, 무분별하게 사용하면 유지보수하기 어려워진다.

반응형

+ Recent posts