Spring

[Spring] 스프링에서 이벤트 발행과 구독 @EventListener

누구세연 2024. 10. 25. 23:17

Spring에서 ApplicationEvent 객체를 사용하여 특정 이벤트를 발생시키고 이를 구독하는 방식으로 서로 다른 컴포넌트 간 느슨한 결합을 제공할 수 있는 @EventListener에 대해 알아보겠습니다. 👩🏻‍💻

 

 

@EventListener

@EventListener

특정 이벤트가 발생했을 때 이를 구독하고 정의된 메서드를 호출하는 역할을 합니다.

예를 들어, 특정 조건이 발생했을 때 자동으로 알림을 보내거나 데이터를 갱신하는 작업을 비동기 방식으로 처리할 수 있습니다.

이를 통해 모듈 간 결합도를 낮추고 이벤트가 발생하는 시점에만 필요한 작업을 수행할 수 있어 효율적입니다.

 

 

사용 예시

예를 들어, 사용자가 가입할 때 가입 성공 후 환영 이메일을 전송하는 이벤트 핸들러를 작성할 수 있습니다.

 

이벤트 클래스

public class UserRegisteredEvent {
    private final String email;

    public UserRegisteredEvent(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }
}

 

이벤트 발행

UserService 클래스에서 ApplicationEventPublisher를 사용해 UserRegisteredEvent를 발행합니다.

@Service
public class UserService {
    private final ApplicationEventPublisher publisher;

    public UserService(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void registerUser(String email) {
        // 회원가입 로직 (예: 데이터베이스에 저장)
        publisher.publishEvent(new UserRegisteredEvent(email)); // 이벤트 발행
    }
}

 

이벤트 구독

UserRegisteredEvent가 발행되면 @EventListener를 사용해  UserRegisterEvent를 구독하고 특정 작업(이메일 전송)을 실행합니다.

@Component
public class UserEventListener {

    @EventListener
    public void handleUserRegistration(UserRegisteredEvent event) {
        System.out.println("Sending welcome email to " + event.getEmail());
    }
}

 

 

장점

  1. 모듈 간 결합도 감소: @EventListener는 이벤트 기반 구조를 통해 클래스 간의 결합도를 낮추어 유지보수와 확장성을 높여줍니다,
  2. 비동기 처리: 추가적인 설정을 통해 이벤트 핸들러를 비동기로 처리할 수 있어 성능을 최적화할 수 있습니다.
  3. 유연한 기능 확장: 새로운 이벤트 리스너를 추가함으로써 로직을 변경하지 않고도 다양한 후속 작업을 설정할 수 있습니다.

단점

  1. 디버깅 어려움: 이벤트 기반 시스템에서는 메서드 호출 흐름이 보이지 않기 때문에 디버깅이 다소 어려울 수 있습니다.
  2. 코드 복잡성 증가: 이벤트와 리스너가 많아질수록 코드의 흐름이 복잡해져 추적이나 유지보수가 어려워질 수 있습니다.
  3. 오버헤드: 이벤트 수 많아질 경우 성능 저하가 발생할 수 있으며 특히 동기 방식에서는 전체 프로세스가 느려질 수 있습니다.

 

🚨 주의사항

 

  • 비동기 처리 시 주의: 비동기 방식으로 설정할 때는 메서드에서 사용하는 객체들이 스레드 안전하게 관리되도록 신경 써야 합니다.
  • 트랜잭션 경계 설정: 트랜잭션이 완료되지 않았을 때 이벤트가 발생하면 문제가 생길 수 있으므로, 트랜잭션이 필요한 경우 @TransactionalEventListener를 사용하는 것이 좋습니다.
  • 예외 처리: 이벤트 리스너에서 예외가 발생할 경우 전체 애플리케이션에 영향을 미칠 수 있으므로, 적절한 예외 처리가 필요합니다.