[Spring] 싱글톤 컨테이너
웹 애플리케이션과 싱글톤
기존 appConfig 방식으로 객체를 생성하면, 호출할 때마다 새로운 객체를 생성한다.
이렇게 되면 우리가 100번의 요청을 하면 100개의 객체가 만들어져서 메모리 효율 상 좋지 않다.
이를 해결하기 위해 나온 것이 싱글톤이다.
싱글톤 패턴
클래스의 인스턴스가 딱 1개만 생성되는 것을 보장
이를 위해서는 해당 클래스의 생성자를 private로 만든다. -> 외부에서 new를 통해서 새로 객체를 만들지 못한다.
package hello.core.singleton;
public class SingletonService {
//1. static 영역에 객체를 딱 1개만 생성해둔다.
private static final SingletonService instance = new SingletonService();
//2. public으로 열어서 객체 인스턴스가 필요하면 이 static 메서드를 통해서만 조회하도록 허용한 다.
public static SingletonService getInstance() {
return instance;
}
//3. 생성자를 private으로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 막는다. private SingletonService() {
}
public void logic() { System.out.println("싱글톤 객체 로직 호출");
} }
위에는 싱글톤 패턴의 클래스이다.
우선 자기 자신의 객체를 static 메모리 영역에 생성하여 적용해둔다. 그 다음 외부에서 해당 객체를 꺼내서 쓸 수 있도록 getInstance() 메서드를 만든다.
하지만 이렇게 하면 DIP, OCP를 위반하고, 테스트가 어려워지는 등의 문제점이 발생한다.
하지만 스프링 컨테이너가 이를 모두 해결한 방식의 싱글톤을 제공한다.
싱글톤 컨테이너
스프링 컨테이너는 싱글턴 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리한다. 따라서 고객의 요청이 올 때마다 객체를 생성하지 않고, 이미 만들어진 객체를 공유한다.
컨테이너는 하나의 객체를 생성하고 관리한다. 이렇게 하면 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 되고, DIP, OCP, 테스트, private 생성자로부터 자유롭게 싱글톤을 사용할 수 있다.
싱글톤 방식의 주의점
싱글톤 컨테이너는 객체 인스턴스를 하나만 생성해서 공유하는 방식이다. 따라서 싱글톤 객체는 무상태로 설계해야한다
특정 클라이언트에 의존적인 필드가 있으면 안되고, 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
이런식으로 다른 사용자의 데이터와 섞이는 문제가 발생할 수 있다.
@Configuration과 싱글톤
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
... }
위와 같은 코드에서 memberService와 orderService가 동일하게 memberRepository를 호출한다.
이 때 new MemoryMemberRepository를 호출하므로 싱글톤이 깨질 것이라고 생각할 수 있다.
하지만 각 메서드에 로그를 출력하도록 수정하고, 위 메서드를 모두 한번씩 호출해보면, memberRepository가 한번만 호출되는 것을 볼 수 있다.
@Configuration과 바이트코드 조작의 마법
스프링컨테이너는 스프링 빈이 싱글톤이 되도록 보장해주어야한다.
Appconfig에 @Configuration 어노테이션을 쓰고, 실행하면 Appconfig도 빈으로 등록된다.
이 때 그냥 AppConfig가 들어가는게 아니라, AppConfig를 상속받은 클래스가 들어간다.
이 클래스는
이와 같이 동작하여 싱글톤을 유지할 수 있도록 한다.
만약 AppConfig에 @Configuration 말고 @Bean을 적용했으면 싱글톤이 지켜지지 않을 수 있다.
출처
인프런 김영한강사님 - 스프링 핵심원리 기본편
스프링 핵심 원리 - 기본편 강의 | 김영한 - 인프런
김영한 | 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보
www.inflearn.com