본문 바로가기

웹/Spring

[메모] Spring 원리 (1) 싱글톤

 - 싱글톤 패턴 - 

  • 순수한 DI 컨테이너인 AppConfig를 통해 요청을 하면, 매 트래픽마다 객체를 생성
    -> 기존 방식은 메모리 낭비가 심해질 수 있다.
  • 해결방안: 해당 객체가 딱 1개만 생성되고, 공유하도록 설계
    -> 싱글톤 패턴

  • 싱글톤 패턴 구성
package springprinciple.core.singleton;

public class SingletonServiceTest {

    // 1. static 영역에 객체 instance를 미리 하나 생성
    private static final SingletonServiceTest instance = new SingletonServiceTest();

    // 2. 이 객체 인스턴스가 필요하면 오직 getInstance() 메서드를 통해서만 조회가능
    public static SingletonServiceTest getInstance() {
        return instance;
    }

    // 3. 1개의 객체 인스턴스만 존재해야 하므로
    // 생성자를 private로 막아서 혹시라도 외부에서 new 키워드로 객체 인스턴스가 생성되는 것을 막는다.
    private SingletonServiceTest() {
    }

    public void logic() {
        System.out.println("싱글톤 객체 로직 호출");
    }
}

1. static 영역에 객체 instance를 미리 하나 생성 

2. 이 객체 인스턴스가 필요하면 오직 getInstance() 메서드를 통해서만 조회가능 

3. 1개의 객체 인스턴스만 존재해야 하므로, 생성자를 private로 막아서 혹시라도 외부에서 new 키워드로 객체 인스턴스가 생성되는 것을 막는다.

 

  • 싱글톤패턴은 여러가지 방법으로 구현할 수 있다.
    • 단순한 메서드 호출
    • synchronized
    • 정적멤버 (static) - 최초 JVM이 클래스 로딩 때 모든 클래스들을 로드할때 미리 인스턴스를 생성 후 활용
    • LazyHoler
    • DCL
    • ENUM - enum 인스턴스는 기본적으로 스레드세이프 한 점이 보장되기 때문에 이를 통해 생성가능

 

 

 - 싱글톤 패턴의 문제점 - 

  • 싱글톤 패턴을 구현하는 코드가  많이 들어감
  • 의존관계상 클라이언트가 구체 클래스에 의존하여 DIP를 위반한다. (+ 유지보수시에 OCP 원칙을 위반할 가능성이 높다)
  • 내부 속성을 변경하거나 초기화하기 어려워 테스트가 어렵다.
  • private으로 자식 클래스를 만들기 어렵고 유연성이 떨어진다.

 

 - 스프링 컨테이너 - 

  • 싱글톤 패턴의 문제점들을 최소화하여 싱글톤 패턴을 구현
  • 스프링의 기본 빈 등록 방식은 싱글톤 방식
  • 스프링 컨테이너를 통해 요청마다 객체를 생성하지 않고, 객체를 공유하여 효율적으로 재사용 가능

 - 싱글톤 방식의 주의점 - 

  • 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지하게 설계하면 안된다
  • 즉, 무상태(stateless)로 설계해야 한다
    • 특정 클라이언트에 의존적인 필드가 있으면 X
    • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 X
    • 가급적 읽기만 가능해야 한다
    • 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다