관리 메뉴

Rootable의 개발일기

빈 스코프 본문

Spring

빈 스코프

dev-rootable 2023. 5. 26. 12:30

📌 빈 스코프 종류

 

스코프(Scope)란 빈이 존재할 수 있는(active) 범위를 말한다.

 

1. 싱글톤 스코프

기본적으로 스프링 빈은 싱글톤으로 생성되므로, default scope로 보면 된다. 싱글톤처럼 스프링 컨테이너의 생성부터 종료까지 유지되는 가장 넓은 범위의 스코프이다.

 

2. 프로토타입 스코프

프로토타입 빈매번 요청할 때마다 새로 생성되는 빈(매번 참조값이 다름)이다. 해당 빈은 프로토타입 스코프 범위를 따르는데, 스프링 컨테이너가 빈의 생성, 의존관계 주입, 초기화까지만 관여하고 더 이상 관리하지 않는 매우 짧은 범위의 스코프이다. 그래서 @PreDestroy와 같은 종료 메서드가 호출되지 않는다.

 

3. 웹 스코프

웹 요청(HTTP 요청)이 들어오고 나갈 때까지 유지되는 스코프

 

📌 프로토 타입 빈을 싱글톤 빈과 함께 사용 시 발생하는 문제점

 

# 상황

 - 싱글톤 빈에서 프로토타입 빈을 의존관계 주입을 통해 받는 상황

 - 해당 프로토타입 빈은 카운팅 변수가 있음

 - Client는 프로토타입 빈이 매번 새로운 객체를 생성하여 카운팅 변수 값을 변경할 것이라고 기대함

 - 2회 count++ 을 수행했을 때, 2번의 결과 모두 1이라고 기대했지만 최종 결과는 2가 된 상황

 - 하지만 싱글톤 빈에 주입된 프로토타입 빈은 주입 시점에 생성된 후 재사용하도록 동작함

 

일반적으로 스프링 빈은 싱글톤 빈으로 생성되므로 싱글톤 빈에서 프로토타입 빈을 주입 받아 사용하게 된다. 하지만 이렇게 되면 프로토타입 빈이 주입 시점에 생성은 되지만 싱글톤 빈과 함께 계속 유지되는 문제가 발생한다.

 

📌 해결 방법 : Provider

 

위 문제를 해결할 방법으로 Provider가 있다.

 

Provider는 DL(Dependency Lookup, 의존 관계 조회(탐색))이라는 역할을 수행하는데, 이것은 직접 필요한 의존 관계를 스프링 컨테이너에서 찾는 것을 말한다. 컬렉션 객체 타입을 지정해주는 것과 마찬가지로 찾고자 하는 객체를 지정해주면 된다.

 

@Scope("singleton")
static class ClientBean {
    @Autowired
    private ObjectProvider<PrototypeBean> prototypeBeanProvider;
    
    public int logic() {
    	PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
        prototypeBean.addCount();
        return prototypeBean.getCount();
    }
}

호출할 때마다 다른 프로토타입 빈이 호출됨

 

동작

@Autowired로 주입 시점에 실제 PrototypeBean이 주입되는 것이 아니라 CGLIB를 통해 원본을 상속받은 가짜 프록시 객체가 주입된다. 그리고 원하는 위치에서
getObject() 메서드를 호출하면 다시 스프링 컨테이너에서 DL을 통해 해당 타입의 Bean을 찾아주는 것이다. 결과적으로 매번 새로운 PrototypeBean을 받아 사용할 수 있는 것이다.

 

CGLIB를 통해 생성된 MyLogger 클래스

 

특징

 - ObjectFactory를 상속받음

 - 옵션, 스트림 처리 등 편의 기능이 많고 별도의 라이브러리가 필요 없다.

 - 스프링에 의존

   => JSR-330 Provider라는 자바 표준을 사용하면 동일한 기능을 수행하고 스프링에 의존하지 않는다.

   => 하지만 별도의 라이브러리가 필요함

 

웹 스코프에도 적용 가능

웹 스코프는 HTTP 요청이 시작되면 생존이 시작되는 스코프라고 했다. 그래서 웹 스코프를 의존관계 주입으로 받게 되면 주입 받는 시점에 요청이 시작되지 않았기 때문에 오류가 발생한다. 이 경우에도 Provider를 통해 웹 스코프 빈의 생성 또는 요청을 지연하여 해결할 수 있다.

 

Provider는 주입 시점에 DL을 수행할 프록시 객체를 주입받는데, 이것을 getObject() 메서드를 통해 호출하면 그 시점에 DL 객체가 스프링 컨테이너에서 해당 타입의 빈을 찾아 준다. 그래서 자신이 원하는 시점에 웹 스코프라는 빈을 DI할 수 있는 효과를 볼 수 있다.

 

Reference:

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

'Spring' 카테고리의 다른 글

서블릿(Servlet) 기본  (1) 2023.07.11
웹 서버와 웹 애플리케이션 서버(WAS)  (0) 2023.07.11
BeanFactory vs ApplicationContext  (0) 2023.05.19
빈 생명 주기 콜백  (0) 2023.05.11
의존 관계 주입(DI, Dependency Injection)  (0) 2023.05.09