Spring

Bean 스코프

Jay-JI 2024. 7. 16. 19:53

Bean Scope 란

 

Bean은 스프링 컨테이너에서 관리하는 객체를 의미하며 Bean Scope는 이러한 Bean이 존재할 수 있는 범위를 뜻한다.

Bean의 기본 스코프는 singleton이라 어플리케이션이 구동되는 동안 하나의 인스턴스만 생성되어 사용된다. 많은 Spring 개발자들이 Bean의 스코프를 기본값인 singleton으로만 사용하기 때문에 크게 신경 쓰지 않는 경우가 많다. 하지만 Bean 스코프를 잘 활용하면 보다 다양한 요구사항에 맞춰 어플리케이션을 효율적으로 개발할 수 있다.

 

참고로 Bean scope는 다음과 같이 사용할 수 있다.

@Component
@Scope(value = "prototype")
public class ProtoType {
}

 

Bean Scope 종류

 

Bean 스코프의 종류는 다음과 같다.

스코프 설명
singleton (기본값) 스프링 IoC 컨테이너당 하나의 인스턴스만 사용
  - 어플리케이션이 구동되는 동안 하나의 bean만 생성됨
prototype 매번 새로운 bean이 생성됨
request HTTP request 사이클마다 한 개의 bean을 사용
  - 즉, 요청이 들어오고 나갈 때까지 bean 유지됨
  - 웹 관련 기능에서만 사용 가능
session HTTP session 마다 한 개의 bean을 사용
  - 즉, 웹 세션이 생성되고 종료될 때까지 bean이 유지됨
  - 웹 관련 기능에서만 사용 가능
application Servlet Context의 사이클마다 한 개의 bean을 사용
  - ServletContext는 웹 어플리케이션 전체의 생명주기를 관리하는 컨텍스트
  - ServletContext는 웹 어플리케이션이 시작될 때 생성되고, 종료될 때 소멸됨
websocket Web Socket 사이클마다 한 개의 bean을 사용
  - 즉, 웹소켓이 연결되고 종료될 때까지 bean이 유지됨

 

1. singleton

  • 주로 상태가 없는 서비스나 리소스를 관리할 때 쓰임
  • @Controller, @Service와 같은 bean 들은 메소드의 파라미터와 리턴값으로 다뤄지기 때문에 인스턴스 자체가 상태를 유지하지 않는다.
  • 매번 bean을 생성하지 않기 때문에 메모리 관리도 효율적임

2. prototype

  • 주로 상태를 가지는 인스턴스가 필요한 경우에 쓰임
  • 각 작업마다 새로운 인스턴스가 필요 / 복잡한 초기화 필요 / 단기 사용 객체가 필요한 경우에 사용하면 효과적임
  • 일반적인 로직보다 특별한 경우에 사용함

3. request

  • HTTP request 사이클 동안 독립적인 상태를 가지는 인스턴스가 필요한 경우에 쓰임
  • ex) 사용자가 검색을 할 때마다 입력하는 검색 조건을 bean으로 등록하면 다른 bean에서 검색 조건을 손쉽게 호출 가능

4. session

  • HTTP session이 유지되는 동안 독립적인 상태를 가지는 인스턴스가 필요한 경우에 쓰임
  • ex) 사용자의 로그인 세션 정보를 bean으로 등록하면 다른 bean에서 사용자 세션 정보를 손쉽게 호출 가능

5. application

  • 하나의 Servlet Context 내에서 bean을 공유할 때 사용
    - Servlet Context는 웹 어플리케이션 내의 모든 서블릿과 JSP가 공유하는 환경 설정 객체이다.
    - Servlet Context는  웹 어플리케이션의 전역 정보를 저장하고 공유하며, 리소스와 설정에 접근할 수 있는 기능을 제공한다.
  • ex) 하나의 Servlet Context 내에 여러 모듈로 구성된 애플리케이션에서, 모든 모듈에서 공유되어야 하는 빈을 생성할 때 유리함
ecommerce-app

├── pom.xml (또는 build.gradle)

├── product-service
│   ├── src/main/java/com/example/product
│   ├── src/main/resources
│   ├── pom.xml (또는 build.gradle)

├── order-service
│   ├── src/main/java/com/example/order
│   ├── src/main/resources
│   ├── pom.xml (또는 build.gradle)

└── user-service
    ├── src/main/java/com/example/user
    ├── src/main/resources
    ├── pom.xml (또는 build.gradle)

 

6. websocket

  • Web Socket 연결이 유지되는 동안만 사용되는 bean을 생성할 때 사용
  • ex) 웹 소켓 연결에서 사용되는 session 정보를 bean으로 생성하여 사용하는 경우

 

prototype scope 사용시 주의할 점

 

prototype scope는 매번 새로운 bean을 생성한다. 반면 singleton scope는 bean을 한번만 생성한다. 따라서 singleton scope를 가진 A라는 bean에 prototype scope를 가진 B라는 bean이 주입되었다면 B라는 bean은 매번 새로운 bean을 생성하지 않는다.

따라서 문제를 해결하기 위해서는 다음과 같은 방법이 필요하다.

 

1. proxy mod

@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProtoType {
}
  • 프로토타입으로 쓸 bean을 대상으로 위와 같이 설정하면 된다.
  • 만약 해당 객체가 클래스가 아니라 인터페이스라면 proxyMode = ScopedProxyMode.INTERFACES 를 사용하면 된다.

2. ObjectProvider 객체 사용

@Component
public class Single {

    @Autowired
    ObjectProvider<ProtoType> protoType;

    public ProtoType getProtoType() {
        return protoType.getIfAvailable();
    }
}

 

3. @Lookup 사용

@Component
public class SingletonBean {

    @Lookup
    public PrototypeBean getPrototypeBean() {
        // Spring이 이 메서드를 오버라이드하여 매번 새로운 인스턴스를 반환합니다.
        // 따라서 return 값이 null이어도 PrototypeBean 을 return 한다. 
        return null;
    }
}

출처:
https://velog.io/@probsno/Bean-%EC%8A%A4%EC%BD%94%ED%94%84%EB%9E%80
https://catsbi.oopy.io/b2de2693-fd8c-46e3-908a-188b3dd961f3
https://code-lab1.tistory.com/186
https://xephysis.tistory.com/25