Singleton 싱글톤 디자인 패턴

이용만·2023년 4월 4일
0

싱글톤(singleton)
: 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는디자인 패턴입니다.

스프링 컨테이너의 시작과 함께 생성되어서 스프링 컨테이너가 종료될 때 까지 유지

  • 싱글톤 빈의 하나의 공유 인스턴스만 관리한다.
    • private 생성자를 사용해 외부에서 임의로 new를 사용하지 못하도록 막아야 합니다.
      해당 bean definition와 일치하는 ID 또는 ID를 가진 빈에 대한 모든 요청은 스프링 컨테이너에서 해당 특정 빈 인스턴스를 반환한다.

싱글톤 내용 정리

  • 싱글톤은 해당 빈의 인스턴스를 오직 하나만 생성해서 사용하는 것을 의미합니다.
  • 단일 인스턴스는 싱글톤 빈의 캐시에 저장됩니다.
  • 이름이 정해진 빈에 대한 모든 요청과 참조는 캐시된 개체를 반환합니다.
    • 싱글톤 스코프의 스프링 빈은 여러번 호출해도 모두 같은 인스턴스 참조 주소값을 가집니다.

예제코드

public class SingletonTest {
    static DependencyConfig dependencyConfig = new DependencyConfig();

    static MemberService memberService = dependencyConfig.memberService();

    static MemberService memberService2 = dependencyConfig.memberService();

    public static void main(String[] args) {

        System.out.println("다른 주소값이 나올겁니다.");
        //수많은 객체를 생성하면 메모리 낭비와 효율성이 떨어진다.
        System.out.println("memberService : " + memberService);
        System.out.println("memberService2 : " +  memberService2 );
    }
}

->싱글톤 패턴 적용

public class SingletonService {
    // 1. static 영역에 객체를 딱 1개만 생성한다.
    private static final SingletonService instance = new SingletonService();
    // 2. 객체 인스턴스가 필요하면 아래 public static 메서드를 통해 조회할 수 있도록 한다.
    public static SingletonService getInstance(){
        return instance;
    }
    // 3. 생성자를 private로 선언하여 외부에서 new 키워드를 통해 객체 생성하도록 없도록 한다.
    private SingletonService(){}
}
  • static 영역에 객체 인스턴스를 미리 1개 생성합니다.

  • 객체 인스턴스가 필요한 경우 getInstance() 메서드를 통해서만 조회할 수 있도록 합니다.

    • 이 메서드를 호출하면 항상 같은 static instance를 호출하게 됩니다.
  • 외부에서 생성자를 new로 새로 생성되는 것을 방지하기 위해 private 생성자로 생성합니다.

public class SingletonTest {
    static SingletonService singletonService1 = SingletonService.getInstance();
    static SingletonService singletonService2 = SingletonService.getInstance();

    public static void main(String[] args) {
        System.out.println("같은 주소값이 나올 것이다.");
        System.out.println("singletonService1 : " + singletonService1);
        System.out.println("singletonService2 : " + singletonService2);
    }
}


Singleton의 문제점

싱글톤 패턴의 문제점

  • 싱글톤 패턴을 구현하는 코드 자체가 많습니다.
  • 의존관계상 클라이언트가 구체 클래스에 의존합니다.
  • 지정해서 가져오기 때문에 테스트하기 어렵습니다.
  • private 생성자를 사용하여 자식 클래스를 만들기 어렵기 때문에 유연성이 떨어집니다.

이러한 싱글톤 패턴의 문제를 싱글톤 컨테이너가 해결해준다.

객체 인스턴스를 싱글톤으로 관리합니다.

  • 스프링 컨테이너는 싱글톤 컨테이너 역할을 합니다.
  • 싱글톤 객체로 생성하고 관리하는 기능을 싱글톤 레지스트리라 합니다.
  • 스프링 컨테이너의 위 기능 덕분에 싱글턴 패턴의 모든 단점을 해결하며 객체를 싱글톤으로 유지할 수 있습니다.
@Configuration
public class DependencyConfig {

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemberRepository();
    }

    @Bean
    public CoffeeService coffeeService(){
        return new CoffeeService(coffeeRepository());
    }

    @Bean
    public CoffeeRepository coffeeRepository(){
        return new CoffeeRepository();
    }
}
  • @Bean을 통해 스프링 컨테이너에 등록됩니다.
public class SingletonTest {
    //spring container 생성
    static AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(DependencyConfig.class);
    
    static MemberService memberService1 = ac.getBean("memberService", MemberService.class);
    static MemberService memberService2 = ac.getBean("memberService", MemberService.class);

    public static void main(String[] args) {
        System.out.println("memberService1 : " + memberService1);
        System.out.println("memberService2 : " + memberService2);
    }
}

싱글톤 방식의 주의점

  • 싱글톤 방식은 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 무상태로 설계해야 합니다.
    • 특정 클라이언트가 값을 변경할 수 있으면 안됩니다.
    • 읽기만 가능해야 합니다.
    • 스프링 빈의 공유 값을 설정하면 장애가 발생할 수 밖에 없습니다.

핵심 포인트

  • 스프링 컨테이너에서 빈 스코프의 기본값은 싱글톤 스코프이다.
  • 싱글톤 패턴을 사용할때 발생하는 문제점을 싱글톤 컨테이너로 해결할 수 있다.
profile
성장하는 개발자가 되고자 합니다.

0개의 댓글