빈의 스코프는 무엇인가?

kdkdhoho·2023년 4월 23일
0

Spring

목록 보기
24/26

개요

Spring Application이 실행되고 그에따라 Spring Container가 생성될 때, 우리가 짠 POJO와, 우리가 추가한 설정 메타정보 (Configuration Metadata) 를 기반으로 객체의 인스턴스를 Spring Bean으로 생성 및 관리합니다.

이때 설정할 수 있는 메타정보다양하게 존재합니다.
그 중, Scope 라는 속성이 있습니다.

따라서, 빈 스코프란 Bean을 설정하는 다양한 요소 중 하나입니다.

그렇다면 Scope에는 어떤 값들이 들어갈 수 있으며, 그에 따라 Bean의 Definition이 어떻게 달라질까요?

Bean Scope

공식 문서에 따르면, 여러 개의 scopes 중 하나로 Bean이 생성되도록 정의할 수 있다고 합니다.

그러면 이제 '여러 개의 scopes'에 대해 알아보겠습니다.

Bean scopes

Spring이 제공하는 Bean scopes는 총 6가지입니다.

  1. singleton
  2. prototype
  3. request
  4. session
  5. application
  6. websocket

이 중, request, session, application, websocket은 web-aware Spring ApplicationContetxt 에서만 사용할 수 있습니다.

참고로 thread scope도 존재하지만 default로 등록되지 않습니다.
또, Custom scope도 만들어 사용할 수 있습니다.

여기서는 Single scope와 Prototype Scope에 대해 다루겠습니다.

Single scope

빈이 싱글톤으로 생성되면 Bean Container 내에서 인스턴스가 오직 하나만 생성 및 관리됩니다. 그리고 Spring이 해당 인스턴스 접근에 대한 캐싱을 지원해줍니다.

Spring에서의 싱글톤 빈 개념은 GoF 패턴 책의 싱글톤 패턴 개념과는 다릅니다.
GoF의 싱글톤은 "특정 클래스의 인스턴스가 ClassLoader 당 하나만 생성되도록 객체의 범위를 하드 코딩한다." 고 설명합니다.
반면, Spring의 싱글톤은 "Container 당 1개의 Bean" 이라고 설명합니다.

인스턴스가 1개인 것은 동일하지만, 해당 인스턴스가 존재하는 위치가 다른 것으로 이해할 수 있겠습니다.

Singleton Scope는 Spring이 Bean을 등록하는 default 정책입니다.
아마 개발자가 Bean의 scope를 정할 때, 가장 많이 그리고 기본적으로 사용되는 scope이며 앞으로 나올 다른 scope들은 각각의 특수한 상황에서만 쓰이기 때문이지 않을까 조심스레 추측해봅니다.

따라서 상태를 가지지 않는 객체를 Bean으로 등록하고 싶을 때, Singleton scope로 설정하면 됩니다.

Prototype scope

Prototype scope로 설정된 Bean은, 해당 객체에 대한 요청이 있을 때마다 새로운 Bean 인스턴스를 생성합니다.
Prototype scope의 Bean이 다른 Bean에 주입되거나, 컨테이너에서 getBean() 메서드 호출을 통해 요청하는 것을 의미합니다.
따라서, 상태를 가지는 객체를 Bean으로 등록하고 싶을 때 Prototype scope로 설정해야 합니다.

흥미로운 점이 하나 있습니다. 다른 scope와 다르게, Prototype scope는 Spring이 Bean의 모든 생명 주기를 관리하지 않습니다.
Spring Container는 Prototype scope의 Bean을 인스턴스화 후에 설정 및 조립하여 클라이언트에게 전달하며, 해당 Bean의 기록은 하지 않습니다.

따라서, Prototype scope Bean의 Initialization method은 호출되지만 Destruction method는 호출되지 않습니다.
결국 자원 관리를 위해 Bean의 할당 제거는 Prototype scope Bean을 사용하는 클라이언트가 담당해야 합니다.
Spring Container가 Prototype scope Bean의 자원 할당을 해제하기 위해서는, 해당 Bean의 참조가 있는 Custom bean post-processor을 사용하면 됩니다.

Singleton-Bean With Prototype-Bean Dependecies

그렇다면 만약, Singleton Bean 내부에 Prototype scope의 Bean을 의존하는 경우 어떻게 될까요?
단순히 Singleton Bean은 1개이고, 그 내부에서 Prototype Bean을 요청할 때마다 새로운 인스턴스가 생길까요?

이는 Spring Container 내부에서 Bean이 생성될 때의 동작 원리를 이해하면 되는데요.

Container에 Bean이 생성될 때 Bean의 의존성은 조립이 완성된 채로 생성됩니다.
즉, Singleton Bean이 생성될 때 Prototype Bean도 생성이 되어 의존성 주입이 이뤄지는데요.
결국 Prototype Bean 입장에서 클라이언트인 Singleton Bean을 위해 Container 내부에 하나의 인스턴스가 생성이 되고, 그 인스턴스가 Singleton Bean에 의존됩니다.

따라서 Singleton Bean이 가지는 Prototype Bean에게 여러 번 요청을 해도, 결국 하나의 인스턴스를 사용하는 셈입니다.

그렇다면 만약 런타임에 Singleton Bean이 반복적으로 Prototype Bean의 새로운 인스턴스를 필요로 하는 경우에는, 메서드 주입을 사용하면 됩니다.

문득 애플리케이션을 매번 실행할 때마다 다른 Prototype Bean 인스턴스가 생성되는지 궁금해져서 직접 확인해보았습니다. 링크

참고

profile
newBlog == https://kdkdhoho.github.io

0개의 댓글