1장. Spring Bean이란 무엇인가?
Spring Bean은 Spring Framework에서 객체를 관리하는 컨테이너의 기본 단위입니다. Spring Bean이 등록되면, Spring IoC(제어 역전) 컨테이너에 의해 생성, 조립, 관리되는 객체가 됩니다. 여기서 IoC는 객체 생성과 그 객체의 멤버 변수, 메소드 호출을 스프링이 대신 관리함으로써 개발자가 직접 객체를 생성해서 사용할 필요가 없어지는 개념입니다.
Spring Bean은 주로 다음과 같은 장점을 제공합니다:
- 개발자의 코드를 모듈로 분리하여 코드의 재사용성을 향상시킵니다.
- 의존성 주입(Dependency Injection)을 통해 간의 낮은 결합도를 유지시킵니다.
- 스프링의 AOP(관점 지향 프로그래밍)와 함께할 수 있어, 로깅, 트랜잭션 관리, 보안 등의 다양한 기능을 구현하는 것이 용이합니다.
스프링 빈을 생성하는법은 주로 다음 세 가지 가 있습니다:
- XML 기반 설정: Spring의 초기 방식이며, Bean을 정하는 데 사용되는 전용 설정 파일 beandef.xml을 사용합니다.
- 설정 클래스를 이용한 방법: Java 기반 설정으로 @Configuration과 @Bean 어노이션을 사용하여 스프링 빈을 설정합니다.
- 선언적 구성: @Component, @Service, @Repository, @Controller 같은 어노테이션을 사용하여 스프링 빈으로 정의하는 방식입니다.
본문의 다음 장에서는의 생명 주기, 빈 스코프와 빈 간의 연관관계 설정 방법에 대해 자세히 설명합니다.
2장. Spring Bean의 생명주기
Spring Bean의 생명주기는 객체의 생성부터 소멸까지의 여러 단계로 나뉩니다. 이러한 생명주기를 정확하게 이해하고 관리하면 응용 프로그램의 전반적인 성능과 메모리 관리에 도움이 됩니다.
다음은 Spring Bean 생명주기의 주요 단계입니다:
- Bean 생성: 스프링 컨테이너가 Bean 정의를 읽어들여 객체를 생성합니다.
- Bean 초기화: 의존성 주입 및 사용자 정의 초기화 메소드가 실행됩니다.
- Bean 사용: 애플리케이션에서 Bean을 사용하여 요청을 처리합니다.
- Bean 소멸: 스프링 컨테이너가 종료되면서 Bean 객체의 소멸 메서드가 호출됩니다.
Bean 초기화와 소멸에 관련된 두 가지 주요 방법을 사용할 수 있습니다:
- init-method 및 destroy-method 속성을 사용한 방법: 이 방식은 XML 기반 설정에서 주로 사용되며, Bean 정의에서 해당 속성을 지정하여 초기화 및 소멸 메서드를 설정합니다.
- @PostConstruct 및 @PreDestroy 어노테이션을 사용한 방법: Java 기반 설정에서 이러한 어노테이션을 사용하여 초기화 및 소멸 메서드를 정의할 수 있습니다.
또한, 스프링 Application Context의 다양한 이벤트를 감지하여 빈 생명주기를 처리하는 방법도 있습니다. 이러한 이벤트 처리는 ApplicationContextAware, BeanFactoryAware, InitializingBean, DisposableBean 등의 인터페이스를 구현하여 가능합니다.
생명주기를 지정하고 제어하는 것은 Bean이 동작하는 순서를 정확하게 파악하고, 공유 리소스 및 연결 해제 등의 메모리 처리를 개선하여 애플리케이션의 전반적인 성능에 도움이 됩니다.
3장. Spring Bean의 스코프
Spring Bean의 스코프는 Bean 객체의 생존 범위와 공유 수준을 결정합니다. 스코프에 따라 스프링 컨테이너는 각 Bean 요청 시 동일한 인스턴스를 반환하거나 새로운 인스턴스를 생성할 수 있습니다. 스코프의 종류를 이해하고 적절한 스코프를 설정하는 것은 리소스 사용, 성능 최적화, 상황에 맞는 공유 수준 설정에 중요한 역할을 합니다.
Spring Framework에서는 다음의 주요 스코프를 제공합니다:
- Singleton (기본 스코프): 스프링 컨테이너는 각 빈 식별자에 대해 한 개의 인스턴스만 생성하며, 애플리케이션 전체에서 공유됩니다. 이 스코프는 애플리케이션 내 특정 Bean이 단 하나만 필요할 때 사용합니다.
- Prototype: 빈 요청시마다 새로운 인스턴스를 생성합니다. Prototype 스코프는 Bean이 사용되는 상황이나, 특정 기간 동안 변경되는 경우에 적합합니다. 요청자마다 독립적인 개체가 필요한 경우 이 스코프를 사용합니다.
- Request: 웹 애플리케이션에서 각 HTTP 요청에 따라 독립적인 Bean이 생성됩니다. 요청이 끝나면 Bean은 소멸됩니다.
- Session: 스프링 컨테이너는 웹 애플리케이션 내에서 각 사용자 세션에 대해 독립적인 빈 인스턴스를 생성합니다.
- Application: 웹 애플리케이션의 ServletContext에 저장되는 Bean입니다. 애플리케이션의 모든 사용자가 공유하고 있습니다.
스코프를 설정하는 방식은 다음과 같습니다:
- XML 기반 설정: Bean 정의에서 'scope' 속성을 지정합니다. 예시: <bean id="myBean" class="com.example.MyBean" scope="singleton">
- Java 기반 설정: @Scope 어노트를 사용하여 클래스 또는 메서드에 스코프를 지정합니다. 예시: @Scope("singleton")
적절한 스코프를 선택하고 사용하는 것은 애플리케이션의 전반적인 동작, 메모리 사용 및 사용자 경험에 큰 영향을 미칩니다.
4장. Spring Bean 간의 연관 관계 설정하기
Spring Bean 간의 연관 관계 설정은 주로 의존성 주입(Dependency Injection, DI)을 통해 이루어집니다. 이를 통해 개발자는 객체의 생성과 사용을 스프링에 미룰 수 있으며, 각 컴포넌트 간의 결합도를 낮출 수 있습니다. 의존성 주입은 주로 생성자 주입, 세터 메소드 주입 및 필드 주입 방식으로 구현됩니다.
1. 생성자 주입(Constructor Injection): 객체 생성 시 생성자의 매개변수를 통해 의존성을 주입하는 방식입니다. 이 방법은 빈 생성시 충분한 정보를 가지고 있고 의존성이 변경되지 않을 것으로 예상될 때 사용합니다.
public class FooService {
private final BarService barService;
public FooService(BarService barService) {
this.barService = barService;
}
}
2. 세터 메소드 주입(Setter Injection): 객체 생성 후 필요한 의존성을 세터 메소드를 통해 주입합니다. 이 방법은 의존성이 객체의 생성 이후 변경될 수 있을 때 사용합니다.
public class FooService {
private BarService barService;
public void setBarService(BarService barService) {
this.barService = barService;
}
}
3. 필드 주입(Field Injection): 객체의 필드에 직접 의존성을 주입하세요. 이 방법은 생성자가 많은 필드를 가지거나 의존성이 동적으로 변경될 때 사용합니다.
public class FooService {
@Autowired
private BarService barService;
}
또한, 스프링에서 의존성 주입을 관리하는데 사용되는 주요 어노테이션은 다음과 같습니다.
- @Autowired: 스프링 컨테이너에서 자동으로 의존성을 주입하도록 지시하는 어노테이션입니다.
- @Inject: @Autowired와 유사하게 작동하지만, Java 표준인 JSR-330에 속한 어노테이션입니다.
- @Resource: 클래스 이름과 이름으로 빈을 주입합니다. 자바 표준인 JSR-250에 속한 어노테이션입니다.
적절한 연관 관계 설정은 애플리케이션의 유지 보수, 성능 및 확장성에 큰 영향을 미칩니다. 구성 요소 간의 강력한 결합을 피하고, 필요한 경우 직접 의존성을 생성 및 관리하는 대신 스프링의 DI 기능을 활용할 수 있습니다.