스프링 공부/어노테이션 정리

@EventListner

장아장 2024. 2. 2. 20:21

내 친구들에게 이벤트란, 템창에 이런게 가득한 일상이겠지...

이 어노테이션을 알기 전에, Event가 무엇인지 알아야 한다.

우리가 게임에서 이야기하는 이벤트란, 일정 기간동안 진행하는 행사를 말한다.

개발에서 이벤트를 말할 때, 우리가 생각해야 하는 것은 이 행사라는 단어다.

How Event?

이벤트란 무엇인가라고 한다면, 행사라고 바로 앞에 적혀있다.

이를 조금 더 자세하게 말하자면 애플리케이션 상에서 나타나는 사건이다.

프론트엔드 개발자라면 더욱 이해하기 쉽다.
onClickEvent, hober와 같은 부분들이 모두 JS의 이벤트를 기반으로 동작하는 함수들이다.
이런 함수들을 잘 읽어보면, 사용자가 일으키는 일련의 사건을 통해 해당 로직들을 동작시킨다는 것이다.

하지만, 나는 백엔드를 공부하고 있다. 이 이벤트를 통해 요청을 받는다면, 이에 대한 응답을 주는 것이 일반적인 방식이다.
그렇다면, 어떻게 이벤트라는 것을 사용할 수 있을까?

이벤트를 발생시키기 위해서는 두 가지가 필요하다.
이벤트, Publisher/Subscriber

이벤트라는 것은 위에서 봤다.
이를 백엔드에서 쓰기 위해서 내가 만들었던 예시를 가져와보았다.

좌석이 팔릴 때, 공연이 더 예약을 받을 수 있는지 확인하고 처리하는 플로우

좌석이 환불될 때, 공연이 예약을 더 받을 수 있게 해주는 플로우

총 두가지가 존재한다.

이 두가지를 좌석과 공연 객체가 서로 연관을 가지지 않고, 독립적이게 동작시킬 것이다.

그렇다면, 좌석객체가 예약/환불될 때 공연 더 예약 받을까?라던가 공연 더 예약 가능해!라는 말을 해주어야 한다.

이렇게 우리는 이벤트를 발생시키는 것이다.

여기에서 좌석과 관련된 일은 좌석이 해내고, 공연이 해내야 할 일들은 공연이 해내게 되는 것이다.

그렇다면 Publisher, Subscriber는 무엇일까?

간단하게 말하면 이벤트를 발행하는 사람, 이벤트를 구독하고 있다가 받으면 일을 하는 사람이다.

좌석이 공연에게 해야할 말을 하면, 공연은 자기 일을 한다.

즉, 좌석(Publisher)공연 더 예약 받을까?라던가 공연 더 예약 가능해!라는 말(특정 이벤트)을 하면 공연(Subscriber)은 그림대로 자기 할 일을 하는 것이다.

Why Event?

그렇다면 이걸 왜 써야할까? 그리고 꼭 써야할까?

안쓰면 안될것은 아니다.

이벤트를 기반으로 각자 자기 할 일을 알아서 시킬수 있지만,

비즈니스로직에서 다른 객체의 리포지토리나 서비스를 불러와 사용할 수도 있다.

그렇다면 나는 이걸 왜 공부하고, 적용해봤을까?

이유는 그 이름도 유명한 DDD(도메인 주도 설계)때문이다

도메인 주도 설계에서, 우리는 객체간의 협력보단, 더욱 독립적인 도메인을 만들기 위해 노력한다.

이를 통해 더욱 간결한 플로우와 정리된 코드를 만들 수 있다.

또한, 기능을 확인하고 개선하는 과정에서 불필요한 부분들을 찾아보는 수고를 줄일 수 있다.

도메인 주도 설계와 이벤트가 무슨 연관이 있을까?

내가 공부하는 도메인 주도 설계에서, 각 도메인 로직들이 독립적이어야 한다고 한다.

즉, 위의 기준에서는 좌석공연간의 서비스나 리포지토리 공유를 없애야 겠다는 생각이 들었다.

이를 위해 이벤트를 기반으로 구현하게 되었다.

이벤트를 발행하기 위해서는 스프링의 ApplicationEventPublisher를 사용했다.

이벤트를 받는 로직에서는 이렇게 어노테이션을 넣어주었다.

이 때, 우리는 어떻게 이벤트를 주고 받을까?

ApplicationEventPublisher를 통해서 우리는 이벤트를 발행한다. 이러한 이벤트를 기다리는 로직들을 @EventListner를 달아서 등록하고, 이러한 로직들이 이벤트를 위임받아 행동을 하는 것이다.

 

여기에서, 우리가 알아야 하는 것이 몇 가지 있다. 

  • @EventListner : 어노테이션은 하나의 객체 혹은 값을 가진다. 
    • 해당 파라미터를 함수의 입력변수로 받게 할 수 있다. 
    • 이를 통해 BoardService에서 BoardRepository, MemberRepository를 모두 연결해서 직접적인 연결을 하지 않게 할 수 있다. 
  • ApplicationEventPublisher 
    • 전역적으로 이벤트를 발생시킨다. 
    • 즉, A, B, C도메인이 있을 때 A도메인에서 a라는 이벤트를 발생시키고, B와C가@EventListner(a)를 가지고 있다면, a이벤트를 통해 b, c를 동작시킬 수 있다. 
  • 이벤트는 언어/프레임워크등에 따라 비동기적/동기적/블록/넌블록이 다 다르다. 

그러면 나는 이런 이벤트를 왜 공부하게 되었을까?

 

DDD때문이었다. 

도메인 주도 설계에서, 도메인간의 독립을 추구해야 한다고 한다. 

개인적으로 이를 통해 코드가 깔끔해지고, 리펙토링이 편해진다는 느낌을 받았다. 

특히, 디버깅을 통해서 몇가지 에러를 찾을 때, A에서 B로 갔다가 하는 경우가 없어서 좋았다. 

 

이 이야기를 왜 할까?

예시를 두고 생각해보면 간단하다. 

회원이 새로운 게시물을 생성하는 로직이 있을 때,

회원의 dto에서 memberId를 가져오고, 검증을 한 후 생성을 한다고 해보자. 

 

그렇다면 해당 로직은 MemberRepository.findById, BoardRepository.save로직을 둘 다 써야한다. 

이 때 MemberRepository를 통해 검증하는 부분, BoardRepository를 통해 검증하는 부분을 분리하는 방법을 만들 수 있다. 

 

자바스크립트에서 EventEmitter를 통한 구현방법도 배워봤는데, 

여기는 스프링 어노테이션 관련 부분이니,

다음에 Event에 대해서 더 자세하게 공부하고 정리하는 포스트를 써봐야겠다.

'스프링 공부 > 어노테이션 정리' 카테고리의 다른 글

@뭐시깽이Constructor  (0) 2023.01.02
@JsonInclude  (0) 2023.01.02
@Log(@Slf4j를 써보다가 궁금해서 찾아본 내용 정리)  (3) 2023.01.01
@Bean  (0) 2022.12.28
@Configuration  (0) 2022.12.28