시스템 디자인 운영·메시징 / 사례 연구
⌕ 주제, 용어, 패턴 검색 ⌘ K
학습 로드맵
CASE · ADVANCED읽기 26분검토일 2026-08-29

분산 이메일
서비스 설계

API accepted나 SMTP remote accepted를 사용자의 inbox 도착으로 말할 수는 없습니다. 도메인별 queue·재시도·bounce·complaint를 분리해 확인 가능한 상태만 표시합니다.

개념 이해전송 경로인증·평판장애 대응진도 저장
30초 핵심 요약

API accepted, SMTP remote accepted, bounce·complaint, mailbox placement를 별도 상태로 둡니다. 4xx는 domain별 backoff, 5xx·complaint는 suppression에 반영하고 확인하지 못한 inbox 도착은 보장하지 않습니다.

요청 경계Idempotency + outbox
전송 경계Domain queue + MTA
결과 경계Accepted ≠ inbox
DESIGN DECISION · 설계 판단

SMTP 수락 이후 어디까지를 전달 성공이라고 말할 수 있는가?

예시 이메일 요청 600만/day 설계 가정
예시 피크 job 약 1,670/s 계산 결과
예시 MIME 원본 230GB/day 계산 결과
최종 선택

recipient state + domain queue + verified MTA feedback

API accepted, 원격 MTA accepted, bounce·complaint를 수신자별 상태로 나눕니다. domain queue에서 4xx backoff와 rate control을 적용하고 검증된 feedback을 suppression에 반영합니다.

선택 이유

  • SMTP 250을 받은편지함 도착으로 과장하지 않습니다.
  • 특정 domain 장애와 평판 문제를 다른 발송에서 격리합니다.
  • bounce·complaint·unsubscribe 뒤 재발송을 빠르게 차단합니다.
포기한 대안

API 요청 안에서 SMTP를 동기 호출하고 성공으로 종료

외부 timeout이 업무 latency에 결합되고 이후 bounce·complaint와 domain별 retry 상태를 추적하기 어렵습니다.

감수한 단점

  • domain별 queue·rate·IP reputation 운영이 필요합니다.
  • SMTP timeout 뒤 중복 가능성을 완전히 제거할 수 없습니다.
  • MIME·첨부·feedback 보존이 storage와 보안 비용을 늘립니다.
01 · REQUIREMENTS

보냈다는 말을 단계별 상태로 나눈다

# 요구사항

SMTP의 원격 수락, inbox placement, 열람은 같은 신호가 아닙니다. 이 설계는 transaction·marketing 목적과 수신자별 결과를 먼저 모델링하고, 발신 서비스에는 SMTP credential과 retry 정책을 숨깁니다.

R1멱등 수락

tenant + Idempotency-Key로 재시도 요청은 같은 message를 재사용합니다.

R2수신자별 상태

fan-out 뒤 queue·attempt·bounce를 recipient 단위로 기록합니다.

R3정책 분리

suppression, unsubscribe, domain rate, abuse 검사를 전송 직전에 적용합니다.

R4감사 가능한 결과

API accepted, SMTP accepted, deferred, bounced, complained를 합치지 않습니다.

02 · HIGH-LEVEL DESIGN

메시지, 수신자, transport feedback을 분리한다

# 아키텍처

outbox는 API 수락과 전송 작업 발행의 틈을 줄입니다. composer는 변경되지 않는 MIME 원본을 만들고, domain queue와 MTA pool은 원격 도메인의 실패·속도·평판을 다른 tenant와 격리합니다.

이메일 제출부터 feedback까지의 독립 경로 SVG DIAGRAM · message / recipient / MTA / DSN
분산 이메일 서비스의 API, MIME composer, 도메인별 큐, MTA, 수신 도메인, bounce와 complaint 피드백 흐름제품 서비스가 이메일 API에 요청을 넣으면 message와 outbox가 기록된다. MIME composer가 object storage의 첨부를 참조해 원본을 만들고, 수신 도메인별 큐와 정책 계층을 거쳐 submission MTA가 수신 도메인의 MX에 전송한다. DSN bounce와 complaint 피드백은 수신자 상태 및 suppression 저장소로 기록된다.durable accept → immutable MIME → domain policy → SMTP relay → feedbackProduct servicetemplate · idempotencyattachment referenceEmail API + Outboxmessage · recipientaccepted ≠ deliveredMIME composerrender · DKIM signobject streamDomain queuerate · TLS policyretry budgetSubmission MTASMTP · TLS · MXIP / pool isolationRecipient MXSMTP 2xx / 4xx / 5xxinbox policyFeedbackDSN · bouncecomplaintRecipient statesuppression · auditmetricsMTA의 수락은 transport 단계의 사실이고, 받은편지함 표시·열람은 별도의 제품 신호다.
중요: SMTP timeout 뒤 원격 MTA가 실제로 받았을 수 있습니다. 따라서 queue의 at-least-once 재처리는 허용하되 새 message를 만들지 않고, message·recipient·attempt ID와 retry budget으로 중복 위험을 줄입니다.
03 · SUBMISSION / DELIVERY FLOW

수락, 조립, 전송, 피드백을 순서대로 남긴다

# 요청 흐름

첨부를 포함한 이메일의 raw MIME은 재시도 중에 조용히 바뀌지 않아야 합니다. 수신자별 job이 도메인 정책·suppression을 다시 확인하고, MTA의 응답과 DSN을 event로 추가합니다.

1Accept + outbox

API가 identity, template, 멱등 키를 검증해 message와 outbox를 함께 기록합니다.

2Compose MIME

scan 완료 object를 stream하고 versioned template·Message-ID·DKIM 서명을 준비합니다.

3Domain policy

수신 domain queue에서 unsubscribe, suppression, quota, rate·TLS 정책을 확인합니다.

4SMTP attempt

submission/MTA가 MX로 relay하고 recipient별 reply class와 attempt를 남깁니다.

5Feedback loop

bounce·complaint·DSN을 dedupe해 state와 suppression, 평판 지표에 반영합니다.

04 · TRADEOFFS

처리량보다 도메인별 제어가 전달 품질을 지킨다

# 대안과 트레이드오프

재시도 기간을 늘리면 일시 장애 복구율은 오르지만 늦은 메일과 비용도 늘어납니다. 전역 처리량보다 domain별 반응과 sender reputation을 우선해 속도를 조절합니다.

선택장점제약권장 판단
앱이 SMTP 직접 호출초기 구현 짧음credential·timeout·retry가 업무 요청에 섞임소규모 내부 도구 외에는 지양
API + outbox + MTA pool전송 장애 격리·감사·재처리상태 모델과 운영 구성 증가거래성 또는 multi-tenant 기본
단일 전역 queue운영 단순캠페인·문제 domain이 전체를 막음매우 작은 volume에 한정
domain queue + token bucket원격 제한·평판·backlog 격리coordinator와 domain dashboard 필요인터넷 발송의 기본
inline 첨부수신자 UX 단순queue·scan·storage 비용 증가작고 scan 완료된 파일만
signed download URL큰 payload와 민감 파일 통제만료·수신자 인증 UX 필요대용량 또는 민감 첨부에 검토
05 · FAILURE MODES

여섯 가지 실패를 transport와 평판 신호로 다룬다

# 장애 6가지
outbox relay 중단

API는 accepted인데 recipient job이 큐에 만들어지지 않아 이메일이 출발하지 않습니다.

대응 · outbox lag·message/job 차이로 감지하고 idempotent replay와 reconciliation으로 누락 0을 검증합니다.
DNS/MX 또는 원격 4xx

특정 수신 domain의 lookup·MTA 응답 문제가 queue age와 retry를 늘립니다.

대응 · domain circuit breaker, cached resolver, jitter와 retry budget을 적용하고 backlog drain을 확인합니다.
?SMTP timeout 뒤 결과 불명

원격 MTA 수락 여부를 모른 채 worker가 죽어 중복 또는 누락 위험이 생깁니다.

대응 · attempt 이력·stable message ID·제한 재시도로 새 message 생성을 막고 ambiguous 비율을 관측합니다.
DKIM key·selector 배포 오류

서명 또는 DNS publish 불일치가 인증 실패·spam 판정 증가로 이어질 수 있습니다.

대응 · key version rollout·검증 sample·rollback을 준비하고 domain health error spike를 봅니다.
첨부 scan/object 장애

첨부를 읽지 못하거나 scan 전 파일이 compose 경로에 노출될 수 있습니다.

대응 · immutable object와 ready gate·격리 버킷을 사용하고 scan pending age를 SLO로 둡니다.
!complaint·abuse 급증

한 tenant의 악용이 IP·도메인 평판을 떨어뜨려 다른 발신자의 전달을 해칩니다.

대응 · tenant pause, suppression, quota, review queue로 격리하고 complaint baseline 회복을 검증합니다.
면접 모드 · 추가 질문06:00
“하루 600만 요청·960만 수신자에게 거래성 메일과 캠페인을 함께 보내야 합니다. SMTP timeout 뒤 중복을 줄이고, bounce·complaint를 반영하며, TLS·DKIM·DMARC와 대용량 첨부까지 다루려면 어떤 데이터 모델·queue·MTA policy·관측 지표를 설계하시겠습니까?”
message + recipientdomain queueattempt + feedbackDKIM · TLS policysuppression · reputation
답변 구조 보기 5단계
  1. API accepted, SMTP remote accepted, bounce·complaint, mailbox placement를 다른 상태로 정의한다.
  2. MIME 원본과 수신자별 job을 만들고 domain queue로 속도·평판 장애를 격리한다.
  3. 4xx는 backoff, 5xx와 complaint는 suppression, timeout은 모호한 attempt로 처리한다.
  4. DKIM·TLS·credential·첨부 scan을 전송 전후의 보안 경계로 운영한다.
  5. domain별 queue age와 SMTP class, bounce·complaint로 복구를 판정한다. 이번 선택: 비동기 domain queue와 MTA feedback을 사용하고, 확인한 범위까지만 전달 상태로 공개한다. 깨지는 신호: SMTP 250을 inbox delivery로 집계하거나 hard bounce 주소가 계속 재시도된다. 다음 검증: 특정 domain의 4xx·timeout·complaint burst를 재현해 rate 조절과 suppression 반영 시간을 측정한다.
INTERVIEW ↔ PRACTICE · 면접과 실무의 차이

SMTP 상태 범위를 설명하고 domain 평판·suppression을 운영하기

INTERVIEW · 면접

accepted, remote accepted, mailbox placement를 서로 다른 상태로 답합니다.

  • MIME·recipient job·domain queue 흐름을 설명합니다.
  • 4xx·5xx·timeout의 다른 재시도 정책을 말합니다.
  • DKIM·TLS·bounce·complaint suppression을 연결합니다.
PRACTICE · 실무

한 domain의 4xx와 complaint burst에서 발송량보다 평판을 보호합니다.

  • domain별 queue age와 SMTP class를 관측합니다.
  • hard bounce 주소가 다시 enqueue되지 않는지 확인합니다.
  • rate 축소 뒤 complaint와 retry budget 회복을 검증합니다.
SOURCES

공식·1차 출처

NEXT CASE STUDY결제 시스템 설계
EDITORIAL NOTES

작성·검토·참고 자료

콘텐츠 원칙
이 문서는 독립적으로 재작성한 한국어 학습 자료입니다. 사실과 학습용 설계 가정을 구분합니다.
작성·기술 검수
프로젝트 운영자가 직접 작성·기술 검토했습니다. 주제별 공식·1차 자료와 명시적인 설계 가정을 확인하며, 독립적인 제3자 검수가 아닙니다. 경력 범위와 검수 원칙 보기
최종 검토
예상 학습 시간
26분

사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.