[Spring] 빈 스코프(Bean Scope)

SEB_BE_43_yeori316·2023년 2월 5일
0

Spring

목록 보기
8/22

빈 스코프(Bean Scope)

bean definition을 만들 때 해당 bean definition에 의해 정의된 클래스의 실제 인스턴스를 만들기 위한 레시피를 만듭니다.
빈이 존재할 수 있는 범위를 의미합니다.

  • 특정 bean 정의에서 생성된 개체에 연결할 다양한 의존성 및 구성 값뿐만 아니라 특정 bean 정의에서 생성된 개체의 범위도 제어할 수 있습니다.

  • Spring Framework는 6개의 범위를 지원하며, 그 중 4개는 ApplicationContext를 사용하는 경우에만 사용할 수 있습니다.

  • bean은 여러 범위 중 하나에 배치되도록 정의할 수 있습니다.

  • 구성을 통해 생성하는 개체의 범위를 선택할 수 있기 때문에 강력하고 유연합니다.

  • 사용자 정의 범위를 생성할 수도 있습니다.

싱글톤(singleton) 스코프

클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는디자인 패턴입니다.

  • 스프링 컨테이너의 시작과 함께 생성되어서 스프링 컨테이너가 종료될 때 까지 유지됨
  • 싱글톤 빈의 하나의 공유 인스턴스만 관리하게 됩니다.
    • private 생성자를 사용해 외부에서 임의로 new를 사용하지 못하도록 막아야 함
  • 해당 bean definition와 일치하는 ID 또는 ID를 가진 빈에 대한 모든 요청은 스프링 컨테이너에서 해당 특정 빈 인스턴스를 반환합니다.

  • 스프링 컨테이너 종료시 소멸 메서드도 자동으로 실행됨

싱글톤 내용 정리

  • 싱글턴은 해당 빈의 인스턴스를 오직 하나만 생성해서 사용하는 것을 의미함

  • 단일 인스턴스는 싱글톤 빈의 캐시에 저장됨

  • 이름이 정해진 빈에 대한 모든 요청과 참조는 캐시된 개체를 반환함

  • 싱글톤 스코프의 스프링 빈은 여러번 호출해도 모두 같은 인스턴스 참조 주소값을 가짐

핵심 포인트

  • bean 하나에 하나씩 메타 정보가 생성되고, 스프링 컨테이너는 이런 메타 정보를 기반으로 스프링 빈을 생성

실습 - 싱글톤(singleton)

스프링 없는 컨테이너만 사용한 객체 생성 방법

public class SingletonTest {

    static DependencyConfig dependencyConfig = new DependencyConfig();

    static MemberService memberService1 = dependencyConfig.memberService();
    static MemberService memberService2 = dependencyConfig.memberService();

    public static void main(String[] args) {
        System.out.println("memberService1 : " + memberService1);
        System.out.println("memberService1 : " + memberService2);
        /*
            같은 memberService를 사용하지만 뒤에 붙은 주소값이 다른걸 볼 수 있습니다.
            수 많은 객체를 생성하게 되면 위에 방식은 메모리 낭비와 효율성이 떨어지게 됩니다.
            위 문제에 대한 해결방법으로 싱글톤 패턴을 사용할 수 있습니다.
        */
    }
}

싱글톤 패턴 적용 코드

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 class SingletonTest {

    static SingletonService singletonService1 = SingletonService.getInstance();
    static SingletonService singletonService2 = SingletonService.getInstance();

    public static void main(String[] args) {
        System.out.println("SingletonService1 : " + singletonService1);
        System.out.println("SingletonService2 : " + singletonService2);
        // 같은 SingletonService를 사용하는 모든 객체는 같은 인스턴스를 바라보게 됩니다.
    }
}

스프링 컨테이너의 기본값은 싱글톤입니다.

  • 위 코드처럼 직접 static 인스턴스를 직접 만들지 않아도 됨

싱글톤 패턴의 문제점

  • 싱글톤 패턴을 구현하는 코드 자체가 많습니다.

  • 의존관계상 클라이언트가 구체 클래스에 의존합니다.

  • 지정해서 가져오기 때문에 테스트하기 어렵습니다.

  • private 생성자를 사용하여 자식 클래스를 만들기 어렵기 때문에 유연성이 떨어집니다.

  • 속성 공유
    • 멀티쓰레드 환경에서 싱글톤 객체의 속성은 여러 쓰레드에 의해 바뀔 수 있습니다.
    • A 쓰레드에선 속성 값을 x로 바꾸고 출력하는 과정에서 B 쓰레드가 속성 값을 y로 바꾸면 쓰레드 A에선 예상하지 못한 값이 나올 수 있습니다.
      (1개의 인스턴스에서 속성 값을 공유하기 때문에 발생하는 문제점입니다.)
    • 가급적 읽기만 가능해야 합니다.
  • Application 초기 구동 시 인스턴스 생성
    • 싱글톤 빈은 기본적으로 애플리케이션 구동 시 생성되므로 싱글톤 빈이 많을 수록 구동 시간이 증가할 수 있습니다.

싱글톤 패턴 문제를 싱글톤 컨테이너가 해결해줍니다.

  • 객체 인스턴스를 싱글톤으로 관리

  • 스프링 컨테이너는 싱글톤 컨테이너 역할을 합니다.

  • 싱글톤 객체로 생성하고 관리하는 기능을 싱글톤 레지스트리라 합니다.

  • 스프링 컨테이너의 위 기능 덕분에 싱글턴 패턴의 모든 단점을 해결하며 객체를 싱글톤으로 유지할 수 있습니다.

static AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(DependencyConfig.class);

static MemberService memberService1 = ac.getBean("memberService", MemberService.class);
static MemberService memberService2 = ac.getBean("memberService", MemberService.class);

싱글톤 방식의 주의점

  • 싱글톤 방식은 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 무상태로 설계해야 합니다.
    • 특정 클라이언트가 값을 변경할 수 있으면 안됩니다.
    • 읽기만 가능해야 합니다.
    • 스프링 빈의 공유 값을 설정하면 장애가 발생할 수 밖에 없습니다.

핵심 포인트

  • 스프링 컨테이너에서 빈 스코프의 기본값은 싱글톤 스코프이다.
  • 싱글톤 패턴을 사용할때 발생하는 문제점을 싱글톤 컨테이너로 해결할 수 있다.

0개의 댓글