스프링은 빈을 왜 싱글톤으로 생성할까?

개발자·2022년 4월 17일
0

Spring

목록 보기
15/18
post-thumbnail

애플리케이션 컨텍스트는 IoC 컨테이너이면서 동시에 싱글톤을 저장하고 관리하는 싱글톤 레지스트리이기도 하다. 스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다. 여기서 싱글톤은 디자인 패턴에서 나오는 싱글톤 패턴과 비슷하지만 구현 방법이 다르다.

빈을 싱글톤으로 생성하는 이유

스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문에 스프링은 빈을 싱글톤으로 만든다. 스프링이 처음 설계됐던 대규모 엔터프라이즈 서버환경은 서버 하나당 최대로 초당 수십~수백 번씩 브라우저나 여러 시스템으로부터 요청을 받아 처리할 수 있는 높은 성능이 요구되는 환경이었다. 또 하나의 요청을 처리하기 위해 데이터 액세스 로직, 서비스 로직 등의 다양한 기능을 담당하는 오브젝트들이 참여하는 계층형 구조로 이뤄진 경우가 대부분이다. 이 때, 클라이언트에서 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다면 부하가 걸려 서버가 감당하기 힘들 것이다. 이렇게 애플리케이션에서 제한된, 수 대개 한 개의 오브젝트만 만들어 사용하는 것이 싱글톤 패턴의 원리이다. 따라서 서버환경에서는 서비스 싱글톤의 사용이 권장된다.

Java로 구현한 싱글톤 패턴의 한계

자바에서 싱글톤을 구현하는 방법에는 다음과 같은 문제가 있다.

  • private 생성자를 갖고 있어 상속할 수 없다.
    싱글톤 패턴은 생성자를 private으로 제한한다. 오직 싱글톤 클래스 자신만이 자기 오브젝트를 만들도록 제한한다. 문제는 private 생성자를 가진 클래스는 다른 생성자가 없다면 상속이 불가능하다는 것이다. 또한 상속과 다형성 같은 객체지향의 특징이 적용되지 않는 static 필드와 메소드를 사용하는 것도 역시 동일한 문제를 발생시킨다.

  • 싱글톤은 테스트하기 힘들다.
    싱글톤은 만들어지는 방식이 제한적이기 때문에 테스트에서 사용될 때 Mock 오브젝트 등으로 대체하기가 힘들다. 싱글톤은 초기화 과정에서 생성자 등을 통해 사용할 오브젝트를 다이내믹하게 주입하기도 힘들기 때문에 필요한 오브젝트를 직접 만들어 사용할 수밖에 없다.

  • 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
    서버에서 클래스 로더를 어떻게 구성하고 있느냐에 따라서 싱글톤 클래스임에도 하나 이상의 오브젝트가 만들어질 수 있다. 자바를 이용한 싱글톤 패턴 기법은 여러 개의 JVM에 분산되어 설치되는 경우에도 각각 독립적으로 오브젝트가 생기기 때문에 싱글톤이 꼭 보장된다고 할 수 없다.

  • 싱글톤 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.
    싱글톤은 사용하는 클라이언트가 정해져 있지 않다. 싱글톤의 스태틱 메소드를 이용해 언제든지 싱글톤에 쉽게 접근할 수 있기 때문에 애플리케이션 어디서든지 사용될 수 있고, 그러다 보면 자연스럽게 전역 상태로 사용되기 쉽다. 전역 상태는 객체지향 프로그래밍에서 권장되지 않는다.

싱글톤 레지스트리

이러한 싱글톤 패턴의 한계 때문에, 스프링은 싱글톤 레지스트리라는 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다.
싱글톤 레지스트리의 장점은 평범한 자바 클래스를 싱글톤으로 활용하게 해준다는 점이다. IoC 방식의 컨테이너를 사용해 제어권을 컨테이너에게 넘겨 싱글톤 방식으로 만들어져 관리되게 할 수 있다. 싱글톤 레지스트리 덕분에 애플리케이션 클래스라도 public 생성자를 가질 수 있으며 테스트하기도 편리해진다. 중요한 것은 싱글톤 패턴과 달리 객체지향적 설계 방식과 원칙을 적용하는데 제약이 없다는 점이다.

싱글톤과 오브젝트의 상태

싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있으므로 상태정보를 내부에 갖고 있지 않는 Stateless 방식으로 만들어져야 한다. 저장 공간이 하나뿐이므로 서로 값을 덮어쓰고 자신이 저장하지 않은 값을 읽어올 수 있기 때문이다. Stateless 방식으로 클래스를 만들기 위해 각 요청에 대한 정보나 DB나 서버의 리소스로 부터 생성한 정보는 파라미터와 로컬 변수, 리턴 값 등을 이용해 관리해줘야 한다. 내부에서 생성되는 변수는 매번 새로운 값을 저장할 공간이 만들어지므로 Stateless하게 관리될 수 있다.

스프링 빈의 Scope

스프링 빈이 생성되고, 존재하며 적용되는 범위를 스코프라고 한다. 스프링 빈의 기본 스코프는 싱글톤이다. 하지만 경우에 따라 다른 스코프를 가질 수 있다. 빈을 요청할 때 마다 새로운 오브젝트를 만드는 프로토타입 스코프, HTTP 요청이 생길때마다 생성되는 Request 스코프, 웹의 세션 스코프와 유사한 Session 스코프 등이 있다.


Ref.

토비의 스프링 3.1

profile
log.info("공부 기록 블로9")

0개의 댓글