이번 글은 싱글톤에 대해서 정리해보려고 한다.
Spring에 대한 내용만은 아니지만 연관되어 이야기 할 수 있기에 정리해볼 것이다.
싱글톤 패턴이란 객체의 인스턴스가 딱 1번만 생성되는 패턴을 말한다.
예를 들어보자면, 어떤 프로그램 내에서 고객은 기능을 실행하기 위해 객체를 생성해야만 할 것이다.
그럴 때 같은 기능인데도 불구하고, 고객이 여러명이면 객체를 여러개 생성할 수 밖에 없을 것이다.
싱글톤 패턴은 이런 상황에서 객체를 1번만 생성하고 그 객체를 이용할 수 있게 하는 패턴인 것이다.
그렇다면 이 싱글톤 패턴은 어떻게 사용하는지 살펴보자.
이른 초기화 방법
public class SingletonService {
private static final SingletonService instance = new SingletonService();
// static으로 생성해서 클래스영역(Static 영역)에 하나만 만들어둔다.
public static SingletonService getInstance() {
return instance;
} // 해당 메소드를 통해서만 조회 할 수 있고,
// 이 메서드를 호출하면 항상 같은 인스턴스를 반환한다.
private SingletonService() { } // private를 통한 외부 생성 막기
}
늦은 초기화 방법
public class SingletonService {
private SingletonService() { } // private 외부 생성 막기
private static class InnerInstanceClass {
private static final SingletonService instance = new SingletonService();
} // SingletonService 클래스 안에는 InnerInstaceClass 의 변수가 없으므로 바로 초기화 되지 않는다.
public static SingletonService getInstance() {
return InnerInstanceClass.instance;
} // 해당 메서드가 호출 될 때 IneerInstanceClass를 초기화 시킨다.
}
주로 사용되는 싱글톤 패턴은 위와 같이 이루어진다.
물론 다른 방법도 물론 존재한다.
synchronized 키워드를 사용해 필요한 시점에 객체를 생성하는 방법을 사용하거나(성능이 매우 떨어짐),
저번에 C 에서 설명했던 volatile 키워드를 사용하는 방법, Enum을 사용하는 방법 등이 존재한다.
이런 식으로 코드를 작성하게 되면 객체를 여러 개 만들게 되어 메모리를 낭비하지 않아도 되어 매우 효율적이게 된다.
하지만 이런 싱글톤 방식에도 문제점이 존재한다.
싱글톤 패턴을 구현하는 코드가 필요하다.
의존관계상 클라이언트가 구체 클래스에 의존한다 = DIP 위반
유연성이 떨어진다.
private 이기에 자식 클래스를 만들기 어렵다... 등등
여러가지 문제가 존재하는데 그러면 어떻게 이런 문제들을 해결 할 수 있을까?
그건 바로 스프링을 이용하는 것이다.
스프링 컨테이너에서는 기본적으로 싱글톤 기능을 지원한다.
저번에 사용했던 코드를 예제로 가져와 보겠다.
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
Repository repository1 = applicationContext.getBean("repository", StuRepository.class);
Repository repository2 = applicationContext.getBean("repository", StuRepository.class);
System.out.println("Repository1 = " + repository1);
System.out.println("Repository2 = " + repository2);
위와 같은 코드를 봤을 때 원래라면 저 둘의 참조 값은 다른게 정상일 것이다.
하지만 스프링 컨테이너를 통해서 이를 가져온 것이기 때문에 같은 참조 값이 조회되는 것을 볼 수 있다.
*** 물론 스프링에서 요청할 때 마다 새로운 객체를 생성해서 반환하는 기능도 제공한다.
따로 싱글톤 코드를 작성한 것도 아니고, 그저 스프링을 이용했을 뿐인데 이런 일들이 가능하다는 것을 볼 때마다 스프링을 개발한 개발자들이나
스프링을 사용하지 않고 좋은 프로그램들을 만드는 개발자들이 정말 대단하기도 하고, 많은 고생을 했을 것 같다는 생각이 든다.
이처럼 장점이 한없이 추가되는 스프링을 배워가는게 정말 재밌는 것 같다.
다음에는 의존관계 자동주입에 대해서 정리하게 될 것 같다.
참고 :
'Spring' 카테고리의 다른 글
[Spring 핵심 원리] 빈 생명주기 콜백 (0) | 2022.03.20 |
---|---|
[Spring 핵심 원리] 의존관계 주입에 대하여 (생성자 주입과 Lombok) (0) | 2022.03.20 |
[Spring 핵심 원리] 수동 빈 등록을 통한 의존관계 주입 (0) | 2022.03.20 |
[Spring 핵심 원리] SOLID (0) | 2022.03.20 |
[Spring 핵심 원리] Spring이란? (0) | 2022.03.20 |