정의
객체의 인스턴스가 오직 1개만 생성되는 패턴을 말한다.
클래스의 인스턴스가 오직 하나만 생성되는것을 보장하고 해당 인스턴스에 전역적으로 접근할 수 있는 방법을 제공하는 패턴이다.
싱글톤의 단점
private생성자를 가지고 있어 상속이 불가능하다
테스트하기 어렵다
생성방식이 제한적이고 Mock객체로 대체하기 어려우며 동적으로 객체를 주입하기도 어렵기 때문이다.
서버환경에서 싱글톤이 1개만 생성됨을 보장하지 못한다.
클래스로더를 어떻게 구성하느냐에 따라서 싱글톤이지만 1개이상의 객체가 생성될 수 있다. 자바언어를 이용한 싱글톤 기법은 서버환경에서 싱글톤을 보장하지 않는다. 분산환경에서도 싱글톤을 보장하기 어렵다
전역상태로 인한 문제
싱글톤의 스태틱메소드를 사용하여 언제든지 해당 객체를 사용하도록 전역설정을 할 수 있다. 전역상태는 객체지향 프로그래밍에서 권장하지 않는다.
Spring에서는 컨테이너를 통해 직접 객체를 싱글톤으로 관리함으로써 객체지향스럽게 개발이 이루어지도록 해주었다.
(안전한)싱글톤 클래스,인스턴스를 구현하는 방법들
초기화 시점에 따라서 나눌 수 있고 thread safe보장여부에 따라서 나눠볼 수 있습니다.
Eager Initialization - 이른 초기화
장점
가장 간단한 형태의 싱글톤 구현방법이다.
클래스의 인스턴스를 클래스 로딩시점에 생성하는 방법으로 thread safe를 보장한다.
단점
Exception에 대한 핸들링을 제공하지 않는다.
인스턴스를 무조건 미리 만들어놓기에 실제로 사용되지 않을경우 낭비다.
Static Block Initailization - 정적 블럭 초기화
이른 초기화와 유사하지만 static block에 try-catch구문을 사용하여 Exception handling이 가능하다는 차이가 존재한다.
Lazy Initailization - 게으른 초기화
이른 초기화처럼 클래스로딩시점에 초기화를 하는것이 아닌 해당 클래스의 인스턴스를 만드는 메소드를 호출할 때 인스턴스가 없다면 생성하는 방식이다.
장점
이른 초기화의 문제점인 사용하지 않았을 경우 인스턴스가 낭비되는 문제를 해결한다
단점
thread safe를 보장하지 않는다. 클래스의 인스턴스가 없는 상황에서 여러 쓰레드가 동시에 인스턴스를 만드는 메소드를 호출한다면 여러개의 인스턴스가 생성되어 싱글톤을 보장하지 못한다.
Lazy initialization with synchronized - 동기화블럭을 사용한 게으른 초기화
기존 게으른 초기화방법에 synchronized block을 사용하여 thread safe를 보장하는 방법이다.
private static으로 해당 클래스의 인스턴스변수를 선언하고 private생성자를 사용하여 외부에서 생성을 막고 인스턴스 생성 메소드에 synchronized키워드를 사용하여 thread safe하게 만든다.
단점
synchronized를 사용함에 따라 큰 성능저하를 유발하여 권장하지 않는 방법이다. 싱글턴 인스턴스를 자주 호출하는 어플리케이션이라면 더욱 더 성능이 떨어진다.
Lazy initialization + Double-checked locking
synchronized를 바로 사용하는것이 아닌 조건문으로 인스턴스의 존재여부를 체크 이후 synchronized를 사용하여 성능저하를 줄이는 방법이다.
성능저하를 근본적으로 해결하는 방법은 아니다.
volatile예약어를 사용하면 멀티스레드환경에서도 instance변수가 singleton인스턴스로 초기화되는 과정이 올바르게 진행되도록 할 수 있다.
Initialization on demand holder idiom - holder에 의한 초기화
inner static helper class를 사용하는 방식으로 volatile이나 synchronized키워드 없이 동시성 문제를 해결한다.
클래스안에 클래스를 두어 홀더역할을 하게하여 JVM의 Class Loader메커니즘과 Class가 로드되는 시점을 이용한 방법이다.
JVM의 클래스 초기화 과정에서 보장되는 원자적특성을 이요하여 싱글톤의 초기화 문제에 대한 책임을 JVM에 위임한다.
방법
private inner static class를 만들어 싱글톤 인스턴스를 갖게 한다.
inner class는 Singleton클래스가 Load될때도 Load되지 않다가 getInstance()가 호출됐을때 JVM메모리에 로드되고 인스턴스를 생성한다.
holder안에 선언된 인스턴스가 static이기 때문에 클래스 로딩시점에 한번만 호출될것이며 final을 사용해 다시 값이 할당되지 않도록 하는 방법이다
제일 많이 사용되는 Singleton클래스 사용방법이다.
Enum Singleton
정의
Java에서 리플렉션이나 직렬화과정에서 싱글톤이 파괴될 수 있기에 이를 방지하기 위하여 enum을 사용하는 방법이다. enum클래스의 인스턴스 생성은 기본적으로 Thread Safe를 보장하기 때문이다.
주의해야할점
만들려는 싱글톤 클래스가 enum클래스 말고 다른 클래스를 상속받아야하는 경우 다중상속이 불가능하기에 사용하기 어렵다.
싱글톤을 보장하기 위한 Spring Configuration
각각 다른 빈에서 의존성 주입의 대상이 같은 클래스(ex>다른 서비스가 같은 레포지토리)일경우 싱글톤이 깨지는 상황이 된다.
이런 경우 싱글톤이 깨지지 않도록 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.(런타임시?) 해당내용은 Configuration Annotation안에 있다.
Configuration Annotation또한 빈으로 등록된다. Configuration클래스는 그대로 빈으로 등록되지 않고 스프링이 CGLIB이라는 바이트코드조작 라이브러리를 사용하여 Configuration클래스를 상속받은 임의의 다른 클래스를 만들고 그 다른 클래스를 빈으로 등록한다.
이런 과정을 통해서 @Bean이 등록된 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
개발 아카이브
글쓰기
블로그 관리
springboot,
spring,
명령줄이너무깁니다,
IntelliJ,
객체지향5원칙,
booleanExpression,
이클립스,
datetitme,
java,
JPA,
gradle,
NULL,
NullPointerException,
인텔리제이,
passbyvalue,
react,
QueryDSL,
qclass,
passbyreference,
external network,
« 2025/02 »
일
월
화
수
목
금
토
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28