`tenant + Idempotency-Key`로 재시도 요청은 같은 message를 재사용합니다.
분산 이메일
서비스 설계
이메일은 API 응답 하나로 끝나지 않습니다. SMTP submission·MTA relay·도메인별 큐·재시도·반송과 complaint, 첨부와 인증을 분리해 전송 상태와 사용자 경험을 과장하지 않는 전달 시스템을 만듭니다.
API가 기록한 요청, MIME 원본, 수신자별 delivery job, SMTP attempt, bounce·complaint는 서로 다른 상태입니다. durable queue에서 수신 도메인별 속도·TLS·평판을 제어하고, timeout은 실패로 단정하지 않습니다. 첨부는 object storage에서 scan·stream하며, DKIM·DMARC·MTA-STS와 suppression을 전송 경로의 정책으로 취급합니다.
보냈다는 말을 단계별 상태로 나눈다
SMTP의 원격 수락, inbox placement, 열람은 같은 신호가 아닙니다. 이 설계는 transaction·marketing 목적과 수신자별 결과를 먼저 모델링하고, 발신 서비스에는 SMTP credential과 retry 정책을 숨깁니다.
fan-out 뒤 queue·attempt·bounce를 recipient 단위로 기록합니다.
suppression, unsubscribe, domain rate, abuse 검사를 전송 직전에 적용합니다.
API accepted, SMTP accepted, deferred, bounced, complained를 합치지 않습니다.
메시지, 수신자, transport feedback을 분리한다
outbox는 API 수락과 전송 작업 발행의 틈을 줄입니다. composer는 변경되지 않는 MIME 원본을 만들고, domain queue와 MTA pool은 원격 도메인의 실패·속도·평판을 다른 tenant와 격리합니다.
수락, 조립, 전송, 피드백을 순서대로 남긴다
첨부를 포함한 이메일의 raw MIME은 재시도 중에 조용히 바뀌지 않아야 합니다. 수신자별 job이 도메인 정책·suppression을 다시 확인하고, MTA의 응답과 DSN을 event로 추가합니다.
API가 identity, template, 멱등 키를 검증해 message와 outbox를 함께 기록합니다.
scan 완료 object를 stream하고 versioned template·Message-ID·DKIM 서명을 준비합니다.
수신 domain queue에서 unsubscribe, suppression, quota, rate·TLS 정책을 확인합니다.
submission/MTA가 MX로 relay하고 recipient별 reply class와 attempt를 남깁니다.
bounce·complaint·DSN을 dedupe해 state와 suppression, 평판 지표에 반영합니다.
처리량보다 도메인별 제어가 전달 품질을 지킨다
전역 QPS를 크게 잡는 것만으로 대량 이메일을 확장할 수는 없습니다. 수신 도메인의 반응, sender reputation, complaint, retry가 함께 움직이므로 queue와 tenant의 failure domain을 의도적으로 나눕니다.
| 선택 | 장점 | 제약 | 권장 판단 |
|---|---|---|---|
| 앱이 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 필요 | 대용량 또는 민감 첨부에 검토 |
여섯 가지 실패를 transport와 평판 신호로 다룬다
API는 accepted인데 recipient job이 큐에 만들어지지 않아 이메일이 출발하지 않습니다.
특정 수신 domain의 lookup·MTA 응답 문제가 queue age와 retry를 늘립니다.
원격 MTA 수락 여부를 모른 채 worker가 죽어 중복 또는 누락 위험이 생깁니다.
서명 또는 DNS publish 불일치가 인증 실패·spam 판정 증가로 이어질 수 있습니다.
첨부를 읽지 못하거나 scan 전 파일이 compose 경로에 노출될 수 있습니다.
한 tenant의 악용이 IP·도메인 평판을 떨어뜨려 다른 발신자의 전달을 해칩니다.
공식·1차 출처
- IETF RFC 5321 — Simple Mail Transfer Protocol: SMTP transport, relay, mail submission과 응답 모델.
- IETF RFC 5322 — Internet Message Format: 메시지 header field와 body 형식.
- IETF RFC 6376 — DomainKeys Identified Mail: DKIM 서명·검증과 DNS 공개 키 모델.
- IETF RFC 8461 — SMTP MTA Strict Transport Security: 수신 도메인의 SMTP TLS 정책 게시와 발견.
작성·검토·참고 자료
참고 자료
- IETF RFC 5321 — Simple Mail Transfer Protocol: SMTP의 mail transport, relay, submission 맥락, reply와 retry 관련 기본 모델.
- IETF RFC 5322 — Internet Message Format: 이메일 message의 header field와 body 형식.
- IETF RFC 6376 — DomainKeys Identified Mail (DKIM) Signatures: DKIM 서명·검증과 DNS 공개 키 조회 모델.
- IETF RFC 8461 — SMTP MTA Strict Transport Security (MTA-STS): SMTP TLS 정책을 수신 도메인이 게시·발견하는 방식.
사실 오류·출처 정정은 문의·정정 페이지로 알려 주세요.