Java Singleton Pattern
Java의 Singleton Pattern이란 무엇일까?
Singleton 패턴은 인스턴스를 불필요하게 생성하지 않고,
오직 JVM 내에서 한 개의 인스턴스만 생성하여 재사용을 위해 사용되는 디자인 패턴이다.
하지만 멀티스레드 환경에서 문제가 생길 수 있어, Thread-safe 한 형태로 구현해야 한다.
따라서 synchronized를 이용하여 Singleton 패턴을 대부분 구현할 수 있다.
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
]
synchrosized 키워드를 통해 단일 스레드가 대상 메소드를 호출 시작 ~ 종료까지
다른 스레드가 접근하지 못하도록 lock을 한다.
따라서 getInstance() 메소드를 synchrosized 키워드를 통해 처리하면,
멀티 스레드에서 동시 접근으로 인한 인스턴스 중복생성 문제를 해결할 수 있다.
스프링 컨테이너의 Bean 객체 또한 싱글톤 스코프(Scope)로 생성된다.
싱글톤 스코프는 프로그램에서 해당 Bean의 인스턴스를 오직 하나만 생성해서 재사용한다.
Spring Singleton 사용 이유
그렇다면 빈 객체는 왜 Singleton 스코프로 생성될까?
Application Context에 의해 등록된 빈은 기본적으로 싱글톤으로 관리된다.
즉, 스프링에 여러 번 빈을 요청하더라도 매번 동일한 객체를 돌려준다는 것이다.
Application Context 가 Singleton으로 빈을 관리하는 이유는
대규모 트래픽을 처리할 수 있도록 하기 위함이다.
스프링은 최초에 설계될 때부터 대규모의 엔터프라이즈 환경에서 요청을 처리할 수 있도록 고안되었다.
그리고 그에 따라 계층적으로 처리 구조가 나뉘게 되었다.
매번 클라이언트에서 요청이 올 때마다 각 로직을 처리하는 빈을 새로 만들어서 사용한다고 생각해 보자.
요청 1번에 5개의 객체가 만들어진다고 하고,
1초에 500번 요청이 온다고 하면 초당 2500개의 새로운 객체가 생성된다.
이러한 문제를 해결하고자 빈을 싱글톤 스코프로 관리하여 1개의 요청이 왔을 때
여러 스레드가 빈을 공유해 처리하도록 하였다.
Spring Singleton 사용 장점
하지만 위에서 본 Java의 기본적인 싱글톤 패턴을 직접 구현하고자 하면 다음과 같은 단점들이 발생한다.
- private 생성자를 갖고 있어 상속이 불가능하다.
- 테스트하기 힘들다.
- 서버 환경에서는 싱글톤이 1개만 생성됨을 보장하지 못한다.
- 전역 상태를 만들 수 있기 때문에 객체지향적이지 못하다.
그래서 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는데,
그것이 바로 싱글톤 레지스트리(Singleton Registry)이다.
스프링 컨테이너는 싱글톤을 생성하고, 관리하고 공급하는 컨테이너이기도 하다.
싱글톤 레지스트리의 장점은 다음과 같다.
- static 메소드나 private 생성자 등을 사용하지 않아 객체지향적 개발을 할 수 있다.
- 테스트를 하기 편리하다.
기본적으로 싱글톤이 멀티스레드 환경에서 서비스 형태의 객체로 사용되기 위해서는
내부에 상태정보를 갖지 않는 무상태(Stateless) 방식으로 만들어져야 한다.
만약 여러 스레드들이 동시에 상태를 접근하여 수정한다면 상당히 위험하기 때문이다.
직접 싱글톤을 구현한다면 상당히 많은 단점들이 있겠지만,
Spring 프레임워크에서 직접 싱글톤으로 객체를 관리해 주므로,
우리는 더욱 객체지향적인 개발을 할 수 있다.
참고자료
https://mangkyu.tistory.com/151
https://int-i.github.io/java/2022-05-22/java-singleton-spring-bean/
'IT > Spring boot' 카테고리의 다른 글
[Spring boot] Persistent Framework & JPA의 등장 (0) | 2024.08.11 |
---|---|
[Spring boot] POJO (Plain Old Java Object) (0) | 2024.08.10 |
[Spring boot] Application Context (0) | 2024.08.09 |
[Spring boot] 이메일 전송 구현 (3) | 2024.08.07 |
[Spring boot] Restful API 등장과 ReponseEntity (0) | 2024.08.07 |