[SeSACx코딩온] Java에서의 Singleton 패턴
Java에서의 Singleton 패턴
1. Singleton 패턴이란?
- 싱글톤 패턴(Singleton Pattern)은 단 하나의 객체만 생성해야 할 때 사용하는 디자인 패턴입니다.
- 이 패턴을 적용하면 애플리케이션 내에서 여러 곳에서 동일한 인스턴스를 참조할 수 있으며, 프로그램 전반에서 하나의 객체를 전역적으로 관리할 수 있습니다.
1) 싱글톤 패턴의 핵심 개념
(1) 하나의 객체만 생성됨
- 싱글톤 패턴은 프로그램이 실행되는 동안 딱 하나의 객체만 생성되며, 이 객체는 프로그램 어디서든 동일하게 사용됩니다.
(2) private 생성자 사용
- 외부에서
new
연산자를 사용하여 새로운 객체를 생성하지 못하도록, 생성자를 private으로 설정합니다. 이렇게 함으로써 외부에서는 객체를 직접 생성하지 못하고, 제공되는 메서드를 통해서만 객체에 접근할 수 있습니다.
(3) 정적 메서드를 통한 객체 반환
- 객체는 정적 메서드를 통해서만 접근할 수 있으며, 이 메서드를 호출하면 단 하나의 인스턴스를 반환합니다.
2. Singleton 패턴의 필요성
- 싱글톤 패턴은 여러 곳에서 동일한 객체를 사용할 때 유용합니다.
- 이러한 상황에서는 불필요한 객체 생성을 피하고 자원 절약과 일관성 유지를 위해 싱글톤 패턴이 필요합니다.
1) 환경 설정 객체: 애플리케이션 전역에서 동일한 설정 값을 참조해야 할 때.
2) 로그 관리자: 프로그램 전반에서 동일한 로그 시스템을 사용할 때.
3) 데이터베이스 연결 관리: 여러 곳에서 동일한 데이터베이스 연결 객체를 사용해야 할 때.
이처럼 하나의 객체만 유지되어야 할 때, 싱글톤 패턴을 사용하면 불필요한 객체 생성을 방지하고 자원을 절약할 수 있습니다.
3. Singleton 패턴 구현
package _05_class._access_modifier._pack5;
public class Singleton {
// 클래스가 로드될 때 단 한 번 초기화되는 정적 필드를 선언
private static Singleton singleton = new Singleton();
// 외부에서 new로 객체를 생성할 수 없도록 private 생성자 선언
private Singleton() {}
// 싱글톤 객체에 접근할 수 있는 public 정적 메서드 제공
public static Singleton getInstance() {
return singleton;
}
}
1) 구현 설명
(1) 정적 필드 (static field)
private static Singleton singleton = new Singleton();
는 정적 필드로 선언되어 클래스가 로드될 때 단 한 번 초기화됩니다. 이는 프로그램이 실행되는 동안 오직 하나의 객체만 생성되도록 보장합니다.
(2) private 생성자
private Singleton()
생성자는 외부에서 객체를 직접 생성하지 못하도록 설계되었습니다. 이렇게 설정함으로써 다른 클래스에서new Singleton()
을 통해 객체를 생성할 수 없으며, 이를 통해 단일 인스턴스를 유지합니다.
(3) 정적 메서드 (static method)
public static Singleton getInstance()
는 싱글톤 객체에 접근할 수 있는 유일한 방법입니다. 이 메서드는 항상 동일한singleton
객체를 반환하며, 외부에서 객체를 생성하는 것이 아니라 이미 생성된 객체에 접근할 수 있습니다.
4. Singleton 패턴 사용 예시
싱글톤 패턴을 사용하여 객체가 하나만 생성되는지 확인해보는 코드입니다.
package _05_class._access_modifier._pack5;
public class SingletonEx {
public static void main(String[] args) {
// Singleton s1 = new Singleton();
// 컴파일 에러 발생: private 생성자 때문에 외부에서 new로 객체 생성 불가
// 정적 메서드를 통해 싱글톤 객체를 얻음
Singleton s2 = Singleton.getInstance();
Singleton s3 = Singleton.getInstance();
// 동일한 객체를 참조하는지 확인 (s2와 s3는 동일한 객체)
if (s2 == s3) {
System.out.println("같은 Singleton 객체");
System.out.println(s2);
System.out.println(s3);
} else {
System.out.println("다른 Singleton 객체");
}
}
}
1) 예시 코드 설명
(1) 객체 참조 비교
Singleton.getInstance()
메서드를 사용하여 두 개의 변수s2
와s3
에 객체를 할당합니다. 싱글톤 패턴에 의해 하나의 객체만 생성되므로,s2
와s3
는 동일한 객체를 참조합니다.
(2) 참조 동일성 검사
s2 == s3
조건을 사용해 두 변수가 동일한 객체를 참조하는지 확인합니다. 조건이 참이라면s2
와s3
는 동일한 인스턴스를 가리키고 있다는 의미입니다. 따라서 출력 결과는 “같은 Singleton 객체”가 됩니다.
출력 결과
같은 Singleton 객체
_05_class._access_modifier._pack5.Singleton@1a2b3c4d
_05_class._access_modifier._pack5.Singleton@1a2b3c4d
두 객체의 참조 주소가 동일함을 확인할 수 있습니다. 즉, s2
와 s3
는 모두 같은 인스턴스를 가리키고 있습니다.
5. Singleton 패턴의 장단점
1) 장점
(1) 자원 절약
- 객체를 한 번만 생성하므로 메모리 자원을 절약할 수 있습니다. 특히 객체 생성 비용이 높은 경우 싱글톤 패턴을 통해 성능 향상을 기대할 수 있습니다.
(2) 전역 접근 가능
- 싱글톤 객체는 전역적으로 접근 가능하여, 여러 클래스에서 동일한 객체를 공유하고 사용할 수 있습니다. 이를 통해 애플리케이션 내에서 일관된 상태를 유지할 수 있습니다.
(3) 상태 관리 용이
- 하나의 인스턴스만 존재하므로, 애플리케이션 전체에서 동일한 상태를 유지할 수 있습니다. 이로 인해 데이터 일관성이 유지됩니다.
2) 단점
(1) 테스트 어려움
- 싱글톤 패턴은 객체의 상태가 전역적으로 공유되므로, 테스트 시 독립적으로 객체를 관리하기 어렵습니다. 각 테스트마다 객체의 상태를 초기화하거나 분리된 인스턴스를 사용하는 것이 불가능할 수 있습니다.
(2) 멀티스레드 환경에서의 문제
- 멀티스레드 환경에서 동기화 처리가 되어 있지 않으면, 여러 스레드가 동시에 객체를 생성하려고 시도할 수 있어 문제가 발생할 수 있습니다. 이를 방지하려면 싱글톤 패턴을 Thread-safe하게 구현해야 합니다.