반응형

# 싱글톤 컨테이너

## 웹 애플리케이션과 싱글톤

  • 스프링은 기업용 온라인 서비스 기술을 지원하기 위해 탄생함.
  • 대부분의 스프링 애플리케이션은 웹 애플리케이션이고, 웹 애플리케이션은 여러 고객이 '동시'에 요청을 한다.
  • 현재 작업한 DI 컨테이너 (AppConfig)의 경우 고객이 요청을 하면 new로 반환. 그렇기 때문에 고객이 여러 번 요청하면 동일한 요청에 대해 객체가 여러개 생성되게 된다. 

SingletonTest : 요청 시 마다 새로운 객체 생성되는지 확인 위한 테스트

public class SingletonTest {

    @Test
    @DisplayName("스프링 없는 순수한 DI 컨테이너")
    void pureContainer() {
        AppConfig appConfig = new AppConfig();

        // 1. 조회 : 호출할 때마다 객체 생성하는지 확인.
        MemberService memberService1 = appConfig.memberService();
        MemberService memberService2 = appConfig.memberService();

        // 참조값이 다른 것 확인.
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        Assertions.assertThat(memberService1).isNotSameAs(memberService2);
    }
}
  • 위 테스트 코드 실행 시 아래와 같이 새로운 객체를 생성해서 호출하는걸 확인할 수 있음.

  • 기존에 작업한 스프링 없는 순수한 DI 컨테이너(AppConfig)의 경우 요청 시 마다 객체를 새로 생성한다. (고객 요청에 따라 객체 생성, 소멸이 일어나기 때문에 메모리 낭비가 발생한다.)
  • 해결방법 : 해당 객체가 1개만 생성, 공유할 수 있도록 설계. (싱글톤 패턴)

## 싱글톤 패턴

  • 디자인 패턴으로, 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 패턴.
  • private 생성자를 사용해서 외부에서 임의로 new 하지 못하도록 (객체 인스턴스를 2개 이상 생성하지 못하도록) 막아야 한다.

SingletonService : 싱글톤 패턴 적용.

public class SingletonService {

    // 1. static 영역에 객체를 1개만 생성해둔다.
    private static final SingletonService instance = new SingletonService();

    // 2. 객체 인스턴스 필요 시 해당 메서드를 통해서만 조회하도록 허용.
    public static SingletonService getInstance() {
        return instance;
    }

    // 3. 생성자를 private 로 선언 -> 외부에서 new 키워드 사용하지 못하도록 막음.
    private SingletonService() {
    }

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

SingletonTest : 싱글톤 패턴 적용여부 테스트, 새로운 객체 생성이 아닌 동일한 객체인지 확인.

@Test
@DisplayName("싱글톤 패턴 적용한 객체 사용 테스트.")
void singletonServiceTest() {
    // new SingletonService(); -> 컴파일 오류 발생.

    SingletonService singletonService1 = SingletonService.getInstance();
    SingletonService singletonService2 = SingletonService.getInstance();

    System.out.println("singletonService1 = " + singletonService1);
    System.out.println("singletonService2 = " + singletonService2);

    Assertions.assertThat(singletonService1).isSameAs(singletonService2);
}

싱글톤 패턴의 문제점

  • 싱글톤 패턴 구현하는 코드 자체가 많이 들어감.
  • 의존관계상 문제 존재. (클라이언트가 구체 클래스에 의존, DIP 위반 및 OCP 위반 가능성 높아짐)
  • 테스트에 어려움 존재.
  • 내부 속성 변경, 초기화 어려움.
  • 유연성이 떨어짐.
  • 위 문제들로 인해 안티패턴으로 불리기도 함.
반응형

+ Recent posts