빈 스코프란?
지금까지 우리는 스프링 빈이 스프링 컨테이너의 시작과 함께 생성되어서 스프링 컨테이너가 종료될 때 까지 유지된다 고 학습했다. 이것은 스프링 빈이 기본적으로 싱글톤 스코프로 생성되기 때문이다. 스코프는 번역 그대로 빈이 존재할 수 있는 범위를 뜻한다
스프링은 다음과 같은 다양한 스코프를 지원한다.
- 싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다.
- 프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.
- 웹 스코프
- request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프이다.
- session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프이다.
- application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프이다웹 관련 스코프
빈 스코프는 다음과 같이 지정할 수 있다
@Scope("prototype")
@Component
public class HelloBean {}
수동 등록
@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
return new HelloBean();
}
프로토타입 스코프 - 싱글톤 빈과 함께 사용시 문제점
스프링 컨테이너에 프로토타입 스코프 빈을 요청하면 항상 새로운 객체 인스턴스를 생성해서 반환한다고 했지만, 싱글톤 빈과 함께 사용할 때는 의도한 대로 잘 동작하지 않으므로 주의해야 함
ObjectFactory, ObjectProvider
Provider로 문제 해결
지정한 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 제공하는 것 -> ObjectProvider
(ObjectFactory + 편의 기능 = ObjectProvider)
Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
웹 스코프
지금까지 싱글톤과 프로토타입 스코프를 학습했다. 싱글톤은 스프링 컨테이너의 시작과 끝까지 함께하는 매우 긴 스코 프이고, 프로토타입은 생성과 의존관계 주입, 그리고 초기화까지만 진행하는 특별한 스코프
웹 스코프의 특징
- 웹 스코프는 웹 환경에서만 동작한다.
- 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리한다. 따라서 종료 메서드가 호출된 다.
웹 스코프 종류
- request: HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴 스가 생성되고, 관리된다.
- session: HTTP Session과 동일한 생명주기를 가지는 스코프
- application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
- websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프
- 스프링 컨테이너에서 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를 찾는 방법을 알고 있다.
- 클라이언트가 myLogger.logic() 을 호출하면 사실은 가짜 프록시 객체의 메서드를 호출한 것이다. 가짜 프록시 객체는 request 스코프의 진짜 myLogger.logic() 를 호출한다.
- 가짜 프록시 객체는 원본 클래스를 상속 받아서 만들어졌기 때문에 이 객체를 사용하는 클라이언트 입장에서는 사실 원본인지 아닌지도 모르게, 동일하게 사용할 수 있다(다형성)
- 가짜 프록시 객체는 실제 request scope와는 관계가 없다. 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤 처럼 동작한다.
주의
- 마치 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 결국 주의해서 사용해야 한다.
- 이런 특별한 scope는 꼭 필요한 곳에만 최소화해서 사용해야하며, 무분별하게 사용하면 유지보수하기 어려워진다.
출처 : 김영한 스프링 핵심 원리
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] 8. 빈 생명주기 콜백 (0) | 2024.06.19 |
---|---|
[Spring] 7. 의존관계 자동 주입 (0) | 2024.06.19 |
[Spring] 6. 컴포넌트 스캔 (0) | 2024.06.18 |
[Spring] Section 5. 싱글톤 컨테이너 (0) | 2024.06.07 |
[Spring] Section 4. 스프링 컨테이너와 스프링 빈 (0) | 2024.06.06 |