https://velog.io/@eastperson/Transaction-Outbox-Pattern-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0 읽고 정리한 글
특정 DB 상태를 변경하는 트랜잭션과 함께 이벤트를 발행해야 할 때 사용할 수 있는 패턴. 이벤트를 따로 테이블을 만들어서 기록하는 방식을 사용하는듯함
트랜잭션 아웃박스 패턴 -> DB의 해당 이벤트 메시지를 기록함. 그런 다음 별도 프로세스가 저장된 이벤트를 읽어서 메시지 브로커에 전송함.
outbox란 보낼편지함 이란 뜻이 있다.
위 패턴의 구성요소는 메시지를 보내는 sender, 엔티티 및 메시지 outbox 를 저장하는 db, 메시지를 저장하는 테이블 or record(nosql의 경우)message outbox, outbox 에 저장된 메시지를 메시지 브로커로 보내는 서비스인 Message Relay.
outbox 테이블은 임시 메시지 큐 역할을 하며, 엔티티 업데이트와 함께 트랜잭션으로 묶임 Message Relay는 Outbox 테이블에 저장한 데이터를 비동기적으로 읽어서 메시지를 발행하여 메시지 브로커에게 전달하는 역할을 함.
message relay를 구현하는데는 Polling Publisher, Transaction log tailing의 두 가지 방식이 있다.
RDBMS를 사용하는 앱에서 outbox 테이블에 삽입된 메시지를 발행하는 간단한 방법으로, 테이블을 폴링해서 미발행된 메시지를 조회하는 방식. 규모가 작은 경우에 사용해도 문제는 없다.
앱에서 커밋된 업데이트는 각 DB의 트랜잭션 로그가 남습니다, 이 로그를 읽어서 메시지 브로커에 발행하는 방식입니다.
트랜잭션 로그 마이너는 로그 항목을 읽고, 각 항목을 메시지로 전환하여 메시지 브로커에 발행합니다.
로그의 변경된 데이터를 감지하는 작업을 CDC 라고 한다네요. Change Data Capture. Kafka Connect에서 위 작업을 서포트하는 기능이 있는듯함니다, 아직 카프카는 잘 몰라서,,, 요런게 있다~
트랜잭션에 관해 모르는 것들이 많아서 찾아보았는데, 아웃박스 패턴을 처음 알게되었슴니다. 생각해보면, "어떤 작업을 완료하고, 이 작업이 완료되었다는 이메일을 전송해야한다" 같은 비즈니스 로직이 있다면 위 패턴을 몰라도 어느정도 비슷한 방식으로 구현을 시도했을거 같습니다. 대신 DB 업데이트와 메시지 전송의 원자성을 보장하기 위해서, 이벤트를 테이블에 저장하는 방식은 바로 생각은 못 했을 거 같고, 메시지 큐만 사용해서 해결했을 거 같습니다,, 이런 패턴이 있다는걸 알게되었으니 비슷한 비즈니스 로직을 구현해야할 때 참고하면 좋을듯합니다
이제 이메일 전송 등의 이벤트를 별도로 처리하는 방식을 선택했다면, 데이터의 일관성을 맞추는 부분을 고려하고.. 외부 api 요청등의 완료 여부를 봐야한다면 또 그렇게 구현해야하고,, 메시지를 중복해서 보내는지는 않는지,,, 등의 복잡성이 추가되기는 하겠지만, 복잡성이 추가되고 트랜잭션이 가벼워지는 트레이드 오프는 안 할 이유는 크지 않다고 생각하기때문에 이렇게 처리하는게 좋아보임니다