※ 본 포스팅은 Inflearn - 김영한 강사님의 '스프링 핵심 원리 - 기본편' 을 참고,공부하여 만들었습니다.
싱글톤 이란?
싱글톤은 객체지향 디자인패턴중 하나이고 이 싱글톤 패턴은 인스턴스를 하나만 생성하도록 보증하는 패턴, 최초로 인스턴스를 생성하면 그 이후에 인스턴스를 계속해서 생성해도 똑같은 인스턴스를 반환시켜준다.
Service service = new Service();
클라이언트가 위의 객체를 사용하는 어떤 프로그램을 사용할 때 마다 , 인스턴스를 생성
만약 다수의 클라이언트가 동시에 서비스를 사용한다면?
만약 A,B,C 3명이 아닌 100,000명 1,000,000명이 이용한다면 그수에 맞는 인스턴스를 생성, 소멸해야한다.
이는 엄청난 메모리 낭비와 함께 트래픽 문제를 발생시킨다.
하지만
싱글톤패턴(Singleton Pattern) 은 하나의 실객체만을 반환시켜주어 하나의 Service()객체를 모든 클라이언트가 공유해서 쓸 수 있도록 해준다.
싱글톤패턴에는 여러가지 종류가 있지만 , 그 중 하나를 예시를들어 코드를 짜보면 다음과 같다.
그 결과 똑같은 객체를 반환한다.
싱글톤을 사용하는 이유 ,장점
- 고정된 메모리 영역을 가지고 하나의 인스턴스만 사용 →메모리 절약
- 싱글톤 클래스의 인스턴스는 전역변수이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉬움
- DBCP(DataBase Connection Pool) 과 같은 공통된 객체를 여러개 생성해야 하는 상황에 자주 사용
싱글톤의 단점
- 구현하는 코드가 많아짐
- DIP(Dependency Inversion Principal , 의존 관계 역전 원리) 위반
- OCP(Open Closed Principal , 개방 폐쇄의 원리) 위반
SingletonTest는 결국 SingletonService라는 구현체에 의존 , DIP는 인터페이스에 의존해야한다.
그러나 위의 코드는 구체화된 클래스에 의존하다보니 변경과 수정에 자유롭지 못함 따라서 OCP 위반
따라서 결과적으로
객체지향과는 거리가 먼 패턴이다.
싱글톤으로 설계하면 필연적으로 다른 서비스들과의 의존성이 올라가기 때문에 테스트가 용이하지않다.
그렇다면 객체지향의 원칙도 지키면서 , 싱글톤 패턴을 써서 객체를 구현하려면 어떻게 해야할까?
개발자들에게 찾아온 봄 , Spring
Spring의 객체관리 - Spring Container
스프링 컨테이너는 기본적으로 싱글톤 컨테이너 역할을 한다.
빈을 등록할때 별다른 설정을 하지않으면 기본적으로 싱글톤방식으로 객체를 생성한다.
이는 스프링이 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는 싱글톤 레지스트리를 갖고 있기 때문이다. ( 싱글톤과는 대비되는 프로토타입으로 설정도 가능)
스프링의 싱글톤 컨테이너는 기존의 싱글톤패턴의 스태틱 메소드와 private 생성자를 사용해야하는 비정상적인(인용) 클래스가 아니라 평범한 자바 클래스를 싱글톤으로 활용하게 해준다.
스프링 컨테이너의 생성 & 테스트
1) DI 컨테이너 + @Configuration
제어를 역전하는 DI 컨테이너에 각각 서비스를 구성하는 객체의 의존관계를 주입하여 생성하는 메서드를 생성후 @Bean 을 붙여 반환되는 객체를 스프링 컨테이너에 빈으로 등록
스프링 컨테이너는 @Configuration 이 붙은 AppConfig 를 설정(구성) 정보로 사용한다. 여기서 @Bean 이라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다
2) 스프링 컨테이너 생성
스프링 컨테이너 생성 -> new AnnotationConfigApplicationContext(AppConfig.class)
3) 의존관계 설정
4) 테스트결과
싱글톤(스프링) 컨테이너의 주의점
무상태성(Stateless)으로 설계해야함 , 상태를 유지하는 필드가 존재하면 무시무시한 일이 발생
EX) 상태성(stateful)로 설계한 객체를 스프링빈에 담아서 테스트
price 같이 값이 상태를 유지하는 필드를 가진 객체를 생성
해당 객체를 빈으로 등록후 스프링 컨테이너를 테스트
여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지 (stateful)하게 설계하면 안된다
따라서 상태를 유지하는 price필드로 인하여 A사용자는 10000원 짜리 상품을 구매하고 , 나중손님이 20000원 짜리 상품을 구매하면 20000원을 결제해야하는 위험한 상황을 초래
정리
- 객체를 하나만 생성하여 클라이언트가 공유해야 하는 상황에서 싱글톤패턴은 적절한 디자인패턴 하지만 객체지향의 특성을 살리기 어렵고 테스트가 쉽지않다는 단점이 존재
- Springframework의 스프링 컨테이너(싱글톤 컨테이너)는 객체들을 싱글톤으로 관리해주며 , 객체지향의 원칙을 위반하지 않게하여 개발자들의 개발을 더욱 편하게 해준다.
- 단, DBCP 같은 다수의 클라이언트가 공동으로 사용하며 , 반복적으로 사용되는 객체에 사용되어야 하고 , 무상태성으로 설계하여야한다.
'Spring > Spring Study' 카테고리의 다른 글
[Inflearn] 컴포넌트 스캔과 자동 의존 관계 주입 (0) | 2021.08.20 |
---|---|
[Inflearn] 스프링 컨테이너와 빈 (0) | 2021.07.01 |
[Inflearn] AppConfig 리팩터 + (7월7일 내용 수정 및 보강) (0) | 2021.06.30 |
[Inflearn] 좋은 객체 지향 설계 원칙 (0) | 2021.06.29 |
[Inflearn] AppConfig (0) | 2021.06.28 |