메시지 시스템 연동에 실패하는 가능성도 있기 때문에, 메시지 시스템에서 메시지 데이터가 유실되지 않도록 보장하는 방법은 바로 메시지 데이터를 DB에 저장하는 것. 저장 후 이 메시지를 읽어 메시징 시스템에 전송하면 된다.

이처럼, 메시지 데이터를 DB에 보관하는 방식이 트랜잭션 아웃박스 패턴의 핵심

트랜잭션 아웃박스 패턴은 하나의 DB 트랜잭션 내에서 다음의 2가지 작업 수행

  • 실제 업무 로직에 필요한 DB 변경 작업 수행
  • 메시지 데이터를 아웃박스 테이블에 추가 아웃박스 테이블에 쌓인 메시지들을 별도의 메시지 중계 프로세스가 주기적으로 읽어서 메시징 시스템에 전송
sequenceDiagram
    participant A as 시스템 A
    participant DB as 데이터베이스
    participant R as 메시지 중계 시스템<br/>(Message Relay)
    participant M as 메시징 시스템<br/>(Message Broker)
    
    Note over A,M: 트랜잭션 아웃박스 패턴

    rect rgb(230, 240, 250)
        Note left of A: 1. 비즈니스 트랜잭션
        A->>A: 비즈니스 로직 수행
        A->>DB: BEGIN TRANSACTION
        A->>DB: 비즈니스 데이터 저장
        A->>DB: Outbox 테이블에 이벤트 저장<br/>(status: PENDING)
        A->>DB: COMMIT TRANSACTION
        A-->>A: 트랜잭션 성공
    end

    rect rgb(250, 230, 240)
        Note left of R: 2. 메시지 발행 (비동기)
        loop 주기적으로 실행
            R->>DB: Outbox 테이블 조회<br/>(status = PENDING)
            DB-->>R: 미발송 이벤트 목록 반환
            
            loop 각 이벤트에 대해
                R->>M: 메시지 발행
                M-->>R: 발행 성공 응답
                R->>DB: Outbox 이벤트 상태 업데이트<br/>(status: SENT)
                
                alt 발행 실패 시
                    M--xR: 발행 실패
                    R->>DB: 재시도 횟수 증가
                    Note over R: 다음 주기에 재시도
                end
            end
        end
    end

    rect rgb(240, 250, 230)
        Note left of DB: 3. 정리 작업 (선택적)
        loop 주기적으로 실행
            R->>DB: 오래된 SENT 이벤트 조회
            DB-->>R: 정리 대상 이벤트 목록
            R->>DB: DELETE 또는 아카이브 처리
        end
    end

    Note over A,M: 장점: 트랜잭션 일관성 보장, At-least-once delivery 보장<br/>단점: 추가적인 중계 시스템 필요, 지연 발생 가능

트랜잭션을 롤백하면 메시지 데이터도 함께 롤백되므로 잘못된 데이터가 전송될 일이 없음.

발송 완료를 표시하는 방법 2가지

  • 아웃박스 테이블에 발송 상태 칼럼을 두는 것
    • 이 칼럼에 3가지 상태(발송 대기, 발송 완료, 발송 실패)를 둠.
    • 발송 대기 상태를 갖는 데이터를 조회하고 발송에 성공하면 발송 완료로 업데이트하는 방식.
  • 메시지 중계 서비스가 성공적으로 전송한 마지막 메시지 ID를 별도로 기록하는 방식
    • 파일이나 별도의 테이블에 메시지 ID를 저장해두고, 다음번 대기 메시지 조회시 이 ID이후의 메시지만 선택하는 것.

아웃박스 테이블 구조의 예

칼럼타입설명
IDbig intPK. auto inc
messageIdvarchar메시지 ID
messageTypevarchar메시지 타입(LoginFailed, OrderPlaced 등)
payloadclob메시지의 데이터(JSON 등)
statusvarcher이벤트 처리 상태(WAITING, DONE, FAILED)
failCountint실패 횟수
occuredAttimestamp메시지 발생 시간
processedAttimestamp메시지 처리 시간
failedAttimestamp마지막 실패 시간