객체의 생성은 오직 하나만 생성되는 것을 보장하며,
인스턴스에 접근할 수 있는 전역적인 접촉점을 제공하는 패턴
싱글톤 패턴의 특징
- 객체의 인스턴스가 오직 단 1개만 생성이 된다.
- 자바에서 객체를 생성할 때, new 라는 키워드를 이용하여 객체를 생성하는데, 싱글톤 패턴을 적용한 모든 코드에서 new는 단 한 번만 이루어지게 된다.
싱글톤 패턴을 사용하는 이유
- 메모리 측면에서의 이점
- 최초 한번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 메모리 낭비 방지할 수 있다.
- 다른 클래스간에 데이터 공유가 쉽다.
- 싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다. 하지만 객체 접근 시 동시성 문제가 발생할 수 있으니 이점을 유의해서 설계하는 것이 좋다.
이러한 싱글톤 패턴이 장점이 강해서 무조건 사용해야 하는 것 처럼 보이지만 그렇지만은 않다.
싱글톤 패턴의 단점
- 개방-폐쇄 원칙 위배
- 싱글톤 인스턴스가 너무 많은 일을 하거나 데이터를 공유시킬 경우에 다른 클래스의 인스턴스 간에 결합도가 높아진다.
- 객체 지향 설계 원칙에 어긋나기 때문에 수정이 어려워지고 유지보수의 비용이 높아질 수 있다.
- 멀티쓰레드 환경에서의 동시성 문제가 발생할 수 있다.
싱글톤 방식의 주의점
싱글톤 방식에서는 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 상태를 유지(stateful)하게 설계하면 안된다.
따라서, 무상태(stateless) 하게 설계해야 한다.
무상태(stateless) 란??
- 특정 클라이언트에 의존적인 필드가 있으면 안된다.
- 값을 변경할 수 있는 필드가 있으면 안된다.
- 가급적 읽기만 가능해야 한다.
- 공유되지 않는 지역변수, 파라미터등을 사용해야 한다.
자바에서의 싱글톤 패턴
자바에서의 싱글톤 패턴이란 JVM에서 클래스의 객체가 단 하나만 존재하게 하는 디자인 패턴이다.
클래스 내부에서 private static final 키워드로 객체를 생성한다.
- 외부에서는 객체 생성 불가
- 단 하나의 객체 생성
아래의 예시 코드를 통해 싱글톤 패턴을 이해 해보자.
SingletonService.java
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {
}
}
SingletonTest.java
void singletonServiceTest(){
SingletonService singletonService1 = SingletonService.getInstance();
SingletonService singletonService2 = SingletonService.getInstance();
System.out.println("singletonService1 = " + singletonService1);
System.out.println("singletonService2 = " + singletonService2);
Assertions.assertThat(singletonService1).isSameAs(singletonService2);
}
Result
singletonService1 = com.example.springdemostudy.singleton.SingletonService@6e4566f1
singletonService2 = com.example.springdemostudy.singleton.SingletonService@6e4566f1
getInstance를 통해 JVM 로딩 시에 생성된 객체 인스턴스를 비교했을 때 같은 객체임을 확인하여 싱글톤 패턴이 제대로 적용됬음을 알 수 있다.