Spring Application Event를 사용해보긴 했지만, 용어와 코드가 어떻게 매칭되는지는 늘 헷갈렸다.
이번 글에서는 이벤트 관련 용어와 Spring을 이용해 내부 이벤트를 사용할 때 참고할 수 있는 예시 코드를 소개하려 한다.
1. 이벤트 용어
멘토링 시간에 들었던 예시는 이벤트 관련 용어를 이해하는 데 가장 도움이 되었다.
마라탕집 3000평 가게에 식사하러 갔다.
테이블A에서 "계산해" 달라고 한다
→ 지나가던 알바가 무전기로 "A테이블 계산이요"라고 전달한다.
→ 계산 서버가 달려와서 "계산해드리겠습니다"
- 이벤트 프로듀서 (Publisher) = 테이블A
- 이벤트 = "계산 해줘" → 커맨드가 아니니깐, “계산해줘” 보다는 "여기 식사 다 했어요!" 일 듯.
- 이벤트 브로커 = 알바 + 무전기
- 이벤트 컨슈머 (Listener) = 계산 서버 : 이벤트를 구독하고 있다가 해당 이벤트 발생 시 미리 정의된 로직 실행
- 이벤트 핸들러 = 실제 실행되는 구체적 처리 로직 → "계산 서버"가 계산 처리
2. 코드로 보는 이벤트
소개하는 코드는 Spring에서 이벤트를 언제, 어떻게 발행하고 수신 측에서 어떻게 받아 처리하는지 쉽게 이해할 수 있는 좋은 튜토리얼이 될 것이다.
*// === 이벤트 클래스 ===*
public class OrderCompletedEvent {
private String orderId;
private String userId;
private List<String> items;
private int amount;
private LocalDateTime timestamp;
*// 생성자, getter/setter...*
}
*// === 주문 서비스 (이벤트 발행자) ===*
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(String userId, List<String> items, int amount) {
*// 주문 생성 로직*
String orderId = UUID.randomUUID().toString();
*// 주문 저장...*
saveOrder(orderId, userId, items, amount);
*// 이벤트 발행 (기존 코드는 수정 불필요!)*
OrderCompletedEvent event = new OrderCompletedEvent(orderId, userId, items, amount);
eventPublisher.publishEvent(event);
System.out.println("📝 주문 생성 완료: " + orderId);
}
}
*// === 기존 서비스들 ===// 결제 서비스*
@Service
public class PaymentService {
@EventListener
public void handleOrderCompleted(OrderCompletedEvent event) {
System.out.println("💳 결제 처리 시작: " + event.getOrderId());
processPayment(event.getAmount());
sendPaymentConfirmation(event.getUserId());
}
}
*// 재고 서비스*
@Service
public class InventoryService {
@EventListener
public void handleOrderCompleted(OrderCompletedEvent event) {
System.out.println("📦 재고 차감 처리: " + event.getOrderId());
updateStock(event.getItems());
checkLowStock();
}
}
*// === 새로운 요구사항 1: 포인트 적립 기능 추가 ===*
@Service *// 새로운 서비스 추가!*
public class PointService {
@EventListener *// 기존 코드 수정 없이 리스너만 추가!*
public void handleOrderCompleted(OrderCompletedEvent event) {
System.out.println("⭐ 포인트 적립 처리: " + event.getOrderId());
int points = (int)(event.getAmount() * 0.01); *// 1% 적립*
addPoints(event.getUserId(), points);
sendPointNotification(event.getUserId());
}
}
*// === 새로운 요구사항 2: 이메일 알림 추가 ===*
@Service *// 또 다른 새로운 서비스!*
public class NotificationService {
@EventListener *// 또다시 기존 코드 수정 없이!*
public void handleOrderCompleted(OrderCompletedEvent event) {
System.out.println("📧 이메일 알림 발송: " + event.getOrderId());
sendOrderConfirmationEmail(event.getUserId(), event);
sendSMSNotification(event.getUserId());
}
}
*// === 새로운 요구사항 3: 배송 준비 추가 ===*
@Service *// 계속해서 새로운 서비스 추가 가능!*
public class ShippingService {
@EventListener
public void handleOrderCompleted(OrderCompletedEvent event) {
System.out.println("🚚 배송 준비 시작: " + event.getOrderId());
createShippingLabel(event);
scheduleDelivery(event.getOrderId());
}
}
*// === 컨트롤러 (실행부) ===*
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/orders")
public ResponseEntity<String> createOrder(@RequestBody OrderRequest request) {
orderService.createOrder(
request.getUserId(),
request.getItems(),
request.getAmount()
);
return ResponseEntity.ok("주문이 접수되었습니다.");
}
}
실행 시 로그:
📝 주문 생성 완료: abc-123-def
💳 결제 처리 시작: abc-123-def
📦 재고 차감 처리: abc-123-def
⭐ 포인트 적립 처리: abc-123-def
📧 이메일 알림 발송: abc-123-def
🚚 배송 준비 시작: abc-123-def
3. 이벤트 사용 장점
- 기존 코드 수정 없음: OrderService, PaymentService, InventoryService는 전혀 건드리지 않음
- 새 서비스 추가: 새로운 비즈니스 로직이 필요하다면 서비스 클래스를 하나 추가하고, 메서드에 @EventListener만 붙이면 된다.
어떤 이벤트를 리슨할지는 발행된 이벤트 객체와 수신 측에서 정의한 이벤트 객체가 동일한 타입으로 매칭되어 결정된다. - Spring이 자동 처리: Spring이 OrderCompletedEvent가 발행되면 모든 @EventListener를 자동으로 호출
- 독립적 실행: 각 리스너는 독립적으로 실행되며, 하나가 실패해도 다른 리스너에 영향 없음
- 확장 용이: 쿠폰 서비스, 리뷰 요청 서비스 등 무한히 추가 가능
이렇게 Spring Application Event를 사용하면 기존 코드 변경 없이 새로운 기능을 계속 추가할 수 있습니다!
'Essay > WIL' 카테고리의 다른 글
[WIL] 루퍼스_부트캠프 9주차 (0) | 2025.09.14 |
---|---|
[WIL] 부트캠프 8주차 (0) | 2025.09.07 |
[WIL] 부트캠프 6주차 (0) | 2025.08.24 |
[WIL] 부트캠프 5주차 (1) | 2025.08.18 |
[WIL] 부트캠프 4주차 (4) | 2025.08.10 |