스프링 프레임워크를 처음 접할 때 가장 자주 등장하는 용어 중 하나가 바로 "Bean"입니다. 처음 이 용어를 들으면 "콩(bean)?"이라고 생각할 수 있지만, 사실 스프링에서 말하는 Bean은 자바 객체입니다. 조금 더 정확하게는, 스프링 IoC 컨테이너에 의해 관리되는 자바 객체를 말해요. 하지만 이렇게 말하면 여전히 어렵게 느껴질 수 있죠. 그래서 Bean이 정확히 무엇이고, 어떻게 사용하는지 하나씩 알아보도록 하겠습니다.
1. 스프링 Bean이란 무엇인가?
스프링에서 말하는 "Bean"은 객체입니다. 다만, 모든 객체가 Bean은 아닙니다. 스프링은 IoC(Inversion of Control, 제어의 역전)이라는 디자인 패턴을 사용해 애플리케이션을 구성하고 관리합니다. 이 때 스프링 IoC 컨테이너에서 관리되는 객체들만 Bean이라고 불리죠.
간단하게 설명하자면, Bean은 스프링이 생성하고, 의존성을 관리하는 자바 객체입니다.
2. 왜 Bean이 중요한가?
스프링의 핵심은 객체 간의 의존성을 관리하는 것입니다. 예를 들어, 클래스 A가 클래스 B를 필요로 할 때, A가 B를 직접 생성하면 둘 사이의 결합도가 높아져 유지보수가 어려워질 수 있습니다. 스프링은 이런 문제를 해결하기 위해 의존성 주입(Dependency Injection)이라는 개념을 도입했습니다.
스프링에서 Bean은 이런 의존성 주입을 통해 클래스들 간의 관계를 간편하게 설정하고 관리할 수 있게 해줍니다.
3. Bean을 만드는 방법
그럼 스프링에서 어떻게 Bean을 만들고 사용하는지 알아보겠습니다. 크게 세 가지 방법이 있습니다.
1) @Component
와 @Autowired
를 사용한 방법
스프링에서 가장 기본적으로 사용하는 방법 중 하나가 바로 @Component
애너테이션입니다. 이 애너테이션을 클래스 위에 붙이면, 스프링이 해당 클래스를 Bean으로 등록합니다. 그리고 @Autowired
를 통해 필요한 곳에 자동으로 주입할 수 있습니다.
import org.springframework.stereotype.Component;
@Component // 이 클래스는 스프링의 Bean이 된다!
public class CoffeeMaker {
public void brew() {
System.out.println("Brewing coffee...");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Cafe {
private final CoffeeMaker coffeeMaker;
@Autowired // CoffeeMaker Bean을 Cafe에 주입한다.
public Cafe(CoffeeMaker coffeeMaker) {
this.coffeeMaker = coffeeMaker;
}
public void serveCoffee() {
coffeeMaker.brew();
}
}
위 예시에서 CoffeeMaker
클래스는 @Component
애너테이션을 통해 Bean으로 등록되었고, Cafe
클래스는 @Autowired
로 의존성을 주입받았습니다.
2) @Configuration
과 @Bean
을 사용한 방법
두 번째 방법은 @Configuration
클래스에서 @Bean
애너테이션을 사용해 직접 Bean을 정의하는 것입니다. 이 방법은 좀 더 명시적으로 Bean을 설정하고 관리하고 싶을 때 유용합니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public CoffeeMaker coffeeMaker() {
return new CoffeeMaker(); // CoffeeMaker Bean을 반환한다.
}
@Bean
public Cafe cafe() {
return new Cafe(coffeeMaker()); // CoffeeMaker를 Cafe에 주입한다.
}
}
여기서 AppConfig
클래스는 Bean을 설정하는 역할을 합니다. @Bean
애너테이션이 붙은 메서드는 Bean을 반환하고, 스프링 컨테이너가 이를 관리합니다.
3) XML 설정을 사용하는 방법 (구버전 방식)
스프링의 초기 버전에서는 XML 설정 파일을 사용해 Bean을 정의했습니다. 최근에는 자바 기반의 설정을 많이 사용하지만, XML 기반의 설정도 알아두면 좋습니다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="coffeeMaker" class="com.example.CoffeeMaker"/>
<bean id="cafe" class="com.example.Cafe">
<constructor-arg ref="coffeeMaker"/>
</bean>
</beans>
위 XML 파일에서 <bean>
태그를 통해 CoffeeMaker
와 Cafe
객체를 Bean으로 정의하고, Cafe
에 CoffeeMaker
를 주입하고 있습니다.
4. Bean의 생명주기
Bean은 단순히 생성되는 것으로 끝나지 않습니다. 스프링에서 Bean은 일정한 생명주기를 갖고, 이를 통해 객체가 어떻게 생성되고 관리되는지를 알 수 있습니다.
- 생성: Bean이 스프링 컨테이너에 의해 생성됩니다.
- 의존성 주입: 필요한 다른 Bean들이 생성되어 주입됩니다.
- 초기화: Bean이 초기화되면서 필요한 설정이 완료됩니다.
- 사용: Bean이 실제로 사용됩니다.
- 소멸: 애플리케이션이 종료되거나 더 이상 필요하지 않을 때 Bean이 소멸됩니다.
스프링에서는 @PostConstruct
와 @PreDestroy
애너테이션을 사용해 초기화와 소멸 메서드를 지정할 수 있습니다.
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class CoffeeMaker {
@PostConstruct
public void init() {
System.out.println("CoffeeMaker 초기화 중...");
}
@PreDestroy
public void destroy() {
System.out.println("CoffeeMaker 소멸 중...");
}
public void brew() {
System.out.println("Brewing coffee...");
}
}
5. 마무리: Bean의 세계를 즐기자!
이제 "Bean"이 단순한 콩이 아니라, 스프링의 강력한 객체 관리 메커니즘의 핵심이라는 걸 이해하셨나요? 스프링은 Bean을 통해 의존성 주입, 객체 관리, 생명주기 등을 효율적으로 처리하며, 개발자의 편의성을 극대화합니다. Bean 개념을 이해하면 스프링 프레임워크가 어떻게 동작하는지, 그리고 그 강력함이 어디서 오는지 더 명확하게 알 수 있을 거예요.
앞으로 스프링을 사용하면서 Bean을 다루는 다양한 방법과 패턴을 직접 경험해보세요. Bean은 여러분의 개발 여정에서 가장 강력한 도구가 될 것입니다!
이 글이 스프링의 Bean을 이해하는 데 도움이 되었기를 바랍니다. 질문이 있으면 언제든지 댓글로 남겨주세요! :)