본문 바로가기
System design

분산시스템에서 시스템간 데이터를 전송하는 법

by yeonn108 2026. 3. 7.

두개 이상의 컴포넌트로 구성된 분산시스템 환경에서 데이터를 전송하는 방법에 대해 알아보자. 

 

REST API나 gRPC로 컴포넌트 간 데이터를 전송할 수 있고, 비동기로 전송하기 위해 Message Queue를 사용할 수 있다. 

컴포넌트 간 네트워크로 연결되기 때문에 패킷 손실이나 네트워크 지연으로 인한 데이터 유실에 대비해야한다.

 

데이터 전달 보장 방법에는 세가지가 있다. 

  • at-most-once (최대 한번)
    메시지를 재전송하지 않는 방식이다. 네트워크 오류 등으로 전달이 실패하면 메시지가 유실될 수 있다. (fire and forget)
  • at-least-once (최소 한번)
    메시지가 최소 한 번 전달되도록 재시도를 수행하는 방식이다.
    네트워크 장애나 응답 손실로 인해 메시지가 중복 전달될 수 있으므로 consumer에서는 멱등성 처리가 필요하다.
  • exactly once (정확히 한번)
    네트워크 불안정, 장애, 재시도 등의 상황에서 메시지 전달 성공 여부를 정확히 판단하기 어렵기 때문에 구현이 매우 어렵다.
    따라서 거의 at-least-once 에 멱등성 처리 방식을 사용한다고 보면 된다.

 

RDB만을 사용하여 실패없는 이벤트 처리 패턴 

특정 데이터를 저장하는 비즈니스 로직이 있다고 해보자. 비즈니스 로직이 정상적으로 수행하면 즉, 트랜잭션이 commit된 이후 이벤트를 발행하고 at-least-once를 위해 이벤트 발행에 대한 재시도를 구현할 수 있다. 그치만 재시도가 무한정 될 수는 없으니 at-least-once를 보장할 수는 없다. 

Transactional outbox pattern Polling publisher pattern을 조합해서 이를 해결할 수 있다.

Transactional outbox pattern이란 비지니스 데이터 변경과 이벤트 메시지를 동일한 트랜잭션으로 RDB에 함께 저장하여 이벤트 유실을 방지하는 패턴이다.

Polling publisher pattern이란 스케줄러가 Outbox 테이블을 주기적으로 조회하여 미발행 이벤트를 메시지 브로커로 발행하는 방식이다.

이벤트를 RDB에 저장할 때는 다음과 같은 컬럼이 포함되어야 한다. 

  • event_id : 이벤트 유니크 값, RDB의 pk값으로 주로 쓴다. 
  • created_at: 이벤트 발생시간
  • status: 상태값
  • payload: 이벤트 payload

이 방식은 at-least-once로 데이터 유실을 방지할 수 있다는 장점이 있다. 

반면, Polling publisher pattern으로 인한 지연 처리 때문에 실시간성으로 처리되어야하는 경우에는 적절하지 않을 수 있다. 

그리고 Transactioner outbox pattern은 데이터베이스 성능과 비례하여 처리 속도가 결정되기 때문에 대용량 이벤트를 발행하는 경우  DB 증설이 필요할 수도 있다. 

 

RabbitMQ를 사용한 전달 방법 

RabbitMQ는 AMQP를 구현한 메시지 브로커로 Ack로 메시지 응답처리 메커니즘을 지원한다. 

producer confirm으로 RabbitMQ 브로커가 메시지를 정상적으로 수신했는지 ack/nack를 받아 처리할 수 있다. 

또한, consumer가 메시지를 처리하고 성공여부에 따라 queue에 ack 혹은 nack를 전송하는 consumer ack방식이 가능하다.

 

만약, consumer에서 장애나 코드 버그 등 모종의 이유로 nack만 보내는 경우 queue에 실패된 메시지가 쌓일 수 있다. 

이때 Dead letter queue를 추가해서 실패된 메시지는 격리되도록 할 수 있다. 

보통 다음의 세가지 상황에서 DLQ로 전송되도록 설정한다. 

  1. consumer로부터 basic.reject나 basic.nack를 수신하면 DLQ로 전송
  2. queue의 메시지가 오래되거나 TTL이 만료된 경우
  3. queue가 가득찬 경우

 

추가로 참고한 영상에서는 kafka를 사용한 방법도 소개되었는데 RabbitMQ와 동일한 개념을 spring 진영의 코드레벨로만 설명이 되어 추가로 kafka와 RabbitMQ의 차이점에서도 학습할 예정이다. 

참고 영상: https://youtu.be/uk5fRLUsBfk?si=-4Xz24dZiZdpkDsb