싱글톤 컨테이너

LST·2022년 7월 26일
0

싱글톤 패턴

  • 스프링 없이 순수한 자바 코드로 만든 DI 컨테이너는 요청을 할 때마다 새로운 객체를 생성한다.
  • 트래픽이 많으면 많을수록 해당 수 만큼의 객체가 생성되고 소멸되기 때문에 메모리 낭비가 심하다.
  • 그렇기 때문에 해당 객체가 딱 1개만 생성되고, 공유하도록 설계하면 된다. 이것을 싱글톤 패턴이라고 한다.
  • 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
  • 싱글톤 패턴의 문제점
    • 싱글톤 패턴을 구현하는 코드가 많이 들어간다.
    • 클라이언트가 구체 클래스에 의존한다. DIP 위반
    • 테스트하기 어렵다.

싱글톤 컨테이너

스프링 컨테이너는 싱클톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤으로 관리한다. 이러한 스프링 컨테이너의 기능 덕분에 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용가능하다.

싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 무상태로 설계해야 한다.

  • 특정 클라이언트에 의존적인 필드가 있으면 안된다.
  • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
  • 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터 등을 사용해야 한다.
@Test
void test(){
	ApplicationContext ac = new AnnotationApplicationContext(Stateful.class);
    Stateful s1 = ac.getBean(Stateful.class);
    Stateful s2 = ac.getBean(Stateful.class);
    s1.order("A",1000);
    s2.order("B",2000);
    // price = ???
}
static class Stateful {
	private int price; // 상태를 유지하는 필드
    public coid order(String name, int price){
    	this.price = price;
    }
}

@Configuration과 싱글톤

ApplicationContext ac = 
	new AnnotationApplicationContext(AppConfig.class);

Annotation~ 에 파라미터로 넘긴 값은 스프링 빈으로 등록된다. 그렇기 때문에 @Configuration을 적용한 DI 컨테이너도 스프링 빈이 된다. 그럼 스프링이 CGLIB 라는 라이브러리를 사용하여 DI 컨테이너를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한다. 그 클래스가 싱글톤이 보장되도록 해준다.

// AppConfig@CGLIB 예상 코드
if (빈이 이미 스프링 컨테이너에 등록되어 있다면){
	return 스프링 컨테이너에서 찾아서 반환;
} else {
	기존 로직을 호출해서 빈을 생성하고 스프링 컨테이너에 등록
    return 반환;
}

위와 같이 @Bean이 붙은 메소드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 등록하고 반환하는 코드가 동적으로 만들어진다. @Configuration 이 CGLIB 기술을 사용해서 싱글톤을 보장하기 때문에 @Bean 만 적용하면 싱글톤을 보장하지 못하고 각각 다른 참조값을 가지게 된다. 그러므로 스프링 설정 정보는 항상 @Configuration 을 사용하자

0개의 댓글