Joe Armstrong 저서에서 인용

"메시지는 유실될 수 있다. Erlang은 실패 가능성을 숨기지 않는다.
그러나 그것은 신뢰할 수 있는 실패이다. 왜냐하면 숨기지 않기 때문이다."

Joe Armstrong, Programming Erlang

💡 "거짓없는(Unreliable but Honest)" 철학

"Erlang은 메시지를 신중하게 보내며, 실패할 가능성을 숨기지 않는다.
메시지가 유실될 수 있음을 정직하게 인정하고,
시스템 설계자가 그에 맞게 복원력을 고려하도록 한다."


언랭에서 출발한 위와같은 개념은 오늘날의 메시지 전송 수준 개념에 영향을 주며 확장 되었습니다.

언랭의 거짓없는 메시지 전송을 살펴보고 메시지 전송 수준에 대한 개념과 함께

Kafka/Akka에서 이용할수 있는 장치도 함께 살펴보겠습니다.

🧩 Erlang의 메시지 전송: "Unreliable but Honest"

🟡 핵심 정의


✅ 의미 정리

요소설명
보낸다는 약속Sender ! Msg를 실행하면 Erlang은 메시지를 보내려고 시도했음을 보장
수신자 보장 없음수신자가 다운되었거나, 네트워크 분리, 큐가 손상된 경우 메시지는 유실될 수 있음
확인(ACK)기본적으로 ACK가 없음. 메시지 수신 여부는 확인할 방법이 없음
신뢰성 책임개발자가 직접 retry, ACK, 중복제거를 구현해야 함
기본 전송 모델At-Most-Once에 가까운 구조 (한 번 보내고 끝)



🧠 Erlang 프로그래머의 현실 대응법


상황대응 방식
메시지 유실 방지gen_server:call 처럼 동기 호출 사용 (내부 ACK)
중복 방지메시지에 UUID 붙이고 중복 수신 필터링
상태 복구supervisor + process monitoring 활용
메시지 순서 보장기본적으로 없음 → 순서를 명시적으로 관리해야 함

예시요약

% 메시지 보내기 (ACK 없음, 실패 감지 불가)
ReceiverPid ! {from, self(), hello}.

% 신뢰 보장 원한다면 call 사용
Response = gen_server:call(MyServer, {do_work, Payload}).

🎯 요약 비교


항목Erlang 기본 메시징Kafka / Akka 등 현대 메시지 플랫폼
전달 보장❌ (at-most-once 유사)✅ (옵션에 따라 보장)
중복 방지❌ 직접 구현✅ 트랜잭션 / idempotency 지원
유실 허용✅ (허용됨, 정직함)❌ 최소 at-least-once 보장됨
ACK / Retry❌ 기본 미제공✅ 명시적 제공


🧠 핵심 요약

단계

시스템

메시지 전달 수준

특징

Erlang (1986)

기본: At-Most-Once

메시지 유실 가능, ack 없음, 재전송은 직접 구현

Akka (2010~)

기본: At-Most-Once + At-Least-Once

at-least-onceAck 직접 구현, DurableMailbox

Akka Persistence

At-Least-Once + Idempotent ActorExactly-Once에 근접

이벤트 소싱, 재처리 시 동일 효과 보장

Kafka (v0.11~)

명시적 지원: At-Most, At-Least, Exactly Once

트랜잭션 API + Idempotent Producer 제공


Message Delivery Semantics

메시지 보장수준은 전략에따라 채택할수 있으며 모든기능에 보장수준을 최고수준으로 하는 오버엔지니어링을 하기보다는

인프라및 설계비용을 고려 전략적 채택이 중요할수 있습니다.

✅ 1. At Most Once (최대 1번 전송)


✅ 2. At Least Once (적어도 1번 전송)


✅ 3. Exactly Once (정확히 1번 전송)


💡 선택 기준 요약표

전송 수준

중복

손실

처리 비용

사용 예시

At Most Once

💲 (낮음)

로그, 알림

At Least Once

💲💲 (중간)

주문, 결제

Exactly Once

💲💲💲 (높음)

금융, 정산


🔍 인프라 비용 고려 팁


Kafka를 활용한 Exactly Once전략

Kafka를 단순하게 이용한다고 ExactlyOnce의 목표가 달성되는것이 아니며 성능을 위해 At MostOnce전략을 채택할수도 있으며

Exactly달성을 위해서는 Kafka의 특성을 이해하고 설계자가 활용해야하며  Kafka는 메시지 보장수준에따른 다양한 전략적 기능을 제공해줍니다.


Kafka에서 **Exactly Once Semantics (EOS)**를 구현하기 위해서는 일반적인 at-least-once 또는 at-most-once보다 복잡한 설정과 추가 기술이 필요합니다. 다음은 Kafka에서 Exactly Once 메시지 전송을 보장하기 위해 반드시 이해하고 활용해야 하는 기술 요소들을 요약한 것입니다:


✅ 1. Transactional Producer


✅ 2. Idempotent Producer


✅ 3. Transaction Coordinator


✅ 4. Transactional Consumer (정확히 Once 소비 보장)


트랜잭션 시작 → 메시지 소비 → 처리 → 결과 produce → offset 커밋 → 트랜잭션 commit


✅ 5. Exactly Once 설정 요약


설정 항목
enable.idempotencetrue (Producer 필수)
acksall
transactional.id고유한 문자열 지정
isolation.levelread_committed (Consumer 측)
offset 커밋 방식

트랜잭션 내부에서 처리 필요


✅ 6. 주의점 / 제약사항


💡 실무에서 함께 고려해야 할 것


AKKA에서의 Exactly Once 전략

✅ 1. Persistence (Event Sourcing) + At-Least-Once + Idempotency 조합


✅ 2. Deduplication (중복 제거 로직)


✅ 3. Transactional Outbox 패턴


✅ 4. Exactly Once Kafka Sink (Kafka + Akka Streams)

Transactional
  .source(...)
  .map { msg -> ProducerMessage.single(..., msg.partitionOffset) }
  .via(Transactional.flow(producerSettings, transactionSettings))
  .runWith(Sink.ignore(), materializer)


✅ 5. Pekko DurableStateBehavior with External Store


✅ 6. Reliable Delivery (Akka Typed) (Experimental / Pekko 개선 중)


🔐 보조 도구


결론

Akka 자체는 정확히 "Exactly Once"를 자동으로 보장하지 않습니다. 하지만 다음의 조합을 통해 이를 현실적으로 달성할 수 있습니다:

At-Least-Once delivery + Idempotent business logic + Persistence or transactional write