Java 아키텍처·Spring 용어 사전
Spring 코어싱글톤 빈 · prototype · 무상태

빈 스코프

빈이 몇 개 만들어지고 얼마나 사는지. 기본은 컨테이너당 하나이며, 그래서 상태를 두면 안 된다.

빈이 몇 개 만들어지고 얼마나 사는지를 정하는 설정. 기본값이 만드는 결과가 크다.

종류

  • singleton — 컨테이너당 하나 (기본값)
  • prototype — 요청할 때마다 새 인스턴스
  • request — HTTP 요청당 하나 (웹)
  • session — HTTP 세션당 하나 (웹)

기본이 싱글톤이라서 따라오는 것 — 무상태여야 한다

// ❌ 싱글톤 빈에 상태를 뒀다 — 모든 요청이 이 필드 하나를 공유한다
@Service
class OrderService {
    private Long currentUserId;                 // 재앙
    public void process(Long userId) {
        this.currentUserId = userId;            // 다른 스레드가 곧바로 덮어쓴다
        // ... A 사용자의 요청이 B 사용자의 데이터를 본다
    }
}

// ✅ 상태는 지역 변수나 파라미터로
@Service
class OrderService {
    public void process(Long userId) { /* userId 를 넘겨 쓴다 */ }
}

"싱글톤 빈에 가변 필드를 두지 않는다" 는 Spring에서 가장 값비싼 사고를 막는 한 줄이다. 재현이 어렵고(동시 요청에서만 발생) 데이터가 섞여 나가므로 피해가 크다.

싱글톤에 프로토타입을 주입하면

@Service
class A {
    private final B b;      // B 가 prototype 이어도
    A(B b) { this.b = b; }  // A 가 만들어질 때 '한 번' 주입된다
}
// → 이후 계속 같은 B 인스턴스를 쓴다. 매번 새로 생기지 않는다
// 매번 새로 필요하면 조회 시점을 미룬다
@Service
class A {
    private final ObjectProvider<B> provider;
    void run() { B b = provider.getObject(); }   // 호출할 때마다 새 인스턴스
}

@Lookup 메서드 주입도 같은 목적이다.

프로토타입의 소멸 콜백은 호출되지 않는다

컨테이너는 prototype 빈을 '생성·주입' 까지만 관리한다

  • @PreDestroy 가 불리지 않는다
  • 자원을 쥐는 빈을 prototype 으로 두면 누수가 된다

GoF 싱글톤과 다르다

  • GoF 싱글톤 — JVM 당 하나. private 생성자 + static 인스턴스
  • Spring 싱글톤 — 컨테이너당 하나. 평범한 클래스이고 컨테이너가 하나만 만들 뿐
    • 테스트에서 new 로 여러 개 만들 수 있다

면접 함정

  • "프로토타입을 주입하면 매번 새 객체" → 싱글톤이 들고 있으면 고정된다.
  • "싱글톤이라 스레드 안전" → 반대다. 공유되므로 상태를 두면 위험하다.

웹 스코프와 프록시

// request 스코프 빈을 싱글톤에 주입하려면 프록시가 필요하다
@Component
@RequestScope                        // = @Scope(value="request", proxyMode=TARGET_CLASS)
class RequestContext { private String traceId; }

@Service
class OrderService {
    private final RequestContext ctx;    // 프록시가 주입된다
    // 실제 호출 시점에 '그 요청의' 인스턴스로 위임된다
}

프록시가 없으면 싱글톤이 만들어지는 기동 시점에 요청이 없어서 주입 자체가 실패한다.

상태가 필요하면 어디에 두나

요청 범위 값 (traceId · 로그인 사용자)

  • @RequestScope · ThreadLocal · Scoped Values (Java 25)

캐시 · 설정처럼 공유해도 되는 불변 값

  • 싱글톤 필드에 final 로 두면 안전하다

가변 상태

  • 싱글톤에 두지 않는다. 파라미터로 넘기거나 외부 저장소로

"불변이면 싱글톤 필드에 둬도 된다" 가 정확한 기준이다. 금지되는 건 가변 상태다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Spring 핵심 — IoC·DI·AOP