스프링 빈 스코프란 무엇일까?
스프링 빈 스코프는 스프링 컨테이너에서 관리되는 빈의 생명 주기와 활용 범위를 정의하는 개념이다. 빈 스코프는 빈이 생성되는 시점, 빈이 사용되는 범위, 빈이 소멸되는 시점 등을 결정한다.
스프링 빈 스코프 종류
싱글톤
- 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다.
- 싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다.
프로토타입
- 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.
- 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.
- 프로토타입 빈을 관리할 책임은 프로토타입 빈을 받은 클라이언트에 있다. 때문에 @PreDestroy 같은 종료 메서드가 호출되지 않는다.
웹 관련 스코프
- 웹 환경에서만 동작한다.
- 웹 스코프는 프로토타입과 다르게 해당 스코프의 종료시점까지 스프링이 관리한다.
- request: HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리된다.
- session: HTTP Session과 동일한 생명주기를 가지는 스코프
- application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
- websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프
빈 스코프 선언
// 자동 등록
@Scope("prototype")
@Component
public class HelloBean {
// Bean 내용
}
// 수동 등록
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public HelloBean helloBean() {
return new HelloBean();
}
}
스프링 빈 스코프 활용
스프링 빈 스코프는 빈의 생명 주기와 활용 범위를 제어하여 코드의 효율성과 유연성을 높일 수 있다.
다음은 스프링 빈 스코프 활용 예시이다.
스코프 | 활용 |
싱글톤 | 데이터베이스 연결, 서비스 객체 등 애플리케이션 전체에서 공유해야 하는 빈을 생성할 때 |
프로토타입 | 매번 새로운 값을 생성해야 하는 빈 예를 들어 랜덤 숫자 생성기 등을 생성할 때 |
리퀘스트 | 사용자 요청마다 새 빈을 사용해야 하는 경우 예를 들어 사용자 세션 정보를 저장하는 빈 등을 생성할 때 |
세션 | 사용자 세션 동안 유지해야 하는 빈 예를 들어 사용자 장바구니 정보 등을 저장하는 빈 등을 생성할 때 |
어플리케이션 | 서버 클러스터 환경에서 모든 서버에서 공유해야 하는 빈 예를 들어 시스템 설정 정보 등을 저장하는 빈 등을 생성할 때 |
프로토타입 빈 사용 시 주의 사항
싱글톤 빈이 프로토타입 빈을 의존하는 경우, 싱글톤 빈은 항상 처음 생성된 프로토타입 빈을 참조하게 된다. 이는 의도하지 않은 동작을 초래할 수 있고 메모리 누수로 이어질 수도 있다.
해결법
1. Provider 패턴 사용
Provider 인터페이스를 사용하여 프로토타입 빈을 요청 시마다 생성할 수 있다. Spring에서는 ObjectProvider를 사용하여 이 패턴을 구현할 수 있다.
@Component
public class SingletonBean {
private final ObjectProvider<PrototypeBean> prototypeBeanProvider;
@Autowired
public SingletonBean(ObjectProvider<PrototypeBean> prototypeBeanProvider) {
this.prototypeBeanProvider = prototypeBeanProvider;
}
public void someMethod() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
// 프로토타입 빈을 사용
}
}
2. FactoryBean 사용
FactoryBean을 사용하여 매번 새로운 프로토타입 빈 인스턴스를 반환할 수 있다.
@Component
public class PrototypeBeanFactory implements FactoryBean<PrototypeBean> {
@Override
public PrototypeBean getObject() throws Exception {
return new PrototypeBean();
}
@Override
public Class<?> getObjectType() {
return PrototypeBean.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
@Configuration
public class AppConfig {
@Bean
public SingletonBean singletonBean() {
return new SingletonBean();
}
@Bean
public FactoryBean<PrototypeBean> prototypeBean() {
return new PrototypeBeanFactory();
}
}
3. 다른 스코프 사용
필요에 따라 다른 스코프를 사용하는 것도 하나의 방법이다.
ObjectProvider
Object Provider는 스프링 프레임워크에서 제공되는 빈 주입(Dependency Injection) 도구이다. Object Provider는 빈을 직접 주입하는 대신, 빈을 얻을 수 있는 팩토리를 제공한다. 이를 통해 코드에서 빈을 직접 참조하지 않고도 빈을 사용할 수 있다.
Object Provider의 장점
- 빈과 코드 사이의 의존성을 분리하여 코드의 유연성을 높인다.
- 테스트 코드에서 쉽게 빈을 모킹(mocking)할 수 있도록 한다.
- 코드에서 빈 생성 코드를 제거하여 코드를 간결하게 만들 수 있다.
@Service
public class MyService {
@Autowired
private ObjectProvider<MyRepository> repositoryProvider;
public void doSomething() {
MyRepository repository = repositoryProvider.getObject();
// repository를 사용하는 코드
}
}
프록시 모드
@Scope 어노테이션의 proxyMode 속성을 사용하여 프록시 모드를 설정할 수 있다. 프록시 모드를 설정하면 빈 스코프가 지정하는 빈 스코프가 지정하는 빈 생성 방식 대신 프록시 객체를 생성하여 주입한다.
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
// 인터페이스라면 ScopedProxyMode.INTERFACES
public class MyService {
// ...
}
동작 정리
- CGLIB 라이브러리를 사용한다.
- 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 들어있다.
- 프록시 객체는 스코프와는 관계가 없다.
- 내부에 단순한 위임 로직만 있고, 싱글톤 처럼 동작한다.
특징
- 프록시 객체 덕분에 클라이언트는 마치 싱글톤 빈을 사용하듯이 편리하게 request scope를 사용할 수 있다.
- Provider를 사용하든, 프록시를 사용하든 핵심 아이디어는 진짜 객체를 조회 시점까지 지연처리 한다는 점이다.
주의점
- 마치 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 결국 주의해서 사용해야 한다.
- 이런 특별한 scope는 꼭 필요한 곳에만 최소화해서 사용하자, 무분별하게 사용하면 유지보수하기 어려워진다.
728x90
'JVM > SpringMVC' 카테고리의 다른 글
[SpringMVC] 스프링 이벤트 시스템 (0) | 2024.08.10 |
---|---|
CORS와 Preflight Request (0) | 2024.03.09 |
요청 처리와 스레드풀 (0) | 2023.12.20 |
Spring WebSocket & STOMP (0) | 2023.12.15 |