선 조치 후 분석

[Spring] Spring Framework - 핵심 원리 (24) - 싱글톤 컨테이너, 스프링 컨테이너 본문

Framework/Spring Framework

[Spring] Spring Framework - 핵심 원리 (24) - 싱글톤 컨테이너, 스프링 컨테이너

JB1104 2022. 2. 8. 23:15
728x90
반응형
SMALL

싱글톤 컨테이너, 스프링 컨테이너


 

  • 스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다.
  • 지금까지 정리했던 내용에서의 스프링 빈이 바로 싱글톤으로 관리되는 빈이다.

 

싱글톤 컨테이너 (=스프링 컨테이너)

  • 스프링 컨테이너싱글턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다.
  • 전에 설명한 컨테이너 생성 과정을 자세히 보자. 컨테이너는 객체를 하나만 생성해서 관리한다.
    @Configuration
    public class AppConfig {
    	@Bean
    	public MemberService memberService() {
    		//return new MemberServiceImpl(new MemoryMemberRepository()); //'MemoryMemberRepository'객체의 참조값을 'MemberServiceImpl'에 넣어준다.
    		return new MemberServiceImpl(memberRepository());
    	}
    	@Bean
    	public MemberRepository memberRepository() {
    		return new MemoryMemberRepository();
    	}
    	@Bean
    	public OrderService orderService() {
    		return new OrderServiceImpl(memberRepository(), discountPolicy());
    	}
    	@Bean
    	public DiscountPolicy discountPolicy() {
    		return new FixDiscountPolicy();
    		//return new RateDiscountPolicy();
    	}
    }​
    빈 이름 빈 객체
    memberService MemberServiceImpl
    orderService OrderServiceImpl
    memberRepository MemoryMemberRepository
    discountPolicy FixDiscountPolicy
  • 스프링 컨테이너는 싱글톤 컨테이너 역할을 한다. 이렇게 싱글톤 객체를 생성하고 관리하는 기능
    싱글톤 레지스트리라 한다.
  • 스프링 컨테이너의 이런 기능 덕분에 싱글턴 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있다.
  • 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 된다.
  • DIP, OCP, 테스트, private 생성자로부터 자유롭게 싱글톤을 사용할 수 있다.

 

코드로 확인해보자. 기존 테스트 코드에 아래 코드를 입력해서 확인하자.

	@Test
	@DisplayName("스프링 컨테이너와 싱글톤")
	public void springContainer() {
		ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
		
		//1. 조회 : 호출할 때 마다 객체를 생성
		MemberService memberService1 = ac.getBean("memberService", MemberService.class);
		
		//1. 조회 : 호출할 때 마다 객체를 생성
		MemberService memberService2 = ac.getBean("memberService", MemberService.class);
		
		//참조값이 같은 것을 확인.
		System.out.println("memberService1 = " + memberService1);
		System.out.println("memberService2 = " + memberService2);
		
		// memberService1 != memberService2
		Assertions.assertThat(memberService1).isSameAs(memberService2);
	}

 

결과를 확인해보면 같은 객체를 생성하는 것을 확인할 수 있다. 

memberService1 = hello.core.member.MemberServiceImpl@226642a5
memberService2 = hello.core.member.MemberServiceImpl@226642a5

 


싱글톤 컨테이너 적용 후

 

아래 MemberServiceImpl에는 싱글톤과 관련된 코드가 하나도 들어가 있지 않다.

public class MemberServiceImpl implements MemberService{
	private final MemberRepository memberRepository;
	
	public MemberServiceImpl(MemberRepository memberRepository) {
		super();
		this.memberRepository = memberRepository;
	}

	@Override
	public void join(Member member) {
		memberRepository.save(member);
	}

	@Override
	public Member findMember(Long memberid) {
		return memberRepository.findById(memberid);
	}
}

 

그림으로 설명하면 아래와 같다. 3명의 각각의 클라이언트들이 MemberService를 요청하면 동일한 MemberService를 반환해서 하나의 객체의 참조값만 전달한다.

스프링 컨테이너 덕분에 고객의 요청이 올 때마다 객체를 생성하는 것이 아니라,
    이미 만들어진 객체를 공유해서 효율적으로 재사용할 수 있다.

 

처음엔 스프링 컨테이너를 사용하면서 장점을 잘 몰랐다.
하지만, 이렇게 스프링 컨테이너로 바꿔가면서 뭐가 좋은지 조금씩 정리하면서 느낄 수 있을 것이다.

 

싱글톤을 그냥 만들어서 사용해도 되지만, 언제 만들어서 사용하며, 더 복잡할 것이다.
그래서 스프링 기능을 사용해서 쉽게 싱글톤의 기능을 사용할 수 있게 된다.

 

참고 
스프링의 기본 빈 등록 방식은 싱글톤이지만, 싱글톤 방식만 지원하는 것은 아니다. 요청할 때마다 새로운 객체를 생성해서 반환하는 기능도 제공한다. 자세한 내용은 추후에 빈 스코프 내용을 정리하면서 알아보자.
(특별한 경우를 제외하고는, 거의 99%는 기본 빈 등록 방식을 사용한다고 한다.)

 

다음 내용은 싱글톤 방식의 주의점을 공부해보자. 너무나도 중요한 내용이라고 한다.

728x90
반응형
LIST