이 글은 김영한 님의 스프링 핵심 원리 - 기본편을 수강하며 정리한 글입니다.
싱글톤 패턴
스프링 컨테이너를 쓰면 스프링 컨테이너가 객체들을 싱글톤으로 만들어서 관리해 준다!
클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다. 스프링 없는 순수한 DI 컨테이너의 경우 는 요청을 할 때마다 객체를 새로 생성하므로 메모리 낭비가 심하다. 해당 객체가 딱 1개만 생성되고, 공유하는 싱글톤 패턴의 적용이 필요하다.
더보기
private static final SingletonService instance = new SingletonService(); // 자기 자신을 static으로 가진다
public static SingletonService getInstance() { //조회
return instance;
}
private SingletonService() { // 생성자를 private으로 선언
}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
문제점
- 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.
- 의존관계상 클라이언트가 구체 클래스에 의존한다. → DIP를 위반한다. .getInstance() 하여 접근해야 한다
- 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다.
- 테스트하기 어렵다.
- 내부 속성을 변경하거나 초기화 하기 어렵다.
- private 생성자로 자식 클래스를 만들기 어렵다.
- 유연성이 떨어진다.
- 안티패턴으로 불리기도 한다.
스프링 프레임워크는 싱글톤 패턴의 문제점을 다 제거하면서 객체를 싱글톤으로 관리해 준다.
🗯️ 주의점
객체 인스턴스를 하나만 생성해서 공유하게 되면 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하게 된다. 때문에 싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안 된다. 무상태(stateless)로 설계해야 한다.
- 특정 클라이언트에 의존적인 필드가 있으면 안 된다.
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안 된다. (가급적 읽기만 가능해야 한다.)
- 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
@Configuration과 바이트코드 조작
스프링 설정 정보는 항상 @Configuration을 사용하자.
스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.
@Test
void configurationDeep() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
System.out.println("bean = " + bean.getClass());
}
bean = class hello.core.AppConfig // 예상(순수한 자바 코드)
bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$4c90c804 // 실제 출력 CGLIB
🌳 CGLIB : 바이트코드 조작 라이브러리
라이브러리를 사용해서 해당 클래스를 상속받은 다른 클래스를 만들어서 스프링 빈으로 등록한다.
@Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
🌳 @Configuration을 적용하지 않고, @Bean만 적용한다면?
CGLIB 기술 없이 순수한 AppConfig로 스프링 빈에 등록된다.
→ 싱글톤이 깨져서 memberRepository가 여러 번 호출된다. (new로 객체 생성을 여러 번 하게 된다)
bean = class hello.core.AppConfig
'Back-End > Spring' 카테고리의 다른 글
[Spring] 의존관계 자동 주입 방법 (0) | 2022.03.20 |
---|---|
[Spring] 🌟 컴포넌트 스캔과 의존관계 자동 주입 (0) | 2022.03.19 |
인프런 스프링 강의 (0) | 2022.03.09 |
[Spring] BeanFactory와 ApplicationContext (0) | 2022.03.08 |
[Spring] 스프링 빈 조회 (0) | 2022.03.08 |
댓글