Bean이란 스프링 컨테이너가 관리하는 자바 객체이다. 여기서 중요한 개념 중 하나가 빈의 스코프(Scope) 인데, 빈 스코프는 빈 인스턴스가 생성되고 소멸하는 컨테이너 영역을 의미한다.
빈 스코프는 빈을 생성하고 소멸시키는 방법을 결정하여 메모리 관리와 빈의 생성 시점 등을 세밀하게 컨트롤한다.
스프링에서는 기본적으로 6가지의 빈 스코프가 제공된다.
scope | 설명 |
---|---|
singleton | 하나의 빈 인스턴스만 생성하고 캐시에 저장해 재사용 |
prototype | 요청할 때마다 새로운 인스턴스를 생성 |
request | 각 HTTP 요청마다 새로운 빈을 생성 |
session | 각 HTTP 세션마다 빈을 생성하고, 세션이 끝나면 소멸 |
application | ServletContext 수준에서 하나의 인스턴스를 생성 |
websocket | 각 WebSocket 세션마다 별도의 빈 인스턴스를 생성 |
단일 인스턴스를 생성해서 캐시에 저장하고, 이후 모든 요청에서 그 캐시된 인스턴스를 반환하는 방식이다. 이 방식은 메모리 절약과 성능 최적화에 도움을 준다.
빈이 호출될 때마다 새로운 객체를 생성한다. 일반적으로 상태를 가진(stateful) 빈은 프로토타입 스코프를 사용하고, 상태가 없는(stateless) 빈은 싱글톤 스코프를 사용한다. 다른 스코프와 달리 프로토타입은 스프링 컨테이너가 모든 생명주기를 관리하지는 않으며, 호출에 의해 빈이 생성되면 컨테이너에서는 빈에 대한 기록을 유지하지 않는다.
Web-aware 스코프
Request, Session, Application, Websocket 스코프는 주로 웹 애플리케이션에서 사용된다. 이들은 웹 관련 요청을 처리할 때만 사용 가능하고, Spring Web MVC와 함께 사용할 때는 DispatcherServlet이 별도의 설정 없이 자동으로 처리해준다.
모든 로그인 Http 요청마다 LoginAction 빈에 대한 새로운 인스턴스를 만들어 request를 처리한다. 각 인스턴스가 별개로 존재하기 때문에 객체 내부의 속성 값 등을 변경해도 다른 인스턴스에는 영향을 끼치지 않는다. 각 객체는 request processing 이 끝날 경우 사라진다.
session scope 로 정의된 빈으로부터 생성된 객체는 http session 이 만료되기 전까지 메모리를 차지한다. 웹 어플리케이션 세션에 대한 데이터를 유지하고 관리할 때 사용된다.
ServletContext 레벨에서 유일한 인스턴스를 생성한다. HTTP 요청이 들어오면 웹 서버는 요청을 처리하기 위해 새로운 스레드와 서블릿을 생성하며, 애플리케이션 스코프로 생성된 빈은 스레드마다 별도의 인스턴스가 생성되어 사용되기 때문에 멀티스레드 환경에서 안전하게 빈을 사용할 수 있다.
웹소켓은 Http 와 다른 프로토콜을 사용하며, 클라이언트와 서버 간 양방향 통신을 가능케 한다. 또한 각 웹소켓 세션마다 별도의 빈 인스턴스가 생성되며 웹소켓 세션의 생명주기와 함께 관리된다. (@WebSocketScope 는 Spring 의 WebSocket 구현체인 Spring Websocket에서만 사용할 수 있다.)
빈 생성 - 스프링 컨테이너가 빈을 생성
의존성 주입 - 생성된 빈에 필요한 의존성을 주입
초기화 콜백 - 초기화 작업을 할 수 있도록 특정 메서드가 호출
빈 사용 - 정상 초기화 후 애플리케이션에서 빈을 사용
소멸 콜백 - 리소스 해제나 연결 종료 등의 작업 수행
빈 생명주기 콜백 관리 방식 3가지
방식 | 장점 | 단점 |
---|---|---|
인터페이스(InitializingBean, DisposableBean) | 명확한 라이프사이클 관리 | 스프링에 의존적, 메서드 이름 변경 불가 |
설정 정보를 통한 메소드 등록 | 메서드 이름 자유롭게 설정 가능, 외부 라이브러리에도 적용 가능 | initMethod, destroyMethod 직접 설정 필요 |
@PostConstruct, @PreDestroy 어노테이션 | 가장 권장되는 방법, 자바 표준 어노테이션으로 다른 컨테이너에서도 동작 | 외부 라이브러리에는 적용 불가 |
public class ExampleBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
// 초기화 콜백 (의존관계 주입이 끝나면 호출)
}
@Override
public void destroy() throws Exception {
// 소멸 전 콜백 (메모리 반납, 연결 종료와 같은 과정)
}
}
public class ExampleBean {
public void initialize() throws Exception {
// 초기화 콜백 (의존관계 주입이 끝나면 호출)
}
public void close() throws Exception {
// 소멸 전 콜백 (메모리 반납, 연결 종료와 같은 과정)
}
}
@Configuration
class LifeCycleConfig {
@Bean(initMethod = "initialize", destroyMethod = "close")
public ExampleBean exampleBean() {
}
}
public class NetworkClient{
...
@PostConstruct
public void init() {
System.out.println("NetworkClient.init");
connect();
call("초기화 연결 메세지");
}
@PreDestroy
public void close() {
System.out.println("NetworkClient.close");
disconnect();
}
}