[Spring]프로토타입과 스코프

토비의 스프링 vol2 챕터 1.3 프로토타입과 스코프를 읽고 정리한 글 입니다.

스코프

  • 존재할 수 있는 범위
  • 빈 오브젝트가 만들어져 존재할 수 있는 범위이다.

스프링 빈은 기본적으로 싱글톤으로 만들어 진다.

  • 애플리케이션 컨텍스트마다 빈의 오브젝트는 한 개만 만들어진다.
  • 요청이 있을 때마다 매번 애플리케이션 로직을 담은 오브젝트를 새로 만드는 건 비효율적이기 때문이다.
  • 하나의 빈 오브젝트에 동시에 여러 스레드가 접근하기 때문에 상태 값을 인스턴스 변수에 저장해 두고 사용할 수 없다.
  • 싱글톤으로 설정된 빈은 DI, DL시 항상 같은 오브젝트가 리턴됨이 보장된다.
    • DL (Dependency Lookup) : 컨테이너에서 getBean()을 통해 조회하는 것,
    • 주입 받는 것이 아니라 직접 필요한 의존관계를 찾는 것.

프로토타입 스코프는 컨테이너에게 빈을 요청할 때마다 매번 새로운 오브젝트를 생성해준다.

  • 프로토타입 빈은 IoC의 기본 원칙을 따르지 않는다.
  • 프로토타입 스코프를 갖는 빈은 요청이 있을 때마다 컨테이너가 생성하고 초기화하고 DI까지 해주기도 하지만 일단 빈을 제공하고 나면 컨테이너는 더 이상 빈 오브젝트를 관리하지 않는다.
  • 프로토타입 빈은 생성 후 관리는 전적으로 DI 받은 오브젝트에 달려있다.
    • 프로토타입빈을 주입받은 빈이 싱글톤이라면, 이 빈에 주입된 프로토타입 빈도 역시 싱클톤 생명 주기를 따름
    • 그러나 주입받은 빈의 스코프가 더 작다면, 프로토타입 빈도 해당 빈과 함께 제거
    • 메소드 안에서 사용하고 따로 저장해 두지 않는다면, 메소드가 끝나고 프로토타입 빈도 제거
IoC의 기본 개념은 애플리케이션을 구성하는 핵심 오브젝트를 코드가 아니라 컨테이너가 관리한다는 것이다. 그래서 스프링이 관리하는 오브젝트인 빈은 그 생성과 다른 빈에 대한 의존관계 주입, 초기화(메소드 호출), DI, DL을 통한 사용, 제거에 이르기까지 모든 오브젝트의 생명주기를 컨테이너가 관리한다. 빈에 대한 정보와 오브젝트에 대한 레퍼런스는 컨테이너가 계속 갖고 있고, 필요할 
때마다 요청해서 빈 오브젝트를 얻을 수 있다.

 

프로토타입 빈은 내부에서 스프링의 DI를 통해 빈을 주입받아야 할 경우 사용한다.

  • 프로토타입 빈은 코드에서 new로 오브젝트를 생성하는 것을 대신하기 위해 사용된다.
  • 사용자 요청별로 독립적인 정보나 작업 상태를 저장해둘 오브젝트를 만들 필요가 있다.
  • 이 경우 new로도 충분한데, 왜 프로토 타입 빈을 사용할까?
  • 사용자 요청에 따라 매번 독립적인 오브젝트를 만들어야 하는데, 매번 새롭게 만들어지는 오브젝트가 컨테이너 내의 빈을 사용해야 하는 경우 즉, 프로토타입 빈안에서 DI가 필요한 경우 사용한다.
  • 코드에서 일일이 수동으로 DI를 해줄 것이 아니라면 프로토타입빈으로 생성하는 것이 좋다.
  • 매번 새로운 오브젝트가 필요하면서 DI를 통해 다른 빈을 사용할 수 있어야 한다면? -> 프로토타입빈 사용

 

요청 스코프 빈은 하나의 웹 요청 안에서 만들어지고 해당 요청이 끝날 때 제거된다.

  • 각 요청별로 독립적인 빈이 만들어지기 때문에 빈 오브젝트 내에 상태 값을 저장해 둬도 안전하다.
  • 하나의 웹 요청을 처리하는 동안 참조하는 요청 스코프 빈은 항상 동일한 오브젝트임이 보장된다.

세션 스코프는 HTTP 세션과 같은 존재 범위를 갖는 빈이다.

  • HTTP 세션은 사용자별로 만들어지고 브라우저를 닫거나 세션 타임이 종료될 때까지 유지되기 때문에 로그인 정보나 사용자별 선택옵션을 저장해두기에 유용하다.
  • 웹 환경에종속적인 HttpSession을 다른 계층으로 넘겨서 사용하게 하는 건 좋지 않다. -> HTTP 세션에 저장되는 정보를 웹 기술에 종속적이지 않은 오브젝트에 담아서 (ex. DTO(?)) HTTP 세션에 직접 접근이 가능한 프레젠테이션과 서비스 계층사이에 주고받아야 한다.
  • 세션 스코프를 이용하면 이런 번거로움 없이도 HTTP 세션에 저장되는 정보를 모든 계층에서 안전하게 이용할 수 있다.

 

애플리케이션 스코프는 서블릿 컨텍스트에 저장되는 빈 오브젝트이다.

  • 서블릿 컨텍스트는 웹 애플리케이션마다 만들어진다.
  • 웹 애플리케이션마다 스프링의 애플리케이션 컨텍스트도 만들어진다.
  • 드물지만 웹 애플리케이션과 싱글톤 스코프가 다른 경우가 있다.
  • 애플리케이션 스코프도 싱글톤 스코프와 마찬가지로 상태를 갖지 않거나, 상태가 있다고 하더라도 읽기전용으로 만들거나, 멀티스레드 환경에서 안전하도록 만들어야 한다.

 

스프링 빈 생명주기 메소드로 초기화 메소드와 소멸메서드가 있다.

해당 부분은 초보 웹 개발자를 위한 스프링5 프로그래밍 입문의 내용을 정리하였습니다.

 

컨테이너가 관리하는 빈 객체의 라이프사이클은 객체 생성 -> 의존 설정 -> 초기화 -> 소멸의 라이프 사이클을 가진다. 스프링 컨테이너는 빈 객체를 초기화하고 소멸하기 위해 빈 객체의 지정한 메서드를 호출한다. 스프링은 다음의 두 인터페이스에 이 메서드를 정의하고 있다.

  • InitializingBean
  • DisposableBean

모든 클래스가 위의  인터페이스를 구현하여 사용할 수 있는 것이 아니다. 외부에서 제공받은 클래스에서 사용하고 싶은 경우에는 스프링 설정에서 직접 초기화, 소멸 메서드를 지정할 수 있다.

@Bean(initMethod="connect", destroyMethod="close")
public Client2 client2() {
    Client2 client = new Client2();
    client.setHost("Host");
    return client;
}

 

혹은 @PostConstruct, @PreDestory 애노테이션을 적용해서 초기화, 소멸 메서드를 지정 할 수 있다.

 

 

스프링은 왜 싱글톤을 기본 스코프로 사용할까?

  • 서버 성능에 좋기 때문이다.
  • IoC컨테이너를 통해 주입받는 싱글톤 스코프 빈은 '동일성'을 보장한다. 
  • 스프링이 주로 적용되는 대상은 자바 엔터프라이즈 기술을 사용하는 서버환경이다. 초 당 많은 요청을 받아내야 하고, 요청을 처리하기 위해 컨트롤러 단, 서비스 단, 레포지토리 단으로 많은 계층으로 구성되어있다. 그리고 이 계층 마다 다양한 객체들이 참여하여 협력한다.
  • 그런데 요청이 들어올 때 마다 비즈니스 로직 처리를 위한 객체를 새로 생성한다면? -> 힙 메모리가 꽉 찰 것이다.

 

멀티 스레드 환경에서 싱글톤은 무상태성으로 만들어져야 한다.

  • 싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있다.
  • 다중 사용자의 요청을 한꺼번에 처리하는 스레드들이 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우 위험하다.
  • 저장할 공간이 하나 뿐이니 서로 값을 덮어쓰고, 자신이 저장하지 않은 값을 읽어올 수 있기 때문이다.

댓글



Designed by JB FACTORY