싱글톤 패턴 (Singleton Pattern)
싱글톤 패턴은 어떤 클래스를 애플리케이션 내에서 주로 하나만 존재하도록 강제하는 패턴이다 이렇게 만들어진 클래스의 오브젝트는 애플리케이션 내에서 전역적으로 접근이 가능하다 단일 오브젝트만 존재해야 하고, 이는 애플리케이션의 여러 곳에서 공유하는 경우에 주로 사용한다
서버 어플리케이션과 싱글톤
스프링은 기본적으로 싱글톤 방식으로 빈을 생성한다 이는 스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버 환경이기 때문이다 일반적인 서버 환경은 초당 수십, 수백번의 요청을 처리해야 하고, 매 요청마다 로직을 담당하는 오브젝트를 생성하면, 생성과 가비지 콜렉션에 사용되는 리소스가 증가하고 서버가 감당해야 할 부하가 증가한다 따라서 이를 해결하기 위해 애플리케이션 안에서 한 개의 오브젝트만 만들어서 사용하도록 한 것이 바로 싱글톤 패턴이다
자바 기반 싱글톤 패턴의 한계
일반적인 싱글톤 패턴을 구현한 코드는 다음과 같다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserDao{
public static USerDao INSTANCE;
private UserDao(ConnectionMaker connectionMaker){
this.connectionMaker = connectionMaker;
}
public static synchronized UserDao getInstance(){
if (INSTANCE == null) {
INSTANCE = new UserDao(...);
return INSTANCE;
}
}
}
이러한 방식을 사용하면 여러 문제가 발생하는데 하나씩 살펴보자
private 생성자를 갖기 때문에 상속이 불가능하다
싱글톤 패턴은 생성자를 private 으로 제한하여 자기 자신 이외에는 객체를 만들 수 없도록 한다 따라서 이 클래스는 상속이 불가능하고 객체지향적인 설계의 장점을 적용하기 어려워진다
테스트하기 어렵다
싱글톤은 만들어지는 방식이 제한적이기 때문에 테스트에 사용하기 어렵다
서버환경에서 싱글톤이 하나만 만들어지는 것을 보장하지 못한다
클래스 로더를 구성하는 방법, 여러 JVM에 분산되어 설치되는 방식에 따라 싱글톤을 보장할 수 없다
전역 상태를 만들 수 있기 때문에 바람직하지 못하다
싱글톤의 static 메소드를 통해 전역 변수처럼 사용할 수 있다 전역 변수처럼 사용하는 경우 객체지향적 관점에서 바람직하지 않다
싱글톤 레지스트리
위와 같은 단점을 해결하기 위해 스프링 컨테이너는 싱글톤 레지스트리 기능을 제공한다 싱글톤 레지스트리에 사용될 클래스는 private 생성자를 가질 필요가 없으며, static 메서드를 가질 필요가 없다 이를 통해 싱글톤 패턴을 염두에 두지 않고 작성할 수 있고 이는 객체지향적 설계에 매우 적합하다
싱글톤 레지스트리 사용의 주의점
일반적인 멀티스레드 환경이라면 여러 스레드에서 동시 접근하여 사용할 수 있다 만약 읽기 전용이 아닌 값에 동시에 접근하면 의도치 않은 결과를 낳을 수 있다