스프링 빈 스코프
스프링에서 싱글톤과 프로토타입 빈 스코프를 제공하고 있으며, 스프링 MVC 웹 애플리케이션을 사용할 경우 웹 스코프를 제공한다.
싱글톤
- 싱글톤 빈은 스프링 컨테이너에서 한 번만 생성되며, 컨테이너가 사라질 때 제거된다.
- 생성된 하나의 인스턴스는 Spring Beans Cache에 저장되고, 해당 빈에 대한 요청과 참조가 있으며 캐시된 객체를 반환한다. 하나만 생성되기 떄문에 동일 참조를 보장한다.
- 기본적으로 모든 빈은 스코프가 명시적으로 지정되지 않으면 싱글톤이다.
- 대상 클래스에 @Scope("singletone")을 붙이면 된다.
- 싱글톤으로 적합한 객체는 아래와 같다.
- 상태가 없는 공유 객체
- 읽기 전용으로만 상태를 가진 객체
- 쓰기가 가능한 상태를 지니면서도 사용 빈도가 매우 높은 객체
- 동기화 전략이 필요하다.
프로토타입
- 프로토타입 빈은 DI가 발생할 때마다 새로운 객체가 생성되어 주입된다.
- 빈 소멸에 스프링 컨테이너가 관여하지 않고, GC에 의해 빈이 제거된다.
- 대상 클래스에 @Scope("prototype")을 붙이면 된다.
- 프로토타입으로 적합한 객체
- 사용할 때마다 상태가 달라져야 하는 객체
- 쓰기가 가능한 상태가 있는 객체
싱글톤 빈과 프로토타입 빈을 같이 사용할 때 생기는 문제
- 프로토타입 객체가 싱글톤 객체를 가지고 있는것은 문제가 되지 않는다.
- 반대로 싱글톤 객체가 프로토타입 객체를 가지고 있는 경우, 의도한 것과 다른 결과를 낼 수 있다.
- 싱글톤 빈으로 생성되는 시점에 프로토 타입 빈이 생성되어 있기 때문에 싱글톤 빈 내부의 프로토타입 빈을 호출하게 되면 매번 같은 값을 가져오게 된다.
웹 스코프
- 스프링이 사용하는 싱글톤 스코프는 스프링 컨테이너의 시작부터 끝까지 함께하는 스코프이고, 프로토타입 스코프는 생성과 의존 관계 주입 및 초기화까지만 진행하는 스코프이다.
- 웹 스코프는 웹 환경에서만 동작하는 스코프이며 프로토타입과 다르게 특정 주기가 끝날 때까지 관리를 해준다. 따라서 @PreDestroy와 같이 소멸 콜백이 호출된다는 특징이 있다.
- 웹 스코프의 종류
- Request
- HTTP 요청 하나가 들어오고 나갈때까지 유지되는 스코프
- 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.
- Session
- HTTP Session과 동일한 생명 주기를 가지는 스코프
- Application
- 서블릿 컨텍스트와 동일한 생명 주기를 가지는 스코프
- WebSocket
- 웹 소켓과 동일한 생명 주기를 가지는 스코프
- Request
스프링 빈의 생명 주기
싱글톤 빈
싱글톤 빈의 생명 주기는 다음과 같다.
- 스프링 컨테이너 생성
- 스프링 빈 생성
- 의존관계 주입
- 초기화 콜백
- 사용
- 소멸 전 콜백
- 스프링 종료
스프링 컨테이너가 생성되고, 스프링 빈이 등록되어 의존 관계가 주입되는 사실은 익숙하지만, 소멸 전 콜백에 대해서 알아보자.
@Component
public class OrderServiceImpl implements OrderService {
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(int age, String itemName, int itemPrice) {
int discountPrice = discountPolicy.discount(age, itemPrice);
return new Order(itemName, itemPrice, discountPrice);
}
@PostConstruct
public void init() {
System.out.println("초기화 콜백입니다.");
}
@PreDestroy
public void close() {
System.out.println("소멸 전 콜백입니다.");
}
}
위 코드와 같이 @PostConstruct를 사용하면 초기화 콜백이 호출되고, @PreDestroy를 호출하면 소멸전 콜백이 호출된다.
프로토타입 빈
프로토 타입 빈은 스프링 컨테이너가 빈 생성까지만 관리하고, 그 이후에는 제어권이 사라진다.
- 스프링 컨테이너 생성
- 스프링 빈 생성
- 의존 관계 주입
- 초기화 콜백
- 사용
- GC에 의한 수거
싱글톤 빈은 Thread-safe한가?
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
싱글톤 패턴은 위와 같으며, 전체 애플리케이션 중 단 한번만 초기화되어 애플리케이션이 종료될 때까지 메모리에 상주하게 된다.
만약 싱글톤이 상태를 갖게 되면 멀티쓰레드 환경에서 동기화 문제가 발생할 수 있다.
스프링에서는 별다른 설정을 하지 않을 경우 디폴트가 싱글톤으로 빈이 관리된다. 그런데, 싱글톤 빈을 사용할 때 private 생성자, static 변수, static 메서드를 정의하지 않고도 싱글톤으로 사용한다.
그래서 간혹 싱글톤 빈은 상태를 가져도 Thread-safe할 것이라는 착각을 하는 경우가 있다.
결론은 스프링은 싱글톤 레지스트리를 통해 private 생성자, static 변수 등의 코드 없이 비즈니스 로직에 집중하고 테스트 코드에 용이한 싱글톤 객체를 제공해주는 것 뿐이지, 동기화 문제는 우리가 처리해야한다.
만약 싱글톤 빈이 상태를 갖게되고, 아무런 동기화 처리를 하지 않는다면 멀티 쓰레드 환경에서 부작용이 발생할 수 있다.
출처
https://taes-k.github.io/2020/06/14/spring-bean-scope-lifecycle/
Scope에 따른 Spring bean life-cycle
Spring bean bean의 life-cycle을 알아보기에 앞서서 bean의 개념부터 간단하게 알아보도록 하겠습니다. (해당 포스팅 내용은 정확한 내용 전달을 위해 Spring doc 내용을 발췌 번역한 내용임을 알립니다. -
taes-k.github.io
'🍃Spring' 카테고리의 다른 글
[Spring] IoC와 DI (2/2) (0) | 2023.05.29 |
---|---|
[Spring] IoC와 DI (1/2) (0) | 2023.05.27 |
[Spring] 스프링 빈 (1/2) (0) | 2023.05.26 |
[Spring] 테스트 클렌징시 deleteAll()을 사용할 때의 주의점 (0) | 2023.05.13 |
[Spring] WebMvcTest에서 발생하는 SpringSecurity 의존성 문제 해결하기 (0) | 2023.04.19 |