[Design Pattern] - 싱글톤 패턴 #137
Irisation23
started this conversation in
m.Design-Pattern
Replies: 1 comment 2 replies
-
LazyHolder 방식을 추천하신다고 하셨는데 그리고 글 잘 읽었습니다.! |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
[디자인패턴] 싱글톤 - 발표자료 Fin
0. TL;DR 📚
단일 인스턴스
이다.단일 인스턴스
가 모두 공용으로 사용한다.개방 폐쇄 원칙
을 어길수 있다.단일 책임 원칙
을 어길수 있다.멀티 스레드
상황을 고려해야 한다.1. 싱글톤이란? 🤔
아래와 같이 해석될 수 있다.
잠깐 객체지향으로 돌아와 우리가 배운 개념으로는 클래스는
설계도
이다.그
설계도
로 만들어 내는여러 객체
를 통해 또 다른 설계도에서 만들어진 객체들과 프로그램의 세계에서메시지
를 주고 받으며상호작용
하기를 기대한다.객체가 하나면 우리가 알고있는 객체지향이 맞을까? 왜 싱글톤은 단일 객체를 가질 수 밖에 없었을까?
싱글톤에 대해 알아보자.
1.1 싱글톤 특징
메모리 절약
모든 객체는 JVM의 Heap 메모리에 저장된다.
그러나 싱글턴 객체는 단 한번만 생성되기 때문에 최초에 생성된 단 한개의 객체만 Heap에 저장된다.
이후 모든 클라이언트가 참조하는 해당 인스턴스는 Heap에 하나밖에 없는 주소를 참조한다.
데이터 공유
싱글톤으로 구현된 객체는 JVM Heap 에 저장된 하나의 객체를 모든 클라이언트들이 공유하게 된다.
만약 싱글톤 객체에 공유할 정보를 넣는다면 손쉽게 모든 클라이언트들이 공유할 수 있게 된다.
멀티스레드 환경을 고려
다수의 클라이언트에서 하나의 객체, 즉 하나의 자원을 공유하는 상황이다 보니 자칫하면 치명적인 문제가 발생할 수 있다.
싱글톤 구현 시 멀티스레드를 고려하지 않으면 여러 클라이언트에서 하나의 자원에 접근하며
[레이스 컨디션](https://ko.wikipedia.org/wiki/%EA%B2%BD%EC%9F%81_%EC%83%81%ED%83%9C)이 발생 할 수 있다.
만약 싱글턴의 생성 로직에서 레이스 컨디션이 발생한다면, 여러개의 객체가 생성되는 일도 발생할 수 있다.
테스트 코드 작성이 까다롭다.
테스트 케이스들을 작성할 때는 필연적으로 다양한 입력값, 출력값을 정의해야 한다.
만약 싱글톤 클래스가 불변객체이고, 생성자를 통해서 값을 주입받는 다면?
결론적으로 까다롭다라는 표현한 이유는 단순 테스트하기 위한 불필요한 코드가 증가하게 된다.
싱글톤은 이러한 특징들을 가지고 있다.
2. 싱글턴의 구현 방법
public static final
필드volatile
키워드2.1 public static final 필드
instance
GC의 대상이 아니기 때문이다.2.2 정적 팩터리 방식
정적 팩터리 방식에서는 여러가지 방법을 사용할 수 있다.
이 방식들의 공통적인 특징은 다음과 같다.
getInstance
메소드는 싱글톤을 반환하는 기능을 한다고 알려져 있음getInstance
메소드만 수정하면Singleton
<-->Non Singleton
으로 변경할 수 있음1) private static final 필드 사용
2.1 과 특징이 같다.
2) Lazy Initialization(지연 초기화)
1)번 방법은 사용하지 않아도 불필요하게 객체가 생성된다는 단점이 있었음.
하지만 지연 초기화 방법을 사용하면 그러한 점을 해결할 수 있다.
레이스 컨디션
이 발생할 경우, 싱글톤을 만족하지 않을 수 있음!3) Lazy Initialization + Synchronization(지연 초기화 + 동기화)
멀티스레드 환경에서 레이스 컨디션이 발생하는 경우를 방지하기 위해 동기화를 사용하는 방법임.
Java 의 synchronized 키워드를 이용해서 동기화 문제를 해결함.
4) LazyHolder 방식 - Initialization on Demand Holder (IODH) - [추천] ✨
LazyHolder 방식은 지연 초기화 방식의 성능적 문제를 개선하기 위해 제안된 방법
synchronized 키워드를 사용하면 JVM 내부적으로 락을 획득하는 작업 때문에 성능 저하가 발생
하지만 이 방법은 Class Loader 에 Singleton4 인스턴스 생성 역할을 맡기며 지연 초기화를 구현하는 방법임
클래스 로드와 초기화 과정은 thread-safe 하게 동작하는데, 이는 synchronized 보다는 성능이 보장됨.
5) volatile + double-checked locking
이 방식은 getInstance() 메서드가 호출될 때 인스턴스가 null인지 확인하고, null일 경우에만 동기화 블록에 진입한다.
동기화 블록 내에서 다시 한 번 인스턴스가 null인지 확인하고, null일 경우에만 인스턴스를 생성한다.
volatile
키워드는 instance 변수가 여러 스레드에 의해 공유될 수 있음을 나타낸다.volatile
키워드는 변수의 값을 메모리에서 읽어오도록 강제하여, 여러 스레드가 동시에 접근할 경우 발생할 수 있는 문제를 방지한다.3.
개방 폐쇄 원칙
🔥 &단일 책임 원칙
🔥자, 다시 1. 의 객체지향관점으로 돌아와서 생각 해 보자.
해당
싱글턴 패턴
은개방 폐쇄 원칙
와단일 책임 원칙
를 시원하게 어기고 있다. 객체지향의 5원칙 중 무려 2개를 어기고 있다.따라서 객체 지향 설계 원칙에 어긋나기 때문에 수정이 어려워지고 유지보수의 비용이 높아질 수 있다.
4. 결론 💬
멀티스레드
를 고려해야하고,단일 책임 원칙
,개방 폐쇄 원칙
을 잘 지켰는지 체크를 해야한다. ✅5. 회고 🧹
2023-04-04 화
싱글턴 패턴을 구현함에 있어 꽤 많은 연관관계가 있단 사실을 알게 되었다.
개발을 하면서 코드를 작성하는 것보다는 (키보드에 손을 올리기 전에) 해당 기술이 왜 사용되는지에 대한 생각을 먼저 하는 것이 좋다고 느낀다.
출처
Beta Was this translation helpful? Give feedback.
All reactions