소프트웨어 디자인 패턴에서 싱글턴 패턴을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.
스프링에서 스프링 컨테이너가 관리하는 자바 객체를 ‘빈’ 이라고 한다.
빈은 @Configuration 어노테이션과 @Bean어노테이션을 사용하여 등록하거나, @Component어노테이션을 사용하여 등록할 수 있다.
빈이 사용되어지는 범위를 뜻하는 ‘스코프’를 설정할 수 있는데 스프링에서의 디폴트 값은 싱글톤이다.
@Scope(value = “prototype”)으로 매번 새로운 빈을 정의해서 사용하는 prototype스코프를 사용할 수 있지만 왜 스프링에서는 singleton 스코프를 디폴트로 사용할까?
스프링에서 bean은 기본적으로 싱글톤으로 관리된다. 즉, 스프링에 여러 번 bean을 요청하더라도 매번 동일한 객체를 돌려준다는 것이다. 싱글톤으로 bean을 관리하는 이유는 대규모 트래픽을 처리할 수 있도록
하기 위함이다.
스프링은 controller, service, repository등의 계층적으로 처리 구조가 나누어 지도록 설계되었다. 이에 따라 하나의 요청이 들어올 때 로직을 처리하는 bean을 새롭게 만들어서 사용한다고 가정해 보자. 하나의 요청에 4 ~ 5개의 bean이 만들어 지고, 초당 500번의 요청이 들어온다고 하면 초당 2000 ~ 2500개의 새로운 bean이 생성된다는 것이다. GC의 성능이 좋아도 한번 부하가 걸리면 관리가 힘들 것이다.
이러한 문제를 해결하기 위해 요청이 왔을 때 여러 쓰레드가 빈을 공유해 처리하도록 하기 위해서 bean을 싱글톤으로 사용한다.
싱글톤이 멀티쓰레드 환경에서 서비스 형태의 객체로 사용되기 위해서는 내부에 상태정보를 갖지 않는 무상태(Stateless) 방식으로 만들어져야 한다. 만약 여러 쓰레드들이 동시에 상태를 접근하여 수정한다면 상당히 위험하기 때문이다.
Stateless 방식으로 클래스를 만들기 위해 각 요청에 대한 정보나 DB나 서버의 리소스로 부터 생성한 정보는 파라미터와 로컬 변수, 리턴 값 등을 이용해 관리해줘야 한다. 이를 통해 내부에서 생성되는 변수는 매번 새로운 값을 저장할 공간이 만들어지므로 Stateless하게 관리될 수 있다.