Inbox / Outbox 패턴 정리
Inbox와 Outbox는 MSA나 이벤트 기반 구조에서 메시지를 안전하게 주고받기 위해 사용하는 패턴이다.
서비스 간 통신에서 이벤트를 사용할 때는 다음과 같은 문제가 발생할 수 있다.
- DB 저장은 성공했는데 이벤트 발행은 실패하는 경우
- 같은 이벤트가 여러 번 전달되는 경우
- 이벤트 처리 중 장애가 발생하는 경우
이런 문제를 줄이기 위해 사용하는 것이 Outbox 패턴과 Inbox 패턴이다.
Outbox란?
Outbox는 내 서비스에서 발행해야 할 이벤트를 저장하는 공간이다.
예를 들어 주문이 생성 되면 주문 서비스는 다른 서비스에게 주문이 생성됐다는 이벤트를 보내야 한다.
일반적인 흐름은 다음과 같다.
주문 생성
→ 주문 DB 저장
→ 주문 생성 이벤트 발행
하지만 이 방식은 문제가 생길 수 있다.
주문 DB 저장 성공
→ 이벤트 발행 실패
이 경우 주문은 생성됐지만, 다른 서비스는 주문이 생성됐다는 사실을 알 수 없다.
그래서 Outbox 패턴에서는 이벤트를 바로 발행하지 않고, 먼저 DB에 저장한다.
주문 DB 저장
→ outbox 테이블에 이벤트 저장
→ 별도 프로세스가 outbox 이벤트를 읽어서 메시지 브로커로 발행
핵심은 비즈니스 데이터 저장과 이벤트 저장을 같은 트랜잭션으로 처리한다는 것이다.
order 저장, outbox 저장 둘 중 하나라도 실패하면 전체 트랜잭션이 실패하기 때문에, 데이터는 저장됐는데 이벤트 기록은 없는 상황을 줄일 수 있다.
Outbox 테이블 예시
outbox
- id : 이벤트 식별자
- event_type : 이벤트 종류
- payload : 실제 이벤트 데이터
- status : 발생 상태
- created_at : 생성 시간
- published_at : 발행 완료 시간
Outbox에 저장된 이벤트는 이후 별도 스케줄러나 이벤트 발행기가 읽어서 Kafka, RabbitMQ 같은 메시지 브로커로 전송한다.
Inbox란?
Inbox는 다른 서비스에서 받은 이벤트를 저장하는 공간이다.
메시지 브로커를 사용하면 같은 이벤트가 여러 번 전달될 수 있다.
예를 들어 이벤트 처리는 성공했지만, 메시지 ACK 처리 전에 장애가 나면 브로커는 해당 메시지가 처리되지 않았다고 판단하고 다시 보낼 수 있다.
이때 같은 이벤트를 또 처리하면 문제가 생긴다.
예를 들어 계좌 생성 이벤트가 두 번 처리되면 같은 사용자의 계좌가 중복 생성될 수 있다.
그래서 Inbox 패턴을 사용한다.
이벤트 수신
→ inbox 테이블에 event_id가 있는지 확인
→ 없으면 저장 후 처리
→ 있으면 이미 받은 이벤트이므로 무시
즉, Inbox는 받은 이벤트를 중복 처리하지 않기 위한 장치이다.
Inbox 테이블 예시
outbox
- id : 이벤트 식별자
- event_id : 원본 이벤트 식별자
- event_type : 이벤트 종류
- payload : 수신한 이벤트 데이터
- status : 처리 상태
- received_at : 수신 시간
- published_at : 처리 완료 시간
여기서 중요한 값은 event_id이다.
event_id를 기준으로 이미 처리한 이벤트인지 확인할 수 있다.
Outbox와 Inbox의 차이
| 구분 | Outbox | Inbox |
| 위치 | 이벤트를 보내는 서비스 | 이벤트를 받는 서비스 |
| 역할 | 발행할 이벤트 저장 | 수신한 이벤트 저장 |
| 목적 | 이벤트 유실 방지 | 이벤트 중복 처리 방지 |
| 핵심 값 | event_id, status | event_id |
| 예시 | 대회 참가 이벤트 저장 후 발행 | 대회 참가 이벤트 수신 후 계좌 생성 |
'Study' 카테고리의 다른 글
| Redis Sorted Set (0) | 2026.05.02 |
|---|---|
| WebSocket & 실시간 통신 (0) | 2026.05.01 |
| 데이터 정합성 (0) | 2026.04.27 |
| 멱등성 (0) | 2026.04.26 |
| 라우터 / 스위치 / 허브 차이 (0) | 2026.04.25 |