[Spring] 스프링 Bean Scope (싱글톤, 프로토타입 빈)

손효재·2022년 4월 28일
0

Spring

목록 보기
2/3

Spring Bean Scope

스코프 Scope

빈이 존재할 수 있는 범위를 뜻한다. 스프링 빈은 기본적으로 싱글톤 스코프로 생성되기때문에,
스프링 빈이 스프링 컨테이너의 시작과 함께 생성되어서 스프링 컨테이너가 종료될 때 까지 유지된다.

싱글톤 빈

싱글톤은 Bean의 기본 스코프이다. @Scope={”singleton”}
스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이며, 스프링 컨테이너 생성 시점에 초기화 메서드가 실행된다.

생성한 Bean의 인스턴스가 같음을 확인할 수 있고, 스프링 컨테이너가 종료될 때 preDestroy의 로그를 확인할 수 있다.

프로토타입 빈

스프링 컨테이너에 요청할 때마다 새로 생성되는 Bean이다. @Scope={”prototype”}
스프링 컨테이너는 프로토타입 Bean의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 짧은 범위의 스코프이다.
프로토타입 스코프 Bean은 스프링 컨테이너에서 해당 Bean을 조회할 때 생성되고, 초기화 메서드가 실행된다.

조회 시점에 Bean이 생성되며, 2번 조회한 Bean이 모두 다른 인스턴스임을 확인할 수 있다.
또한, Bean을 생성한 이후 관리범위가 끝나기 때문에 스프링 컨테이너를 close해도 preDestroy로 설정한 로그가 호출되지 않는다.
만약 프로토타입 Bean을 종료해야한다면, 클라이언트가 직접 destroy를 호출해야 한다.

프로토타입 빈 테스트

프로토타입 Bean 내부에 count가 있고, 클라이언트가 addCount()를 호출하면 count가 올라간다.
다른 클라이언트가 다른 프로토타입 Bean의 addCount를 하게되면, 다시 count가 올라가 1이 된다.
이렇게되면, 2개의 다른 프로토타입의 count가 1이 되는 것을 확인할 수 있다.

프로토타입 빈과 싱글톤 빈을 함께 사용할 때 문제점

그렇다면, clientBean이라는 싱글톤 빈에서 프로토타입 빈을 의존관계로 가져와 사용해보자!

clientBean은 싱글톤 빈이기 때문에, 스프링 컨테이너 시점에 Bean이 생성된다. 따라서, 의존관계 주입 시점에 프로토타입 빈이 필요하여 요청하게되면, 프로토타입 빈을 생성하고 의존관계를 주입해준다.
그렇게되면 clientBean은 count가 0인 프로토타입 빈을 내부 필드에 가지고 있게된다.

이때, 클라이언트A가 clientBean을 요청하면, 싱글톤 빈이기 때문에 같은 clientBean이 반환된다.
이후 클라이언트A가 clientBean에서 어떤 로직을 호출하면서 addCount가 호출되면, 프로토타입 빈의 count가 1이 된다.

다음으로, 클라이언트B가 clientBean을 요청하여 로직을 호출하면
clientBean은 싱글톤 빈이기 때문에 항상 같은 빈을 반환한다. 이때 clientBean의 내부에 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈이므로 이미 1의 상태를 가지고 있다.

이 프로토타입 빈은 싱글톤 빈의 주입 시점에 생성된 것이기 때문에 프로토타입 빈이 사용할 때마다 새로 생성되는 것이 아니다.
즉, 프로토타입 빈을 사용하는 의도에 맞지 않게 싱글톤 빈과 함께 계속 유지된다.

해결 방법 - ObjectFactory, ObjectProvider

의존관계를 외부에서 주입(DI) 받는게 아니라,
ObjectFactory,ObjectProvider는 직접 필요한 의존관계(지정한 빈)를 스프링 컨테이너에서 찾아주는 Dependency Lookup(DL, 의존관계 조회)를 제공한다.

provider로 getObject()를 호출하면 스프링 컨테이너에서 프로토타입 빈을 호출해 항상 새로운 빈을 반환한다.

0개의 댓글