Spring - Event

buckshot·2024년 2월 26일

Spring

목록 보기
1/8
post-thumbnail

최근 알림기능을 구현하면서 Spring Event를 사용을 했다.
해당 기능을 이용하면서 솔직히 구동 원리에 대해서는 깊게 알지는 못했다.
그래서 지금 다시 공부를 하면서 정리를 한다...


Spring Event

Spring은 내부 Event 매커니즘을 내포하고 있다.

EventBeanBean사이 데이터를 전달하는 방법 중 하나!

일반적으로 클래스에서 특정 생성자, 필드 주입을 통해 주입된 의존성은 클래스 내에서 사용되어 작업을 수행하거나 기능을 확장하는 데 사용이 된다.

	private final A a;

하지만 Event는 이와 다른 매커니즘이다.

Event는 특정 Event를 발행시키는 Publisher와 해당 이벤트를 구독하는 Listener이 있다. 그리고 Event에서 데이터를 담는 Event모델이 있다.

위 처럼 일반적인 형태는 서비스 상호간 강한 의존성이 강하게 되어있다. 하지만 Event를 이용하여 위 방법에 비해 의존성이 떨어진다.

  • 서비스 상호간의 의존성이 낮으면 생기는 장점

    • 유연성과 재사용성 향상 :
      의존성이 낮을수록 서비스는 더 견고하고 재사용성이 증가한다. 각 서비스는 자체적으로 독립적드로 기능을 하며, 다른 서비스에 영향을 덜 받아 유연하게 변경이 될 수 있다. 이렇게 될 경우 이후에 변경 사항이 적용되어도 쉽게 대처가 가능해진다.

    • 결합도 감소 :
      서비스 간의 강력한 의존성은 시스템 전체의 결합도를 높일 수 있다. 하지만 의존성이 낮으면 각 서비스는 독립적으로 변경될 수 있으며, 한 서비스의에 미치는 영향을 최소화할 수 있다.


Event

기능 구현을 하면서 직접 작성했던 Event모델 코드다.

@Getter
public class ChangeOfPostEvent extends ApplicationEvent {
    private final JobPost jobPost;
    private final Application application;
    private final CauseTypeCode causeTypeCode;
    private final ResultTypeCode resultTypeCode;

    public ChangeOfPostEvent(Object object, JobPost jobPost, Application application,CauseTypeCode causeTypeCode, ResultTypeCode resultTypeCode) {
        super(object);
        this.jobPost = jobPost;
        this.application = application;
        this.causeTypeCode = causeTypeCode;
        this.resultTypeCode = resultTypeCode;
    }
}

일단 Event모델은 이벤트를 나타내는 추상클래스인ApplicationEvet를 상속을 함으로 이벤트 처리 메커니즘을 활용할 수 있다.

또한, ApplicationEvent의 생성자를 호출하는 super()을 이용하여 부모 클래스의 생성자는 이벤트를 발행시키는데 필요한 정보를 초기화 한다.

여기서의 object는 일반적으로 publisher를 가지고 있는 객체를 사용한다.


Event Publisher

아래 코드 또한 작성한 코드의 부분을 갖고 왔다.

private final ApplicationEventPublisher publisher;

    @Transactional
    public void modifyPost(...) {
        ...
       while (iterator.hasNext()) {
           Application application = iterator.next();
           if (form.getMinAge() > LocalDateTime.now().plusYears(1).getYear() - application.getMember().getBirth().getYear()){
               applicationsToRemove.add(application);
               publisher.publishEvent(new ChangeOfPostEvent(this,jobPost,application, POST_MODIFICATION,DELETE));
           }else {
               publisher.publishEvent(new ChangeOfPostEvent(this,jobPost,application,POST_MODIFICATION,NOTICE));
           }
       }
    }

Publisher은 Event를 생성한다.
Event를 생성하기 위한 BeanApplicationEventPublisher이다.

따라 이벤트를 사용하기 위해 주입을 받고 publishEvent메소드를 사용하면 해당 이벤트는 발행이 된다.

그리고 Eventobject 파라미터로는 보인 객체인 this를 주며 인스턴스를 만든 후 publishEvent의 파라미터로 넘기면 된다.


Event Listener

그리고 발행된 이벤트를 구독하는 Event Listener는 방금 전 알아본 Publisher에서 발행된 Event를 사용한다.

Listener을 만들기 위해서는 ApplicationListener<Event모델>을 상속 받아야 기능을 한다.

public class NotificationEventListener {

    @EventListener
    public void postCorrectionEventListen(ChangeOfPostEvent event) {
        if (event.getResultTypeCode() == NOTICE) {
 			notificationService.notifyApplicantsAboutPost(event);
        }else {
 			notificationService.deleteApplicationNotification(event);
        }
    }
}

@EventListener 어노테이션을 이용하여 발행되는 이벤트를 구독하여 로직을 수행을 한다.

(Spring Framework 4.2 이전)
4.2 이전에는 위 방법과 다르게 구성을 했어야 했다.

@Component
public class EventListener implements ApplicationListener<Event모델> {

 	@Override
    public void onApplicationEvent(Event모델 event) {
        ...
    }
}

현재는 @EventListener 을 이용하기 때문에 ApplicationListener<CustomEvent> 인터페이스를 구현할 필요가 없어졌다.

<참고 자료>
https://wildeveloperetrain.tistory.com/217
https://sabarada.tistory.com/184

profile
let's go insane

0개의 댓글