Spring에서 중요하다고 할 수 있는게 뭐가 있을까? 그것은.. Bean이다.
- Spring의 핵심 철학인 DI(Dependency Injection)과 IoC(Inversion of Control)의 중심에 있는 것이 Bean이다.
Bean이 무엇이길래?!
먼저, 의존 역전 원칙(DIP : Dependency Inversion Principle), Interface, DI에 대해 우선 알아보자.
DIP (Dependency Inversion Principle)
- DIP는 의존 역전 원칙으로 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안되며, 둘 다 추상화(인터페이스)에 의존해야 한다는 것이다.
- 이는 추상화된 인터페이스를 통해 상호작용해야 한다는 것이다.
- 상위 모듈은 인터페이스에 의존
- 하위 모듈은 인터페이스를 구현
Interface
- 추상화를 위한 메커니즘으로, 메서드의 선언만 포함하고 구현은 제공하지 않는 구조
- 객체 간의 결합도를 낮추기 위해 사용한다.
DI (Dependency Injection)
- 객체 간 의존성을 외부에서 주입받아 객체 간 결합도를 낮추는 설계 패턴
- 객체 생성 및 관리를 외부 컨테이너(Spring)가 담당
- 필드 주입 : @Autowired 를 필드에 사용
- 생성자 주입 : 생성자를 통해 의존성을 주입
- setter 주입 : setter 메서드를 통해 의존성을 주입
그럼 Spring Bean의 역할은 무엇일까?
- Spring은 IoC 컨테이너(객체의 제어권이 개발자가 아닌 컨테이너가 가짐)를 통해 Bean 객체를 생성, 관리, 소멸까지 담당한다.
- DI를 통해 Bean 간의 의존성을 주입한다.
- Bean은 interface와 DIP 원칙을 적용하여 설계된 객체 간 의존성을 해결한다.
Spring Bean으로 DI와 DIP 구현
// 1. Interface 정의
public interface PaymentService {
void processPayment();
}
// 2. 구현 클래스
@Component
public class CreditCardPaymentService implements PaymentService {
@Override
public void processPayment() {
System.out.println("신용카드 결제");
}
}
// 3. 상위 모듈 (OrderService)
@Component
public class OrderService {
private final PaymentService paymentService;
// 생성자 주입
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService; // DIP 준수
}
public void placeOrder() {
paymentService.processPayment();
}
}
위의 예시를 보면서 생각해보자. 최근에 주문 플랫폼 프로젝트를 진행했기 때문에 Order와 Payment의 경우를 예시로 들었다.
Spring에서 이 코드는 다음과 같이 동작하게 된다.
- IoC 컨테이너 초기화 : 애플리케이션 실행 시 Spring IoC 컨테이너가 초기화된다. IoC 컨테이너는 애플리케이션의 모든 객체(Bean)를 관리하며, 객체의 생성과 주입을 담당한다.
- Bean 스캔 및 등록 : Spring은 @Component 어노테이션이 붙은 클래스를 스캔하여 Bean으로 등록한다.
- 의존성 확인 및 주입 : Spring은 OrderService의 생성자를 분석하고, PaymentService 타입의 의존성이 필요하다는 것을 파악한다. 그리고 PaymentService 인터페이스를 구현한 Bean을 검색하고 OrderService의 생성자에 주입한다.
- 객체 사용 : 애플리케이션이 OrderService Bean을 요청하면 컨테이너는 의존성이 주입된 인스턴스를 반환한다.
이를 통해서 알 수 있는 건 다음과 같다.
- PaymentService 인터페이스에서 CreditCardPaymentService 구현체를 자동으로 연결한다.
- 상위 모듈(OrderService)은 PaymentService 인터페이스에 의존한다. (결제가 필요하다는 것만 알고, 어떻게 결제할 지는 모름)
- 하위 모듈(CreditCardPaymentService)은 인터페이스를 구현한다.
- DI에 의해 구현체가 자동으로 연결된다.
- Spring의 DI는 DIP를 자연스럽게 구현하고 있다.
Bean에 대해서 조금 더 알아보자.
Spring에서는 Bean의 scope를 설정하여 Bean이 생성되고 관리되는 범위를 정의할 수 있다.
Bean의 Scope
- Singleton : Bean의 기본 스코프이다. Spring 컨테이너 내에서 단 하나의 인스턴스만 생성되어 공유된다.
- 사용 시점 : 대부분의 경우, 상태를 공유하지 않는 빈(Stateless Bean)에 적합하다.
- 특징 : Spring 컨테이너가 시작될 때 빈이 생성된다. 모든 요청에 대해 동일한 인스턴스가 반환된다.
- Prototype : 요청 시마다 새로운 인스턴스를 생성한다.
- 사용 시점 : 상태를 가지는 Bean(Stateful Bean)이나 특정 요청마다 새롭게 초기화가 필요한 경우에 적합하다.
- 특징 : 컨테이너가 Bean을 생성 후 초기화만 담당하고, 이후의 라이프사이클은 컨테이너가 관리하지 않는다.
- Request : HTTP 요청 하나마다 새로운 빈 인스턴스를 생성한다.
- 사용 시점 : 웹 애플리케이션에서 HTTP 요청마다 고유한 데이터를 관리할 때 적합하다.
- 특징 : 요청이 끝나면 빈은 소멸된다.
- WebSocket : 웹소켓 세션 동안 동일한 Beean 인스턴스를 사용한다.
- 사용 시점 : 웹소켓 연결에 따라 Bean을 분리하여 관리하고 싶을 때 적합하다.
- 특징 : 웹 소켓 연결이 종료되면 Bean도 소멸
... 등등 그외에도 session, application도 있다고 한다.
+) Singleton 타입의 빈의 생애주기
1. Spring 컨테이너 생성 : Spring 컨테이너 (Application Context)가 생성된다.
- Spring은 애플리케이션의 설정을 읽고 Bean의 정의를 메모리에 로드한다.
- 컨테이너는 Bean의 lifecycle을 관리할 준비를 한다.
2. Spring 빈 생성 : Spring 컨테이너가 Bean을 생성한다.
- 설정된 클래스 또는 XML 설정에 따라 Bean 객체를 인스턴스화 한다.
- 이 단계에서는 의존관계가 주입되지 않는다.
3. 의존관계 주입 : Spring 컨테이너가 Bean의 의존성을 주입한다.
- 생성자 주입, 필드 주입, setter 주입 방식으로 다른 Bean을 주입
- 이 과정에서 Bean간의 의존성이 해결
4. 초기화 콜백 : Bean이 초기화 작업을 수행한다.
- 의존 관계 주입이 완료된 후, Bean이 application에서 사용되기 전에 필요한 초기화 작업을 수행한다.
5. 사용 : application의 로직에서 Bean을 사용한다.
- Bean은 요청에 응답하거나, application의 특정 작업을 수행한다.
- Singleton Bean의 경우, 여러 요청이 동일한 인스턴스를 공유
6. 소멸 전 콜백 : 컨테이너가 종료되기 전에 Bean이 리소스를 정리하거나 종료 작업을 수행한다.
- 네트워크 연결 해제, 파일 닫기, 캐시 정리와 같은 작업이 필요할 수 있다.
7. Spring 종료 : application context가 종료된다.
- 컨테이너가 관리하던 모든 빈의 소멸 작업을 완료한 후, 컨테이너 자체가 종료된다.
Bean이라는 이름은 귀엽지만.. Bean의 역할은 아주 중요한 것 같다...🫛🫛
'💻 개발 > Spring' 카테고리의 다른 글
11/29 - TIL : MSA에서의 트랜잭션 (0) | 2024.11.29 |
---|---|
11/22 - TIL : 영속성 컨텍스트와 Transaction (1) | 2024.11.22 |
11/20 - TIL : Spring Cloud와 Load Balancer (1) | 2024.11.20 |
MVC Response - Spring MVC (0) | 2023.12.05 |
Spring Annotation MVC - Spring MVC (0) | 2023.12.05 |