# 싱글톤 (Singleton) 패턴
# 싱글톤이란 무엇인가요?
하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴입니다.
하나의 인스턴스를 만들어 여러 모듈들이 공유하며 사용합니다.
# 예시 코드
- 예시 1 : if문 사용 (Lazy-init 방식)
public class Singleton {
private static Singleton instance;
private Singleton() { }
public static synchronized Singleton getInsatance() {
if(instance == null) {
instance = new Singleton();
}
return instance; //instance가 이미 있을 때는, 그 instance 반환
}
}
- 예시 2 : static으로 바로 생성
public class Singleton {
private static final Singleton instance = new Singleton(); //생성자를 한번은 호출해야 하니까 직접 넣어줌
private Singleton() { } //외부에서 생성자를 호출하지 못하게 private으로 설정
public static Singleton getInsatance() {
return instance;
}
}
# 싱글톤을 사용하는 곳
데이터베이스 연결 모듈에 많이 사용됩니다.
ex1) Node.js에서 MongoDB데이터 베이스를 연결할 때 쓰는 mongoose 모듈
ex2) Node.js에서 MySQL 데이터베이스를 연결할 때
# 싱글톤의 장점은 무엇인가요?
- 하나의 인스턴스만을 만들기 때문에, 고정된 메모리 영역을 사용하여 메모리 낭비를 방지할 수 있습니다.
- 싱글톤 인스턴스는 전역으로 접근 가능하기 때문에, 데이터 공유가 쉽습니다.
# 싱글톤의 단점은 무엇인가요?
- 모듈들간의 의존성이 높아집니다. 따라서, TDD(Test Driven Development)를 할 때 문제가 됩니다.
- 멀티스레드 환경에서 동시성 문제 해결을 위해 'syncronized'를 사용해야 합니다. 'syncronized'는 다른 스레드들을 모두 제어하기 때문에, 프로그램 성능저하를 일으킬 수 있습니다.
# 싱글톤의 단점을 해결하기 위한 방법으로는 무엇이 있나요?
- 의존성을 주입합니다. 메인모듈 하위에 의존성 주입자를 추가하여 의존성 주입자가 모듈들을 관리하면, 하위 모듈에 대한 메인 모듈의 의존성이 떨어져 단위 테스트를 하기 편리해집니다.
- 스프링 컨테이너를 사용합니다.
TIP
스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리합니다.
대표적인 예가 스프링 빈입니다.
# 싱글톤 대신 정적클래스를 사용하면 되지 않나요?
정적클래스를 사용하면, 성능면에서 우수할 수 있으나 interface의 사용이 불가능해집니다.
이는, 테스트용 객체(Stub)를 사용할 수 없게 만들어 효율적인 단위테스트를 방해할 수 있습니다.
# Reflection을 사용하면 싱글톤이 의미 없어지지 않나요?
enum 타입을 통해 싱글톤을 만들면 문제가 해결됩니다.
public enum SingletonEnum {
INSTANCE;
int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public class Test {
public static void main(String[] args) {
SingletonEnum singleton = SingletonEnum.INSTANCE;
System.out.println(singleton.getValue());
singleton.setValue(1);
}
}
# 참고자료
출처: 주홍철.면접을 위한 CS 전공지식 노트.서울:길벗,2022.
출처: 정인상, 채홍석.JAVA 객체지향 디자인 패턴.서울:한빛미디어,2019.
출처: https://scshim.tistory.com/361 [책읽는 개발자_테드]