화요일 날 진행했던, 팩토리 패턴과 싱글톤 패턴 발표자료 중 싱글톤 패턴의 발표 자료이다!
싱글톤 패턴 : 애플리케이션에 단 하나의 유일한 객체를 만들기 위한 패턴
싱글톤을 사용해야 하는 이유
위 처럼 각 각 독립된 기능을 수행하는 클래스를 클라이언트 각각이 클래스를 생성해서 사용하게 되면, 메모리 누수가 발생하게 됩니다. 물론 새롭게 생성된 객체들이 GC 를 통해서 자동으로 비워지기는 할 테지만 잦은 GC는 Stop the World 를 발생시켜 프로그램 사용에 있어서 느려짐을 겪을 수 있습니다.
또한, 만약 해당 클래스를 생성하는데 발생하는 리소스가 많다면 이는 더 심하게 발생할 것입니다. 따라서, 싱글톤은 한 번 생성하고 돌려쓰는 용도로 사용을 하는 방식이고 싱글톤 방식을 채택한다면 다음과 같아집니다.
싱글톤 패턴 구현
싱글톤 패턴을 구현하는 방식은 다음과 같이 7가지가 존재합니다.
1️⃣ Eager Initialization
2️⃣ Static block initialization
3️⃣ Lazy initialization
4️⃣ Thread safe initialization
5️⃣ Double-Checked Locking
6️⃣ Bill Pugh Solution
7️⃣ Enum 이용
각각의 방법을 다 알아보기보다 일반적으로 사용되던 1번을 시작으로 각각이 개선된 3번→4번→6번→7번 순서로 알아보겠습니다.
Eager Initialization
가장 일반적인 형태로 볼 수 있는 구현 형태
[문제]
- 사용 할 계획이 없음에도 프로그램이 실행되었을 때 바로 메모리에 적재되어 자원을 낭비
Lazy Initialization
Eager Initialization을 개선한 형태
[개선]
- 프로그램이 실행되자마자 메모리에 올라가지 않아 자원을 낭비하지 않음.
[문제]
- 동시성 문제가 발생
Thread Safe Initialization
Lazy Initialization을 개선한 형태
[개선]
- 동시성 Monitor인 synchronized 키워드를 사용하여 동시성 문제 해결
[문제]
- 다른 스레드들이 빠르게 접근을 할 수 없어 성능 저하 문제가 발생을 하게 되었습니다.
- 메서드 내에 synchronized 블록을 통하여 개선이 가능
Bill Pugh Solution (LazyHolder)
[개선]
위에서 발생한 모든 문제를 개선한 방식. 멀티 쓰레드에도 안전하고, Lazy Loading도 가능
- static 내부 클래스를 사용하여 바로 생성되는 것을 방지
- 한 번 생성 될 때 final 키워드를 사용하여 재 할당 방지
[문제]
- 자바의 Reflection API, 직렬화/역직렬화를 통해 싱글톤이 파괴 될 수 있음.
Enum 방식
[개선]
- enum은 애초에 멤버를 만들 때 private 형태이고, 바로 초기화를 하기 때문에 thread safe함.
- Reflection 공격에도 안전
[문제]
- 싱글톤 클래스에서 일반적인 클래스로 되돌아가려면 코드를 다시 짜야됨
- 사용하지 않을 클래스인데도 시작부터 메모리에 적재됨
- enum 외에는 상속이 불가능
싱글톤 클래스 자체의 문제
1️⃣ 하나의 클래스에 대해 여러 클래스가 의존하게 되는 상황이 생김.
→ 싱글톤 클래스 자체에 변화가 발생하면, 이를 참조하는 모듈들도 변할 수도 있음.
2️⃣ 단위 테스트에 문제가 있음.
→ 단위 테스트는 서로 독립적인 형태로 해야하는데, 싱글톤을 사용하게 되면 매번 싱글톤 클래스를 초기화 시켜서 수행해야함.
실 사용 사례
대표적으로 Spring Framework는 싱글톤 컨테이너인 Bean Container를 사용하여 빈 객체들에 대해 싱글톤으로 관리.
'프로그래머스 데브코스' 카테고리의 다른 글
프로그래머스 데브코스 2주차 회고 (0) | 2023.06.19 |
---|---|
프로그래머스 데브코스 12일차 - 테코톡 발표 & EC2 spot Instance 구매 옵션 (0) | 2023.06.16 |
프로그래머스 데브코스 10일차 - 팩토리 패턴 (2) | 2023.06.14 |
프로그래머스 데브코스 9일차 - Static Inner 클래스를 사용해야 하는 이유, Optional orElse, orElseGet의 차이 (0) | 2023.06.12 |
프로그래머스 데브코스 8일차 - Null 제거와, Pattern 객체 캐싱 (1) | 2023.06.11 |