-
싱글톤과 만능 스프링 컨테이너Server/Spring 2024. 9. 22. 17:12반응형
안녕하세요, 여러분! 오늘은 스프링에서 싱글톤을 어떻게 관리하는지에 대해 알아보는 시간을 가져보려고 합니다.
먼저, 싱글톤 패턴에 대해 간단히 짚고 넘어갈게요. 싱글톤은 인스턴스를 오직 한 개만 생성하여 사용하는 디자인 패턴이에요. 그런데 이 싱글톤을 구현하려면 조금 귀찮은 작업들이 필요하죠.
출처: Tecoble 대표적인 싱글톤 패턴을 살펴보아요.
public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} // private 생성자로 외부에서의 생성을 막음 public static Singleton getInstance() { return instance; // 미리 생성된 인스턴스 반환 } }
위의 코드처럼 private 생성자로 외부에서의 인스턴스 생성을 막고, getInstance() 메서드를 통해 미리 생성된 인스턴스를 반환하도록 구현해야 해요.
하지만 이런 방식에는 몇 가지 문제점이 있어요.
- 싱글톤 패턴 구현 부분이 클라이언트 코드에 노출됨
- 싱글톤 인스턴스가 너무 많은 책임을 갖게 됨 (SRP 위반)
- 테스트하기 어려움
- 내부 속성을 변경하거나 초기화하기 어려움
- private 생성자로 자식 클래스 만들기 어려움
하지만! 우리는 스프링을 사용하잖아요. 만능 스프링 컨테이너를 사용하면 이런 문제점들을 모두 해결할 수 있어요!
스프링 컨테이너와 싱글톤
출처: 브리도의 개발일지 스프링 컨테이너는 싱글톤 객체를 생성하고 관리하는 싱글톤 레지스트리 기능을 제공해요. 컨테이너에 의해 관리되는 빈들은 기본적으로 싱글톤으로 생성되어 관리 되는거죠.
@Configuration public class AppConfig { @Bean public MemberService memberService() { return new MemberServiceImpl(memberRepository()); } @Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); } }
@Configuration과 @Bean을 사용하여 스프링 빈을 등록하면, 스프링 컨테이너가 알아서 싱글톤으로 관리해줘요.
여기서 한 가지 궁금증이 생길 수 있죠. "아니, memberService()와 memberRepository()는 분명 여러번 호출될텐데... 싱글톤이 깨지는 거 아냐??"
하지만 걱정 마세요! 스프링은 이런 의문도 이미 알고 있답니다. 😎
스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig를 상속받은 임의의 다른 클래스를 만들고, 그 클래스를 스프링 빈으로 등록합니다. 이 임의의 클래스가 바로 싱글톤을 보장해주는 비밀병기라고 할 수 있죠!
@Bean public MemberRepository memberRepository() { if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있다?) { return 스프링 컨테이너에서 찾아서 반환; } else { // 스프링 컨테이너에 없으면 return 기존 로직을 호출해서 MemoryMemberRepository를 생성하고 스프링 컨테이너에 등록 후 반환; } }
따라서 memberService()와 memberRepository()는 각각 한번만 생성되고, 같은 인스턴스가 반환되는 것이 보장돼요.
주의사항
싱글톤 패턴을 사용할 때는 주의해야 할 점이 있어요. 바로 상태를 유지(stateful)하게 설계하면 안된다는 것!
public class MemberService { private int price; public void order(String name, int price) { System.out.println(name + " 님이 " + price + "원을 주문하셨습니다."); this.price = price; // 여기가 문제! } }
만약 price와 같이 공유되는 필드에 값을 설정하게 되면, 멀티스레드 환경에서 치명적인 문제가 발생할 수 있어요. A사용자가 10000원을 주문하고, B사용자가 20000원을 주문했는데 A사용자의 주문 금액이 20000원으로 바뀌어버리는 참사... 😱
따라서 스프링 빈은 항상 무상태(stateless)로 설계해야 해요!
마치며
지금까지 스프링에서 싱글톤을 어떻게 관리하는지 알아보았어요. 핵심은 스프링 컨테이너에게 모든 것을 맡기라는 것!
만약 싱글톤으로 관리하고 싶은 객체가 있다면 @Configuration과 @Bean을 사용하여 스프링 빈으로 등록만 하세요. 스프링이 알아서 싱글톤 인스턴스를 생성하고 관리해줄 거예요. 우리는 비즈니스 로직에만 집중하시면 됩니다. 😄
이상으로 스프링 싱글톤에 대한 내용을 마칠게요. 궁금한 점이나 잘못된 점 있으면 편하게 댓글 달아주세요!
비가 오는 날엔 ~
RainyCode를 찾아와
밤을 새워 기다릴게...반응형'Server > Spring' 카테고리의 다른 글
내가 공부하려고 기록하는 객체지향 SOLID 원칙과 예제 코드 (0) 2024.09.20