싱글톤과 스프링 컨테이너

MinSeong Kang·2022년 1월 13일
0

spring

목록 보기
6/18
post-thumbnail

싱글톤 패턴이란?

애플리케이션이 시작될 때, 어떤 클래스가 최초 한번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인패턴이다. 따라서 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 단 하나이며, 최초 생성 이후에 호출된 생성자는 최초에 생성한 객체를 반환한다.

(1) 자바코드에 싱글톤 패턴 적용

public class SingletonInstance {
	
    // 1
    private static final SingletonInstance instance = new SingletonInstance();
	
    // 2
    public static SingletonInstance getInstance() {
        return instance;
    }
	
    // 3
    private SingletonInstance() {
    }
}

주석 1 : static 변수를 사용하여 인스턴스가 사용되는 시점이 아닌 클래스가 로딩되는 시점에 실행하도록 한다.
주석 2 : getInstance 메서드를 통해서만 해당 객체를 얻을 수 있도록 한다.
주석 3 : 생성자를 private으로 지정하여 new를 통한 객체 생성이 불가능하도록 한다.

다른 예시 코드
public class SingletonInstance {

   private SingletonInstance() {
   }

   private static SingletonInstance instance = null;

   public synchronized static SingletonInstance getInstance() {
       if (instance == null) {
           instance = new SingletonInstance();
       }
       return instance;
   }
}    

(2) 싱글톤 패턴을 사용하는 이유?

요청이 있을 때마다 객체를 생성하는 것이 아니라, 이미 생성되어진 객체를 공유하여 재사용이 가능하여 메모리 방지를 방지할 수 있다.

(3) 싱글톤의 문제점?

  1. 싱글톤 패턴을 구현하는 코드가 많이 필요하다.
  2. 테스트를 하기가 어렵다.
  3. 의존관계상 클라이언트가 구체클래스에 의존하게되어, DIP 원칙을 위반하고 OCP원칙을 위반할 가능성이 높다.
  4. private 생성자로 자식 클래스를 만들기 힘들며, 내부 속성을 변경하기 어렵다.

싱글톤 컨테이너 (스프링 컨테이너)

싱글톤 패턴의 문제점을 해결하면서, 따로 싱글턴 패턴을 적용하지 않아도 기본적으로 객체를 싱글톤으로 유지할 수 있는 컨테이너

  • 싱글톤 패턴을 적용하기 위한 코드가 필요없다.
  • DIP, OCP 원칙을 준수하며, 테스트가 자유롭게 가능하다.

(1) 싱글톤 방식의 주의점

객체 인스턴스를 하나만 생성하여 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 상태를 유지하게 설계하면 안된다. → 무상태(stateless) 설계

(2) 무상태(stateless) 설계

특정 클라이언트에 의존적인 필드가 있으며 안되며, 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
→ 필드 대신 자바에서 공유되지 않는, 로컬변수, 파라미터 등을 사용해야한다.

  상태를 유지하는 코드
private int age;

public void introduce(String name, int age) {
    System.out.println("이름은 " + name + "이고, 나이는 " + age + "살 이다.");
    this.age = age;
}

public int getAge() {
    return age;
}
  무상태 설계한 코드
public int introduce(String name, int age) {
    System.out.println("이름은 " + name + "이고, 나이는 " + age + "살 이다.");
    return age;
}

(3) @Configuration

스프링 컨테이너가 기본적으로 객체를 싱글톤으로 유지하게 하게끔 하는 핵심은 @Configuration 이다.

@Test
void checkBeanClass() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
    AppConfig bean = ac.getBean(AppConfig.class);

    System.out.println("bean = " + bean.getClass());
}

위 테스트 코드를 통해 1) @Configuration이 붙은 설정 클래스(AppConfig.class)의 클래스명 과
2) @Configuration이 붙지 않는 순수 설정 클래스(AppConfig.class)의 클래스명 을 출력하여 비교해보았을 때,
1) bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$9db1a227
2) bean = class hello.core.AppConfig
@Configuration이 붙은 설정 클래스명 뒤에 추가적으로 $$EnhancerBySpringCGLIB$$9db1a227 있는 것을 확인 할 수 있다.

설정 클래스에 @Configuration가 붙으므로써, 그 설정 파일은 순수 클래스가 아닌 CGLIB라는 바이트코드 조작 라이브러리를 사용하여 기존의 AppConfig 클래스를 상속받은 임의의 다른 클래스를 생성하여 스프링 빈으로 등록한다.

기존 AppConfig 클래스가 아닌 AppConfig@CGLIB 클래스가 스프링 빈으로 등록된다.

AppConfig@CGLIB는 설정 클래스(AppConfig.class) 내에 @Bean이 붙은 객체를 스프링 빈으로 등록할 때, 이미 스프링 빈으로 등록된 객체에 대해서 존재하는 빈을 반환하고, 스프링 빈으로 등록되어 있지 않다면 생성하여 스프링 빈에 등록하고 반환한다.
→ 이를 통해 스프링 컨테이너는 자바 코드를 읽어 객체를 싱글톤으로 유지하고 관리한다.


참고 자료

https://www.inflearn.com/course/스프링-핵심-원리-기본편#
https://jeong-pro.tistory.com/86
https://maenco.tistory.com/entry/Spring-Container스프링-컨테이너-Singleton싱글톤

0개의 댓글