Spring, @TransactionalEventListener

최근 개발중에 상품정보를 수정시 원격 서비스로 수정된 정보를 전달해줘야 하는 요건이 생겼다.

딱히 완벽한 싱크를 필요로 하진 않기때문에 원격서비스에는 데이터를 받을수 있는 API를 열었고

나는 수정시 해당하는 원격서비스API를 호출하면 되는것이었다.

개발 중 호출시점에 대한 의문이 생겼다.
과연 로직중 어느시점에 API를 호출해서 데이터를 보내야 하는것일까?

해당 로직을 작성한 Service의 메소드위의 @Transactional 어노테이션을 보면서. 
아… 트랜젝션 종료시점에 보내면 되겠구나 라는 생각이 들었다.

구글링으로 Trasaction listener를 검색해보았더니 . 역시나..
@TransactionaEventListener라는게 튀어나왔다.
네이밍만 봐서도 트랜젝션 이벤트를 읽… ㅎ.. 네이밍만 봐서도 알수있다.
이런게 있는줄 처음알았다..
(토비님의 책을 잘 보지 않아서 일수도 있지만.)

@TransactionalEventListener에는 여러 phase를 설정할수 있는데.
설정할수 있는 TransactionPhase는 아래와 같다.
BEFORE_COMMIT
AFTER_COMPLETION
AFTER_COMMIT
AFTER_ROLLBACK

내가 필요한 TransactionEventLister의 Phase는 AFTER_COMMIT이다 
우선 @Component로 공통적으로 사용할 여러 케이스의 리스너 메소드를 작성한다.

리스너 간에는 인자타입으로 구분이 되기 때문에 나는
Callback 메소드를 가진 Event 추상클래스를 작성하고 
상속하여 EventAfterCommit, EventAfterRollback..등을 만들어 두었다.

Event추상 클래스를 만든 이유는 callback 메소드를 익명클래스로 비지니스 로직에서 작성하여 사용하게끔 강제하기 위해서다.

상속받아 추상클래스로 만든 이유는 리스너간 타입구분을 위해서다.

서비스 레이어에서 아래와 같이 사용하면 된다.

나는 익명클래스를 사용하여 로직을 커스텀하게 작성하기 위해 위와 같은 구조로 추상클래스를 작성했다.

DB에서 AWS S3업로드할 파일의 경로를 맵핑할 경우에도 사용할수 있겠다.
의식의 흐름대로 S3업로드 로직을 작성하고, BeforeCommit으로 이벤트를 publish하면 비지니스 로직상 처리가 다 된 이후에 S3업로드까지 하고 커밋되겠다.

afterCommit같은 경우 업무적으로 트랜젝션과 완전히 분리되는 작업을 해야하겠고. 비동기 처리를 해도 무방할것 같다.
이벤트처리중 예외발생에 대한 처리를 어떻게 해야할지 고민해봐야겠다.

Like what you read? Give Circlee7 a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.