싱글톤 패턴과 싱글톤 컨테이너

Jongwon·2022년 3월 23일
0

Java/Spring

목록 보기
7/12

싱글톤 패턴

클래스의 인스턴스가 단 1개만 생성되어야 하는 디자인 패턴입니다. 그렇다면 이 패턴은 왜 필요할까요? 만약에 어떤 고객이 특정 명령, 이를테면 장바구니 호출이라는 명령을 실행하였다고 가정합시다. 한 두번의 호출은 시스템적으로 전혀 지장이 없겠지만, 1초에 10,000번 호출하는(예시에 불과합니다) 경우가 발생한다면 장바구니 인스턴스를 100번 생성 후 호출해야 할 것이고, 이는 메모리적으로 큰 손해입니다.

싱글톤 패턴의 구현

싱글톤을 구현하는 방법은 여러가지가 있습니다.

A. private 생성자를 이용한 구현

public class Singleton {

  //private 접근자를 이용한 static 생성자를 만듭니다.
  private static final Singleton singletonClass = new Singleton();
  
  //Getter 함수를 이용하여 생성된 Singleton()인스턴스를 호출합니다.
  public static Singleton getInstance() {
    return singletonClass;
  }
}



하지만 이 패턴을 적용하기에는 여러가지 문제가 있습니다. 위와 같이 싱글톤을 구현하기에 코드가 복잡하고, 테스트가 어렵습니다. 또한 클라이언트가 구체 클래스에 의존하기 때문에 앞선 SOLID 원칙을 위반할 가능성이 높아집니다.


싱글톤 방식 주의점

객체에 필드를 지정할 때는 유의해야 합니다. 싱글톤 방식에서 필드값을 이용하다보면 공유되기 때문에 원하지 않은 값이 나중에 덮어쓰일 수 있습니다.

@Service
public class StatefulService {

	private int price;
    ...
}

위와 같은 인스턴스가 싱글톤으로 생성이 되었을 때, 두 쓰레드에서 한번에 price에 접근하여 값을 넣는다면 두 값 중 하나는 덮어지게 됩니다.



스프링 컨테이너

스프링은 스프링 컨테이너를 싱글톤 방식으로 만들었습니다. 따라서 스프링 빈에서는 자체적으로 객체 인스턴스가 단 하나만 생성되는 싱글톤 방식으로 관리됩니다.

@Bean 어노테이션이 붙은 메서드는 모두 스프링 컨테이너 내부에서 싱글톤 방식으로 존재하는데, 만약 두 빈이 같은 객체 인스턴스를 참조한다면 어떻게 될까요?

@Bean
public Order1 order1() {
	return new OrderImpl();
}

@Bean
public Order2 order2() {
	return new OrderImpl();
}

이런 방식으로 구현이 되어있다면, OrderImpl()이 두번 생성되고, 다른 인스턴스를 가지므로 싱글톤 방식을 어기게 됩니다.
하지만 스프링에서는 이를 해결하기 위해 @Configuration이라는 어노테이션을 제공합니다.

@Configuration
public class AppConfig {
	@Bean
	public Order1 order1() {
		return new OrderImpl();
	}

	@Bean
	public Order2 order2() {
		return new OrderImpl();
	}
}

@Configuration 어노테이션은 @Bean이 붙은 메서드마다 스프링 빈이 존재하는지 확인 후, 없을 때만 새로운 인스턴스를 만들도록 하기 때문에 싱글톤이 보장이 됩니다.





참고자료
김영한님의 스프링 핵심원리 기본편

profile
Backend Engineer

0개의 댓글