-
싱글톤 패턴과 싱글톤 컨테이너스프링 2021. 8. 28. 11:44
김영한님의 스프링 핵심 원리 - 기본편 강의를 듣고 작성했습니다.
싱글톤 패턴이란?
애플리케이션에서 여러 객체를 생성하지 않고 오로지 한 객체만 생성하는 것
안티패턴이라고도 한다.
싱글톤 패턴의 장점
위의 그림을 보면 클라이언트가 앱에 서비스를 요청할때마다 반복적으로 객체를 만들어서 처리하는 모습을 볼 수 있다.
지금과 같이 클라이언트가 적을경우에는 상관이 없지만 클라이언트의 수가 엄청나게 많아진다면 시스템에 부하를 줄 수 있다.
이를 앱의 생명주기동안 오직 한 객체만 만들어 요청할떄마다 이 객체를 반환해줌으로써 해결할 수 있게 된다.
싱글톤 패턴 구현
Java에서 싱글톤 패턴을 구현하려면 생성자를 private으로 선언해주면 된다.
싱글톤 패턴의 단점
- 코드가 많이 들어간다
- 클라이언트가 구체 클래스에 의존한다(DIP 위반)
- 테스트하기 어렵다.
- 내부 속성을 변경하거나 초기화하기 어렵다.
- private 생성자로 자식 클래스를 만들기 어렵다.
- 유연성이 떨어진다.
스프링 싱글톤 컨테이너
스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리한다.
스프링 컨테이너는 싱글톤 객체를 생성하고 관리해주는데 이런 기능을 싱글톤 레지스트리라 한다.
이런 기능 덕분에 위의 단점을 해결하면서 객체를 싱글톤으로 유지 할 수 있다.
싱글톤 패턴을 사용할때의 주의점
싱글톤 패턴은 무상태(stateless)로 설계해야한다. 만약 상태를 가지게 설계한다면 큰 버그를 발생시킬 수 있다.
위와같이 price의 상태를 유지하는 객체가 있다고 가정하고
이를 스프링 컨테이너에 집어넣어 싱글톤 패턴을 적용시킨다고 하자
그럴경우 A 사용자가 만원을 주문하고 주문금액을 조회하려는 사이에 B사용자가 주문을 진행해 20,000원을 사용하면
A 사용자가 사용한 결과인 만원이 나오는게 아닌 이만원이 나오는 버그가 발생하게 된다.
실무에서 이런 버그가 터지게 되면 굉장히 찾기가 어렵다고하니 공유필드를 주의하자.
@Configuration과 바이트 코드 조작
위와같이 @Configuration을 적용한 AppConfig가 있을 때
코드상에서 memberRepository는 memberService(), memberRepository(), orderService() 각각의 메소드를 호출할 때 객체화되는 것으로 보인다.
즉 3개의 MemoryMemberRepository가 생성되는것처럼 보인다.
하지만 스프링 컨테이너는 싱글톤을 유지한다고 들었는데 위와같이 코드를 짜면 싱글톤이 위배되는것이 아닌가?
다음과 같이 테스트를 진행해보자
싱글톤 컨테이너에 올라간 각각의 객체들을 가져와 memberRepository가 같은지 아닌지 테스트하는 코드이다.
결과를 확인해보니 모든 memberRepository는 같은 객체임이 확인되었다.
어떻게 이럴 수 있을까?
답은 바이트코드조작에 있다
스프링은 클래스를 실행하기 전에 CGLIB을 이용한 바이트코드 조작을 이용해 코드 몇 줄을 기존 코드에 낑겨넣는다.
아마 다음과 같은 코드가 들어가지 않을까 싶다
실제로 위과 같이 빈을 호출해서 클래스의 값을 찍어볼경우
AppConfig뒤에 CGLIB이 붙어서 나오는 것을 알 수 있다.
***
@Bean만을 사용하면 스프링 빈으로는 등록되지만 싱글톤은 보장되지 않는다
그러니 스프링 설정정보는 항상 @Configuration을 함께 사용하자
'스프링' 카테고리의 다른 글
의존관계 자동 주입 (0) 2021.09.06 컴포넌트 스캔 (0) 2021.09.01 스프링 빈과 스프링 컨테이너 (0) 2021.08.02 객체 지향 원리 적용 (0) 2021.07.29 스프링과 객체지향설계 (0) 2021.07.25