비동기 처리중 하나인 Spring Event.. 넌 누구니?
- Spring Event 시스템의 전체 구조, 동작 원리
- ApplicationEvent, ApplicationListener, EventPublisher의 관계를 명확하게 구분하기
- 이벤트 기반 아키텍처가 왜 필요한지, 어떤 장점을 가지는지 이해하기
- 비동기 처리를 이벤트 시스템에 결합하는 이유
- 실제 서비스 아키텍처에서 이벤트 기반 비동기 처리의 흐름
Spring Event 시스템
애플리케이션 내부에서 비동기적으로 로직을 분리하고 결합도를 낮추기 위한 구조들을 제공하고 있다
이벤트를 발행하면, 등록된 리스너들이 이를 수신하여 후속 작업을 처리한다
이런 개념은 Spring 뿐만 아니라 다양한 아키텍처(Domain Event, Event-driven Architecture)로 확장할 수 있는 기초라고 한다
1. 이벤트 시스템의 구조적 개념
Spring Event 시스템은 크게 세 가지 주요 구성요소로 나뉜다고 한다
| 구성요소 | 역할 | 설명 |
| ApplicationEvent | 이벤트 객체 | 발생한 사건(이벤트)의 정보를 담는 객체 |
| ApplicationEventPublisher | 이벤트 발행자 | 특정 시점에 이벤트를 발생시키는 역할 |
| ApplicationListener | 이벤트 수신자 | 발행된 이벤트를 감지하고, 후속 동작 수행 |
1) 이벤트 시스템의 기본 구조
비즈니스 로직 - > ApplicationEventPublisher - > ApplicationEventMulticaster - > ApplicationListener 1, 2, 3
으로 이어지는 이벤트 전달 체계를 기반으로 한다고 함
Multicaster를 통해 ApplicationListener 1, 2, 3에서 트랜잭션이 나뉘는것 같다
2. ApplicationEvent의 역할
ApplicationEvent는 이벤트 시스템의 중심이라고 함.
특정 상황(회원가입, 주문 생성 등..)이 발생했을 때 그 사실(특정 상황이 발생한 사실)을 객체로 표현한다고 한다.
// Event클래스를 생성하고 ApplicationEvent를 상속한다
public class UserRegisteredEvent extends ApplicationEvent {
private final String userEmail;
public UserRegisteredEvent(Object source,
String userEmail,
String phone,
String memberId) { // 생성자를 통해 필요한 파라미터를 받는다
super(source);
this.userEmail = userEmail
}
}
* Spring 4.2부터는 ApplicationEvent를 상속하지 않고, 일반 POJO(Plain Old Java Object)를 이벤트로 사용할 수 있다고 함
우리가 현재 쓰는게 Spring 6 이상이다!
3. ApplicationEventPublisher의 역할
이벤트를 발행하는 컴포넌트로, Spring 컨텍스트에 기본적으로 내장되어있다고 한다.
public class UserService {
private final ApplicationEventPublisher publisher; // EventPublisher
public UserService(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void registerUser(String email) {
// 대충 비즈니스 로직
System.out.println("사용자 등록 완료 : " + email);
// 이후에 ApplicationEventPublisher를 이용해서 이벤트를 발행함
publisher.publishEvent(new UserRegisteredEvent(this, email));
}
}
ApplicationEventPublisher를 이용해 publishEvent() 메서드가 호출되면,
Spring 내부에 있는 ApplicationEventMulticaster가 이를 감지하고 등록된 Listener에게 이벤트를 전달한다고 함
4. ApplicationListener의 역할
ApplicationEventMulticaster를 통해 이벤트를 감지하고 후속 작업을 수행하는 컴포넌트라고 한다.
@Component // Component를 통해 등록
public class WelcomeEmailListener implements ApplicationListener<UserRegisteredEvent> {
// ApplicationListener를 포함하며, 이전에 만들어둔 Event타입을 가진다
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println("환영 이메일 발송 대상 : " + event.getUserEmail());
// 이후 이메일 발송 로직 작성
}
}
위 코드에서는 UserService에 대한 의존성이 전혀 포함되어있지 않기 때문에 서비스 로직에 대해 알 필요가 없다.
이는 Spring Event 시스템을 통해 관심사의 분리(Separation of Concerns)가 이루어졌다는 것을 의미함
팁
| 상황 | 적용 예시 |
| 서비스간 후속 작업을 느슨하게 연결하고 싶을때 | 회원가입 - > 알림 발송 / 포인트 적립(선택) |
| 트랜잭션 내 부수 작업을 분리하고 싶을 때 | 결제 완료 후 재고 차감, 영수증 발행 |
| 이벤트 흐름을 중앙집중형 구조에서 벗어나게 하고 싶을 때 | 모놀리??식 구조의 서비스 로직 분리 |
* 이벤트 리스너의 실행 순서를 보장하려면 @Order 애너테이션을 사용하면 된다고 함
이벤트 기반 아키텍처의 장점
단순한 코드 분리 이상의 장점을 제공한다고 한다.
1. 결합도 감소와 유지보수성 향상
Spring Event를 알기 전, 직접 호출 구조
UserService를 EmailService와 PointService 등등에 주입함
따라서 UserService가 모든 서비스의 존재를 알아야하며, 코드가 점점 복잡해진다!!
아래는 이벤트 기반 구조
UserService에 대해 주입받는 파라미터들을 UserRegisteredEvent를 통해 받고, 이걸 EventPublisher를 통해 이벤트를 발행하고, Listener에게 이벤트를 감지하게끔 한다.
따라서 UserService는 Listener들에 대한 의존성이 전혀 없게 된다. 경유해서 주니까!
Listener의 추가나 수정은 독립적으로 가능하며, 시스템의 확장성이 크게 향상된다고 볼 수 있다.
2. 확장성과 유연성
새로운 기능을 추가해야하는 경우, 기존 로직을 수정하지 않고 새로운 리스터만 등록하면 된다고 한다.
가령 회원가입 시 포인트 지급 기능을 추가하고 싶다면,
@Component
public class PointRewardListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println(event.getUserEmail() + "에게 포인트 지급 완료!");
}
}
위와 같은 형태로 새로운 PointRewardListener를 추가하고, UserService는 그대로 두면 된다.
이렇게 확장에 열려 있고 수정에는 닫힌(Open-Closed Principle) 구조가 실현된다고 한다.
3. 비동기 확장 기반
이벤트 시스템은 이후 @Async 애너테이션과 결합하여 비동기 처리를 구현할 수 있다고 함
이벤트가 발행되면 리스너가 별도의 스레드에서 동작하여 서비스의 응답 속도를 높이고, 부하를 분산시킬 수 있다고 한다.
UserService에 대한 registeruser를 Event형태로 만들고, EventPublisher를 통해 이벤트를 발행하는데?
@Async 애너테이션을 Listener에 달아주면 다른 스레드에서 Listener가 실행되어서 속도가 향상된다고 한다.
정리
| 구분 | 역할 | 비고 |
| ApplicationEvent | 이벤트 데이터 모델 | 일반 POJO로 대체 가능 |
| ApplicationEventPublisher | 이벤트 발행 | publishEvent() 메서드로 호출함 |
| ApplicationListener | 이벤트 수신 및 처리 | onApplicationEvent() 구현 |
| 장점 | 결합도 감소, 유지보수 향상, 비동기 확장 용이 | Open-Closed Principle 적용 |
업로드 할때 그 시점에 이관한다, 알바쓴다.. 비동기 처리
분산처리가 가능한지에 대해..
'Spring Boot > 비동기 처리' 카테고리의 다른 글
| Spring Event : 분산 환경으로의 확장 가능성 (0) | 2025.10.29 |
|---|---|
| Spring Event : 이벤트 기반 비동기 처리 활용사례 (0) | 2025.10.29 |
| Spring Event : 비동기 이벤트 처리 구현 (0) | 2025.10.25 |
| Spring Event : @EventListener 활용 (0) | 2025.10.25 |
| Spring Event : 기본 이벤트 처리 방식 (0) | 2025.10.24 |