공부하는 블로그

Spring | Application Event 본문

Spring

Spring | Application Event

치킨닮은닭 2023. 9. 10. 22:54

Event Driven Programing

 특정 동작에 대해 이벤트를 발생시키고 해당 이벤트를 구독하고 있는 여러 서비스에 이벤트를 전달시켜 동작하게하는 프로그래밍 방식이다. MSA 환경에서 이벤트 기반의 서비스 운영을 위해서 Kafka, RabbitMQ와 같은 다양한 메세지큐 시스템이 이미 개발되어 있다.

Spring Application Event?

 스프링에서 ApplicationEventPublisher을 이용하여 이벤트 기반의 프로그래밍을 할 수 있다. ApplicationEventPublisher를 통해 이벤트를 발행하면, 다른 Bean에서도 @EventListener를 이용하여 이벤트 데이터를 가져올 수 있다.

 

 Kafka가 외부 다른 어플리케이션끼리 메세지를 주고받을 수 있다면, 스프링 내부에서는 Application Event를 이용하면 Bean끼리 메세지를 주고 받을 수 있으니 한 서비스에서의 로직 수행 후에 파생되어 동작해야하는 다른 서비스 로직을 쉽게 수행시킬 수 있다. Spring Application Event를 알기 전에 Kafka를 먼저 접해봐서 스프링 어플리케이션 내에 있는 자그마한 Kafka로 이해했다.

 

 쉽게 비동기를 적용시킬 수 있으며 서비스간의 의존성을 Decoupling이 가능하고 이벤트에 파생되는 작업의 추가가 간편하여 확장성이 좋다. 단, 이벤트를 발생시키고 그 이후의 파생되는 결과를 파악하기 위해서는 구독하고 있는 서비스로 직접 찾아가야 하므로 로직의 흐름 파악이 어렵고 트랙잭션 관리가 어렵다는 단점이 있다.

Publish

 커스텀 이벤트 객체를 생성하고 발행해보도록 하자. ApplicationEventPublisher.publishEvent(obj)를 이용하면 간편하게 개발자가 정의한 커스텀 이벤트를 발행할 수 있다.

 

 먼저 CustomEvent 클래스를 정의하자.

@Getter
@ToString
public class CustomEvent {
  private final String message;

  public CustomEvent(String message) {
    this.message = message;
  }
}

 정의한 이벤트 클래스를 발행하는 서비스를 정의한다. ApplicationEventPublisher는 스프링에서 기본으로 제공하는 Bean이니 별다른 설정 없이 바로 의존성을 주입하여 사용하면 된다.

@Component
@RequiredArgsConstructor
public class CustomEventPublisher {

  private final ApplicationEventPublisher publisher;

  public void publish(@NonNull CustomEvent event) {
    publisher.publishEvent(event);
  }
}

 기본 서비스에서 정의한 CustomEventPublisher를 이용하여 이벤트를 발행한다.

@Service
@RequiredArgsConstructor
public class MyService {

  private final CustomEventPublisher publisher;

  public void someMethod(String param) {
    // 기본 서비스 로직
    // 블라블라 쏼라쏼라

    // 이벤트 발행
    publisher.publish(new CustomEvent(param));
  }

}

Consume

 발행된 커스텀 이벤트는 @EventListener 어노테이션이 적용된 구독 메서드에서 받아와 사용이 가능하다. 간단하게 classes 속성에 구독할 이벤트를 정의해주면 된다.

@Component
@Slf4j
public class CustomEventListener {

  @EventListener(
      classes = {
          CustomEvent.class
      }
  )
  public void onListen(CustomEvent event) {
    log.info("##### listening custom event. event = {}", event);

    // 이벤트 정보를 이용한 필요한 로직 작성
  }

}

 제대로 동작하는지 확인해보기 위해 테스트 클래스를 생성하여 간단하게 MyService를 실행해보자. 별다른 로직이 없으니 콘솔이 제대로 찍히는지만 확인해보면 된다.

@SpringBootTest
@ActiveProfiles("test")
public class SpringApplicationIntegrationTest {

  @Autowired
  private MyService service;

  @Test
  @DisplayName("이벤트 발행 테스트")
  void customEventPublishTest() {
    final String param = "some information.";

    service.someMethod(param);
  }

}

 

테스트 수행 결과

 

 

Reference

'Spring' 카테고리의 다른 글

Spring | MockServer  (0) 2023.09.24
Spring | @TransactionalEventListener  (0) 2023.09.17
Spring | BDD - Given / When / Then  (0) 2023.09.03
Spring | Mockito Unit Test  (0) 2023.08.27
Spring | Annotations  (0) 2020.09.29
Comments