빈 스코프(bean scope)는 스프링 컨테이너가 빈 인스턴스를 언제 만들고 얼마나 오래 유지하는지를 정한다. 기본값은 싱글턴이다.
| 스코프 | 인스턴스 | 쓰임 |
|---|---|---|
| singleton (기본) | 컨테이너당 하나 | 서비스·리포지터리 대부분 |
| prototype | 요청(주입·조회)할 때마다 새로 | 상태를 가진 일회성 객체 |
| request | HTTP 요청마다 | 요청 단위 정보 |
| session | HTTP 세션마다 | 사용자별 장바구니 같은 상태 |
| application | 서블릿 컨텍스트당 하나 | 앱 전체 공용 값 |
싱글턴 빈은 상태를 갖지 않는다
싱글턴 빈 하나를 여러 요청 스레드가 동시에 쓴다. 빈에 변경 가능한 필드를 두면 두 요청이 같은 값을 덮어쓰는 경쟁 상태(race condition)가 생긴다(예: 두 사용자가 같은 좌석을 동시에 예약).
@Service
public class ReservationService {
private int lastSeat; // 위험: 모든 요청이 공유
public void reserve(int seat) { /* ... */ }
}- 서비스는 불변 필드(주입받은 협력 객체)만 두고, 요청별 값은 메서드 지역 변수나 파라미터로 다룬다
- 동기화로 막을 수는 있지만 복잡도와 성능 비용이 커서 보통 설계로 피한다
프로토타입을 싱글턴에 주입하면
싱글턴이 생성될 때 프로토타입 빈을 한 번 주입받고 끝이라, 그 뒤로는 계속 같은 인스턴스를 쓴다. 매번 새로 필요하면 ObjectProvider<T>로 꺼내 쓰거나 메서드 주입(method injection)을 쓴다.
웹 스코프
@RequestScope, @SessionScope, @ApplicationScope는 웹 환경에서만 쓸 수 있다. 싱글턴에 주입할 때는 스코프 프록시(scoped proxy)가 대신 들어가 실제 호출 시점의 요청·세션 인스턴스로 연결해 준다(스프링 프록시).
- request 스코프 빈 생성은 매 요청마다 일어나므로 무거운 초기화를 넣지 않는다
- session 스코프에 큰 데이터나 민감 정보를 두면 서버 메모리와 보안 부담이 커진다. 서버를 여러 대로 늘리면 세션 공유도 필요하다(세션 인증)
"하나만 둔다"는 결정의 일반론은 싱글턴 패턴을 본다. 주입 방식은 의존성 주입 (DI)에서 다룬다.
출처: Spring Framework 문서: Bean Scopes · 싱글턴 빈과 프로토타입 빈의 상호작용 · 스코프 빈을 의존성으로 주입하기