Bean Scope

2026. 6. 6. 22:33·Backend/Spring Boot

Bean Scope 완전 정복

Scope가 뭔가요?

Scope = "이 객체를 얼마나 오래, 어디까지 공유할 것인가"

비유: 카페의 컵

싱글톤 = 카페 전체에서 컵 1개 공유 (모두가 같은 컵 사용)
프로토타입 = 손님마다 새 컵 제공
request  = 한 번 주문할 때마다 새 컵
session  = 한 손님이 앉아있는 동안 같은 컵 사용

각 Scope 상세 설명

1. Singleton (기본값)

@Service // 기본이 singleton
// @Scope("singleton") 생략 가능
public class OrderService {
    private int orderCount = 0; // ⚠️ 위험한 코드 (아래 설명)
}
앱 시작
  ↓
Spring: "OrderService 딱 1개만 만들게"
  ↓
컨테이너에 보관

사용자 A 요청 ──┐
사용자 B 요청 ──┼──→ 모두 같은 OrderService 인스턴스 사용
사용자 C 요청 ──┘

앱 종료될 때까지 이 1개가 계속 살아있음

중요한 주의점 - 상태를 가지면 안 됨

@Service
public class OrderService {

    // ❌ 절대 이렇게 하면 안 됨
    private int orderCount = 0;

    public void order() {
        orderCount++; // 사용자 A, B, C가 모두 같은 변수를 건드림
                      // → 동시성 문제 발생 (Race Condition)
    }

    // ✅ 상태를 메서드 안의 지역변수로만 써야 함
    public void order(OrderRequest request) {
        int localCount = 0; // 메서드 호출마다 새로 생성되는 지역변수 → 안전
        localCount++;
    }
}

사용 예: Service, Repository, Controller → 거의 모든 Spring Bean


2. Prototype

@Component
@Scope("prototype")
public class ReportGenerator {
    private List<String> logs = new ArrayList<>(); // 상태를 가져도 OK

    public void addLog(String log) {
        logs.add(log);
    }
}
사용자 A가 ReportGenerator 요청 → 새 인스턴스 생성 (인스턴스 #1)
사용자 B가 ReportGenerator 요청 → 새 인스턴스 생성 (인스턴스 #2)
사용자 C가 ReportGenerator 요청 → 새 인스턴스 생성 (인스턴스 #3)

각자 완전히 독립된 객체

핵심 주의점 - Spring이 소멸을 관리 안 함

Singleton: Spring이 생성 ~ 소멸 전부 관리
Prototype: Spring이 생성만 해주고 이후는 모름
           → @PreDestroy 콜백 호출 안 됨
           → 개발자가 직접 정리해야 함

사용 예: 요청마다 독립된 상태가 필요한 객체 (보고서 생성기, 장바구니 등)


3. Request

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST,
       proxyMode = ScopedProxyMode.TARGET_CLASS) // proxyMode 필수
public class RequestLogger {

    private String requestId = UUID.randomUUID().toString();

    public String getRequestId() {
        return requestId;
    }
}
HTTP 요청 1 들어옴 → RequestLogger 인스턴스 #1 생성
    요청 처리 중... (Controller → Service → Repository)
    이 요청 안에서는 항상 같은 #1 사용
HTTP 요청 1 끝남 → 인스턴스 #1 소멸

HTTP 요청 2 들어옴 → RequestLogger 인스턴스 #2 생성 (새로 생성)

사용 예: 요청 추적 ID, 요청별 로그 수집


4. Session

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION,
       proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart {

    private List<Item> items = new ArrayList<>();

    public void addItem(Item item) {
        items.add(item);
    }
}
사용자 A 로그인 → ShoppingCart #1 생성
    페이지 이동해도, 여러 요청을 해도 ShoppingCart #1 유지
    "상품 담기" → #1에 추가
    "결제하기" → #1에서 가져옴
사용자 A 로그아웃 (세션 만료) → ShoppingCart #1 소멸

사용자 B 로그인 → ShoppingCart #2 생성 (완전히 별개)
Request vs Session 차이:

Request: 요청 1번 = 1개 (페이지 새로고침하면 새 객체)
Session: 로그인 ~ 로그아웃 = 1개 (브라우저 닫을 때까지 유지)

면접 핵심 포인트

Q. Singleton Bean이 Prototype Bean을 주입받으면?

@Service // singleton
public class OrderService {

    @Autowired
    private ReportGenerator reportGenerator; // prototype이어야 하는데...

    public void createReport() {
        reportGenerator.generate(); // 매번 새 객체를 원하지만...
    }
}

문제 발생 과정:

앱 시작 시:
  Spring: "OrderService 만들어야지" (singleton이라 1번만)
    → "ReportGenerator도 주입해야지"
    → ReportGenerator 인스턴스 #1 생성 후 OrderService에 주입
    → 이 시점에 끝!

사용자 A가 createReport() 호출 → reportGenerator는 여전히 #1
사용자 B가 createReport() 호출 → reportGenerator는 여전히 #1
사용자 C가 createReport() 호출 → reportGenerator는 여전히 #1

Prototype인데 사실상 Singleton처럼 동작 → 버그!

해결 방법 1: ObjectProvider (권장)

@Service
public class OrderService {

    // ReportGenerator 자체를 주입받지 않고
    // "꺼내주는 공장"을 주입받음
    @Autowired
    private ObjectProvider<ReportGenerator> reportGeneratorProvider;

    public void createReport() {
        // 호출할 때마다 새 인스턴스를 꺼내옴
        ReportGenerator generator = reportGeneratorProvider.getObject();
        generator.generate();
    }
}
사용자 A가 createReport() 호출
  → getObject() 호출 → ReportGenerator #1 새로 생성
사용자 B가 createReport() 호출
  → getObject() 호출 → ReportGenerator #2 새로 생성
사용자 C가 createReport() 호출
  → getObject() 호출 → ReportGenerator #3 새로 생성

✅ 매번 새 객체!

해결 방법 2: @Lookup

@Service
public abstract class OrderService { // abstract로 선언

    public void createReport() {
        ReportGenerator generator = getReportGenerator(); // 호출마다 새 객체
        generator.generate();
    }

    @Lookup // Spring이 이 메서드를 오버라이딩해서 매번 새 Bean 반환하도록 조작
    protected abstract ReportGenerator getReportGenerator();
}

해결 방법 3: ApplicationContext 직접 사용 (비권장)

@Service
public class OrderService {

    @Autowired
    private ApplicationContext applicationContext; // 컨테이너 자체를 주입

    public void createReport() {
        // 컨테이너에서 직접 꺼냄
        ReportGenerator generator =
            applicationContext.getBean(ReportGenerator.class);
        generator.generate();
    }
}

Spring 컨테이너에 코드가 직접 의존하게 되어 테스트가 어려워지므로 비권장입니다.


세 방법 비교

방법 권장도 이유

ObjectProvider ✅ 가장 권장 Spring 표준, 테스트 용이
@Lookup △ 상황에 따라 클래스가 abstract여야 함
ApplicationContext ❌ 비권장 컨테이너 직접 의존, 테스트 어려움

전체 Scope 한 눈에 비교

생존 기간 (짧음 → 김)

Prototype  Request    Session    Singleton
  │          │           │           │
  │        요청 1번     로그인~      앱 실행~
매번      동안 유지    로그아웃     앱 종료
새 객체                동안 유지   동안 유지

사용 예:
독립 상태   요청 추적   장바구니    Service
필요한 객체   로그       세션 데이터  Repository

면접 답변 템플릿

"Singleton이 Prototype을 주입받으면 어떤 문제가 있나요?"

"Singleton Bean은 앱 시작 시 1번만 생성되기 때문에, 주입 시점에 Prototype Bean도 딱 1개만 생성되어 고정됩니다. 이후 Prototype Bean이 필요할 때마다 새 객체가 생성되길 기대하지만, 실제로는 처음 주입된 객체만 계속 재사용되어 사실상 Singleton처럼 동작합니다. 이를 해결하려면 ObjectProvider를 사용해 필요한 시점마다 컨테이너에서 새 인스턴스를 꺼내오도록 해야 합니다."

'Backend > Spring Boot' 카테고리의 다른 글

Builder Pattern  (0) 2026.06.06
DAO, DTO, VO, Entity  (0) 2026.06.06
SpringBoot 내부동작  (0) 2026.06.06
[Spring Boot] 공식문서 번역 - RESTful 웹 빌드하기  (5) 2025.02.04
[Spring Boot] 스프링을 처음할때 보기 좋은 공식문서 순서  (3) 2025.01.08
'Backend/Spring Boot' 카테고리의 다른 글
  • Builder Pattern
  • DAO, DTO, VO, Entity
  • SpringBoot 내부동작
  • [Spring Boot] 공식문서 번역 - RESTful 웹 빌드하기
mjwoon
mjwoon
  • mjwoon
    모시깽이 개발자
    mjwoon
  • 전체
    오늘
    어제
    • 분류 전체보기 (38)
      • Study notes (24)
        • 운영체제론 (10)
        • 컴퓨터 네트워크 (0)
        • 자연어처리 (7)
        • 데이터베이스 (0)
        • 객체지향개발론 (0)
        • 딥러닝 (0)
        • 데이터사이언스 (7)
      • Frontend (2)
        • React (2)
      • Backend (6)
        • Spring Boot (6)
      • Algorithm (5)
      • 핸즈온 머신러닝 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자료구조
    자바스크립트
    알고리즘
    재귀
    슬라이딩윈도우
    Nodejs
    JavaScript
    백준
    vscode
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
mjwoon
Bean Scope
상단으로

티스토리툴바