생각나눔

카프카 이벤트를 메서드 호출로 발행하는 것에 대하여..

따뜻한 세상을 만드는 개발자 2024. 11. 3. 11:00

문제 현상

회사에서 작업을 하면서 Transaction이 없던 메서드에 기능을 추가하며

원자성을 보장하기 위해 Transactional을 어노테이션을 추가했다.

 

Transaction이 없던 곳에 적용할 때는 주의를 더 했어야 했는데..

내부 메서드 호출 중 메서드 호출로 카프카 이벤트를 발행하는 곳이 있었고

Transaction이 적용되면서 카프카 이벤트는 발행되었지만 아직 DB에 반영되지 않은 상태가 되었다.

 

이 경우 타이밍 이슈로 문제가 될 수 있는데 해당 카프카 이벤트를 받아

(이 행동이 적절한지를 떠나서) 처리하는 서비스가 곧바로 API 요청을 하거나 DB 조회를 한다면

(새로 만들었던 경우) 데이터가 없거나 (업데이트 하는 경우) 이전 데이터를 보게 된다.

 

TransactionalEventListener를 통해 쉽게 해결 가능

이 경우 가장 쉽게 해결 할 수 있는게 TransactionalEventListener를 사용하는 것이다.

TransactionalEventListener로 Transactional이 commit한 이후에 카프카 이벤트가 발행되도록 할 수 있다.

@TransactionalEventListener(classes = ItemChangedEvent.class, phase = TransactionPhase.AFTER_COMMIT)
public void listenItemChangedEvent(final RuleSetChangedEvent ruleSetChangedEvent) {
    // 카프카 이벤트 발행 처리
}

 

 

주의할 점은 이벤트 발행 시점에 Transaction이 적용되어 있지 않다면 TransactionalEventListner가 호출되지 않는다는 것인데

이 부분은 필요한 경우 팀내 Transaction 컨벤션(Service에 기본적으로 read only Transaction 적용)을 통해 보완해 사용해 볼 수 있다.

카프카 이벤트를 메서드 호출로 발행하는 것에 대하여..

Transaction이 필요 없다면 메서드 호출로 카프카 이벤트 발행해도 이슈 없지만

Transaction이 필요 없다가 Transaction이 추가되는 상황은 자주 있기 때문에

 

카프카 이벤트를 메서드 호출로 발행하는 것을 지양하고 처음부터 Transactional을 적용하고 DB 작업 완료 후 

TransactionalEventListner로 처리되게 하는게 나은 것 같다.