싱글톤 패턴(Singleton Pattern)
웹 애플리케이션에서는 싱글톤 패턴이 많이 활용된다. 웹 애플리케이션은 보통 여러 클라이언트가 서버에 동시에 요청을 한다. 아래 그림과 같이 클라이언트가 memberService를 요청하면 new로 객체를 생성하여 반환해준다. 여러 클라이언트가 요청할 때마다 객체를 새로 생성하여 반환하기 때문에 메모리 낭비가 심하다. 이러한 문제를 해결하기 위해 등장한 방안이 해당 객체가 딱 1개만 생성되고 다른 클라이언트들에게 공유하도록 설계하는 것이고 이를 싱글톤 패턴이라 한다.
싱글톤 패턴은 단순하지만 강력한 흐름을 따른다. (물론 이 흐름말고도 다양한 방법으로 구현할 수 있다.)
싱글톤 패턴은 클래스의 인스턴스가 딱 하나만 생성되는 것을 보장한다. 어떻게?
-> 객체 인스턴스를 2개 이상 생성하지 못하도록 막는다. 어떻게?
-> 클래스에서 private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 막는다.
백문이 불여일타라 했다. 코드를 보고 이해하자.
참고로 자바에서 접근자에 따른 접근 범위는 아래 표와 같다
접근자 | 클래스내부 | 패키지 | 상속받은클래스 | 외부 영역 |
private | O | X | X | X |
default | O | O | X | X |
protected | O | O | O | X |
public | O | O | O | O |
package hello.core.singleton;
public class SingletonService {
}
// 다른 파일에서 선언한 main함수
public static void main(String[] args) {
SingletonService singletonService = new SingletonService();
}
SingletonService라는 클래스를 만들고, 다른 파일에서 이를 호출하면 자바에서 제공하는 기본 생성자 (default constructor)를 통해 문제없이 인스턴스를 생성할 수 있다. 기본 생성자는 public이기 때문이다.
하지만, 생성자를 private으로 선언해놓으면, 아래와 같은 에러가 발생한다.
package hello.core.singleton;
public class SingletonService {
private SingletonService(){
}
package hello.core.singleton;
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance(){
return instance;
}
private SingletonService(){
}
public void login(){
System.out.println("싱글톤 객체 로직 호출");
}
}
핵심은 static을 활용하는 것이다. static을 사용하게 되면 해당 구문이 메모리의 static area에 올라가 프로그램의 시작부터 종료될 때까지 메모리에 남게 된다. 즉, 외부에서 해당 클래스를 여러 번 호출해도 인스턴스를 계속 생성하는 것이 아니라 이미 static 영역에 올라가 있는 하나의 객체만을 참조하여 반환한다는 것이다.
정리하자면,
1. 메모리의 static area에 객체 instance를 미리 하나 생성해서 올려둔다. 위 코드에서 instance 에 해당된다.
2. 이 객체 인스턴스는 오직 getInstance() 메소드를 통해서만 조회할 수 있고 이 메소드를 호출하면 항상 같은 인스턴스(static 영역에 올린)를 반환한다.
3. 딱 하나의 객체 인스턴스만 존재하기 위해 생성자를 private으로 막아 외부에서 new 키워드로 객체 인스턴스를 생성하는 것을 막는다.
싱글톤 패턴을 적용하면 클라이언트의 요청이 올때마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다. 하지만 필연적으로 문제점도 존재한다.
싱글톤 패턴을 구현하기 위해 코드가 길어지고, 의존관계상 클라이언트가 구체 클래스를 의존하기 때문에 DIP를 위반하게 되고 OCP 원칙을 위반할 가능성도 높아진다. 테스트하기 어렵고 내부 속성을 변경하거나 초기화하고 자식 클래스를 만들기도 어렵다. 결론적으로 유연성이 떨어진다. 이 정도면 싱글톤 패턴이 과연 좋은 것일까 의문이 들 정도다.
놀랍게도 스프링이 이 모든 단점을 해결해준다.
스프링 컨테이너는 싱글톤 패턴의 단점과 문제점을 극복하고 객체 인스턴스를 싱글톤으로 관리한다. 추가적인 코드를 작성하지 않아도 된다. 스프링의 기본 빈 등록 방식은 싱글톤이지만, 물론 싱글톤이 아닌 다른 방식도 사용가능하다.
스프링 최고
'Study > Spring' 카테고리의 다른 글
연관관계 매핑 기본 개념 (0) | 2022.11.17 |
---|---|
IoC와 DI (0) | 2022.06.24 |
게시판에 사용한 HTML 정리(feat. thymeleaf) (0) | 2022.01.16 |
스프링 CRUD 게시판 구현(SpringBoot, MySQL, SpringDataJPA) (2) | 2021.12.29 |
좋은 객체 지향 설계의 5가지 원칙 - SOLID (0) | 2021.11.10 |