Backend/Spring

빈 스코프(Bean Scope)

keepbang 2021. 8. 20. 16:18

빈 스코프(Bean scope)

빈이 존재 할 수 있는 범위를 뜻하며 스프링은 빈 등록시 기본적으로 싱글톤 스코프를 사용하고 있습니다.

@Scope를 통해 스코프를 지정해 줄 수 있습니다.


싱글톤(Singleton)

  • 스프링의 기본 스코프로, 스프링 컨테이너의 시작과 종료까지 유지되는 가낭 넓은 범위의 스코프 범위. 싱글톤 스코프로 빈을 등록하면 맨 처음 객체가 한번 생성됩니다.
  • 빈 요청을 할 때 항상 동일한 인스턴스를 반환하여 사용 할 수 있습니다.
  • 스프링에서@Component로 클래스 파일을 생성하면 싱글톤 스코프로 등록이 됩니다.
    @Test
    void singletonBeanTest(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SingletonBean.class);

        SingletonBean bean1 = context.getBean(SingletonBean.class);
        SingletonBean bean2 = context.getBean(SingletonBean.class);

        System.out.println("bean1 = " + bean1);
        System.out.println("bean2 = " + bean2);

        assertThat(bean1).isEqualTo(bean2);

        context.close();
    }

    @Scope("singleton")
    static class SingletonBean{

        @PostConstruct
        public void init(){
            System.out.println("Singleton Bean PostConstruct");
        }

        @PreDestroy
        public void destroy(){
            System.out.println("Singleton Bean PreDestroy");
        }

    }

singleton으로 빈을 등록했을 때 getBean을 하면 같은 주소의 인스턴스를 가져오는걸 확인 할 수 있습니다.

그리고 Container(ApplicatioContext)가 종료되면 종료 메서드(destroy)가 호출됩니다.


프로토타입(prototype)

  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더 이상 관리하지 않는 매우 짧은 범위의 스코프입니다.
  • 프로토타입 스코프는 싱글톤과 달리 생성하고 의존관계 주입까지만 해주기 때문에 빈을 반환해주는건 클라이언트가 직접 해줘야 합니다.(@PreDestroy같은 종료 메서드는 호출되지 않는다.)
  • 프로토타입 스코프의 빈을 요청하면 항상 새로운 인스턴스를 반환합니다.
    @Test
    void PrototypeBeanTest(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrototypeBean.class);

        PrototypeBean bean1 = context.getBean(PrototypeBean.class);
        PrototypeBean bean2 = context.getBean(PrototypeBean.class);

        System.out.println("PrototypeBean1 = " + bean1);
        System.out.println("PrototypeBean2 = " + bean2);

        assertThat(bean1).isNotEqualTo(bean2);

        context.close();
    }

    @Scope("prototype")
    static class PrototypeBean{

        @PostConstruct
        public void init(){
            System.out.println("Prototype Bean PostConstruct");
        }

        @PreDestroy
        public void destroy(){
            System.out.println("Prototype Bean PreDestroy");
        }
    }

 

prototype으로 빈을 등록하면 getBean을 할 때마다 다른 인스턴스를 반환하는걸 볼 수 있고 close메서드로 Container를 종료했을 때 종료 메서드가 호출되지 않습니다.

 

 

Spring boot에서도 테스트를 해봤습니다.

/**
*  singleton bean
**/
@Component
@Scope("singleton")
public class SingletonService {

    @PostConstruct
    public void init(){
        System.out.println("SingletonService PostConstruct");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("SingletonService PreDestroy");
    }
}

/**
*  prototype bean
**/
@Component
@Scope("prototype")
public class PrototypeService {

    @PostConstruct
    public void init(){
        System.out.println("PrototypeService PostConstruct");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("PrototypeService PreDestroy");
    }
}

 

Service에 각각 Singleton과 Prototype의 빈을 만들어 주고 실행했을 경우 SingletonService의 PostConstruct가 호출된걸 볼 수 있지만 Prototype은 호출이 안됐습니다. Prototype은 Container에서 빈을 받아올때만(의존관계 주입을 했을경우) 인스턴스를 생성하기 때문입니다.


웹 스코프

웹 환경에서만 동작하는 스코프.
스프링에서는 웹 스코프로 설정된 빈들을 해당 스코프의 종료시점까지 관리합니다.(종료 메서드 호출됨)

웹 스코프 종류

  • request : HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리됩니다..
  • session : HTTP Session이 생성되고 종료될 때 까지 유지되는 스코프
  • application : 서블릿 컨텍스트와 동일한 생명주기를 가지는 스코프
  • websocket : 웹 소켓과 동일한 생명주기를 가지는 스코프

 

 

[Reference]

  • 인프런 - 김영한님의 스프링 핵심 원리 기본편