빌려온 부품들로 구축할 수 있는 현대적인 이메일
요약
SMTP의 설계 결함을 해결하기 위해 HTTP 기반의 차세대 이메일 프로토콜인 HMTP(Hypertext Mail Transfer Protocol)를 설계하는 방법을 다룹니다. 기존의 검증된 기술 스택(HTTP, TLS, WebFinger 등)을 조합하여 현대적인 메일 시스템을 구축하는 아키텍처를 제안합니다.
핵심 포인트
- SMTP를 대체하는 대신 HTTP 기반의 HMTP 프로토콜 설계 제안
- HTTP의 상태 코드와 인프라를 활용하여 전송 및 상태 관리 해결
- WebFinger를 활용해 DNS 수정 없이 사용자별 메일 위임 구현
- 새로운 기술 발명 없이 기존 표준 기술들을 조립하여 시스템 구축
SMTP가 40년 동안 끌어온 설계 결함들을 해결하며, HTTP 기반의 차세대 이메일 시스템을 설계해 봅시다. 조각조각 말이죠. 우리의 목표는 현재의 메일 시스템을 대체하는 것이 아닙니다(절대 안 됩니다!). 대신 학습하고, 즐기며, 전송, 수신, 게이트웨이, 키 등 모든 요소를 교체할 수 있는 최신 기술들을 발견하는 것입니다. 이 시스템은 Gmail이나 기존의 어떤 이메일 제공자와도 통신하지 않을 것입니다. 오직 자기 자신하고만 통신합니다. 우리가 유지할 유일한 것은 user@domain 형태의 주소 체계뿐입니다. 그 외의 모든 것은 재발명됩니다.
HTTP 기반의 메일 시스템이므로, 프로토콜의 이름으로 HMTP: Hypertext Mail Transfer Protocol이 적절할 것입니다 (SMTP의 Simple을 뜻하는 S 자리가 HTTP의 H 자리에 자리를 내어줍니다).
이제 기술 스택(tech stack)을 준비할 시간입니다: HTTP, TLS, WebFinger, ActivityPub, Webmention, Ed25519, HPKE, sigchains 등.
자재 명세서 (The bill of materials)
이 설계는 단 하나의 기술도 새로 발명하지 않습니다. 모든 것은 이미 존재합니다.
| 문제 | 기존 기술 | 현재 사용자 |
|---|---|---|
| 전송 및 상태 코드 | HTTP | 웹 전체 |
| ... |
우리가 사용할 모든 조각은 표준화되어 있고, 배포되어 있으며, 수백만 명에 의해 대규모로 검증되었습니다. 유일하게 새로운 점은 이들을 조립하는 방식뿐입니다.
HTTP를 선택하는 것은 단순히 실용적인 결정만은 아닙니다. 이는 새로운 프로토콜이 언젠가 구축해야 할 여러 가지 문제들을 시작부터 즉시 해결해 줍니다:
TLS, 가상 호스팅(virtual hosting) 및 SNI: 무료로 사용할 수 있습니다. 상태 코드(Status codes): 메일 프로토콜에 필요한 카탈로그가 이미 HTTP에 존재합니다. 202 Accepted (전송 대기 중), 429 Too Many Requests + Retry-After (속도 제한), 404 / 410 (알 수 없거나 사라진 메일함), 3xx (이동된 메일함), 413 (너무 큰 용량). 심지어 유료 스팸 방지 서비스도 1997년부터 예약된 코드를 사용해 왔습니다: 402 Payment Required.
기존 인프라: 프록시(proxies), 로드 밸런서(load balancers), Nginx, 모든 언어의 라이브러리. 이 프로토콜은 새로운 서버가 되는 것이 아니라, Webmention이나 Micropub처럼 *HTTP 기반의 관례(convention over HTTP)*가 됩니다.
다음 단계로 넘어가 봅시다. 어떻게 HTTP를 통해 사용자를 발견하고, 신원을 확인하며, 메시지를 전달하고, 서명 및 암호화할 수 있을까요?
1. 발견 및 위임 (더 나은 MX)
위임(Delegation)은 정적 문서로 해결됩니다:
GET https://example.com/.well-known/hmtp/ana
{
"inbox": "https://mail.migadu.example/hmtp/inbox/ana",
"keys": { ... },
...
inbox는 다른 호스트에 존재할 수 있습니다. 이것이 바로 DNS를 건드리지 않고 구현하는 MX 레코드입니다. GitHub Pages에 호스팅된 정적 블로그도 JSON 파일을 제공함으로써 자신의 메일을 프로바이더(provider)에 위임할 수 있습니다. 또한 이는 MX가 결코 할 수 없었던 것, 즉 사용자별(per-user) 위임(도메인의 각 메일함을 서로 다른 프로바이더에 배치)을 가능하게 합니다. 우리는 새로운 경로를 발명할 필요조차 없습니다. WebFinger (RFC 7033)가 정확히 이 역할을 수행하며, Mastodon은 이것이 확장 가능하다는 것을 이미 증명했습니다.
2. 키 로테이션(key rotation)에서도 유지되는 신원
신원은 키(key) 그 자체가 될 수 없습니다 (키는 분실되거나 만료되기 때문입니다). 신원은 키가 참조할 수 있는 무언가여야 합니다. 두 가지 앵커(anchor)를 가진 제안은 다음과 같습니다:
암호학적 연속성 (Cryptographic continuity): 발견 문서(discovery document)는 현재 키와 로테이션 체인을 게시하며, 여기서 각 새 키는 이전 키에 의해 서명됩니다. 키 N으로 당신을 알던 사람은 누구도 신뢰할 필요 없이 키 N+1을 검증할 수 있습니다. 이는 ATProto가 DID를 통해 수행하거나 Keybase가 과거에 수행했던 방식인 서명 체인(sigchain)입니다.
폴백으로서의 도메인 제어 (Domain control as a fallback): 서명된 로테이션 없이 키를 분실한 경우(예: 노트북 도난), 도메인은 체인 없이 새로운 키를 선언합니다. 이때 의무적인 공지 기간(예: 30일)을 두어, 당신을 알고 있던 서버들이 "서명이 아닌 도메인에 의해 신원이 재앵커링(re-anchored)되었습니다"라는 경고를 표시하게 합니다.
하지만 도메인에 앵커를 둔 신원에는 그 나름의 아킬레스건이 있습니다. 도메인은 소유하는 것이 아니라 빌리는 것이기 때문입니다. 만약 비용 지불을 중단하여 도메인이 만료되고 누군가 이를 등록한다면, 새로운 소유자는 자신의 키를 당신의 .well-known에 게시할 것입니다.
그리고 그 순간부터 그들은 당신의 메일을 수신하고 당신인 것처럼 서명합니다. 아무도 정당한 상속자와 무단 점유자를 구별할 수 없습니다. 이것이 ATProto가 또 다른 인프라 조각을 대가로 지불하면서, DID를 통해 신원 (Identity)을 도메인 (Domain)으로부터 분리함으로써 해결하고자 하는 문제입니다. 우리는 이것이 알려진 해결책이 있는 실제 문제임을 알고 있습니다. 이제 다음으로 넘어가겠습니다.
3. 큐를 이용한 전달 (저장 후 전달, store-and-forward)
전달 (Delivery)은 수신자의 인박스 (Inbox)로 보내는 POST 요청입니다:
POST /hmtp/inbox/ana HTTP/1.1
Host: mail.migadu.example
Content-Type: application/hmtp+json
핵심은 요청 자체가 아니라, 누가 그 요청을 하느냐입니다. 당신의 클라이언트는 수신자에게 직접 전달하는 것이 아니라, 당신 자신의 서버 (당신의 아웃박스 (Outbox)로 보내는 인증된 POST)로 전달하며, 큐 (Queue)를 관리하고, 지수 백오프 (Exponential backoff)를 통해 재시도하며, Retry-After를 준수하는 것은 바로 당신의 서버입니다.
이는 SMTP의 MUA/MSA/MTA 분리가 옳았음을 인정하는 것입니다. 이메일의 조용한 천재성 중 하나는 목적지 서버가 다운되어 있더라도, 당신의 서버가 며칠 동안 재시도를 수행하는 동안 당신은 그 일을 잊어버려도 된다는 점입니다.
하지만 SMTP에는 없었던 개선 사항을 하나 추가해 봅시다. 모든 메시지는 콘텐츠의 해시 (Hash)인 ID를 포함하므로, 재시도가 멱등성 (Idempotent)을 갖습니다. 수신 서버는 ID를 통해 중복을 제거하며,
탐색(discovery)과 검증(verification)이며, POST는 전달(delivery)을 담당하고, 큐(queue)는 마땅히 있어야 할 곳인 발신자의 서버에 존재합니다.
4. 이미 보유한 키를 이용한 서명 및 암호화
메시지는 단순한 텍스트가 아니라 서명된 객체(signed object)입니다:
{
"id": "sha256:9f2c...",
"from": "ana@example.com",
...
이를 통해 우리는 다음과 같은 많은 이점을 얻습니다:
저장 시의 인증성 (Authenticity at rest): 저장된 메일은 암호학적 증거를 지닙니다. 전달(forward)을 하더라도 원래의 서명이 유지됩니다. 전달 체인을 거치더라도 발신자를 위조하는 것이 불가능해집니다.
DKIM 없는 발신자 검증 (Sender verification without DKIM): 수신 서버는 from 도메인의 .well-known 경로를 GET 요청하여 해당 키가 서명했는지 확인합니다. 이는 Webmention 검증과 동일한 방식입니다. 증거는 소스(source)에서 직접 가져옵니다.
종단간 암호화 (E2E): 탐색 문서(discovery document)가 암호화 키(X25519)를 공개하며, 본문은 HPKE로 봉인됩니다. 봉투(from, to, id, date)는 라우팅과 필터링을 위해 공개 상태로 유지되지만, 내용은 수신자에게만 공개됩니다.
스레드 (Threads): 콘텐츠 해시(content hash)를 통한 in_reply_to 및 references를 사용합니다. 휴리스틱(heuristics) 없이도 대화 내용을 재구성할 수 있습니다.
첨부 파일 (Attachments): 메시지 외부에 존재합니다. 첨부 파일은 발신자의 서버를 가리키는 {hash, url, size} 형태이며, 수신자는 필요할 때 다운로드할 수 있고 수신자의 서버가 이를 미러링(mirror)할 수도 있습니다. 더 이상 base64 인코딩으로 인해 편지함이 비대해지는 일은 없습니다.
5. 계층적 스팸 방지
모든 시스템과 마찬가지로, 이는 여러 계층의 방어가 필요한 복잡한 문제입니다. HMTP를 통해 우리는 세 가지 계층으로 시작할 수 있습니다:
신원 비용 (Identity cost): ana@example.com으로 서명하려면 example.com에서 키 문서를 제공해야 합니다.
정체성 (Identity)은 도메인에 고정되며, 도메인은 비용이 발생합니다. 이것이 셀프 서명된 정체성 (self-signed identities)에는 없는 시빌 비용 (Sybil cost)입니다. 하지만 도메인은 무한한 서브도메인과 메일박스를 제공하므로, 이 비용은 주소의 대량 생성이 아니라 독립적인 정체성의 대량 생성을 늦추는 역할을 합니다. 우리는 루트 레벨에서 작업합니다. 첫 접촉 동의 (First-contact consent): 모르는 발신자는 메일박스로 바로 들어오지 못하고, 첫 메시지가 보이는 "요청 (requests)" 함에 도착합니다 (Signal의 메시지 요청과 유사). 사용자가 수락하면 스레드가 영구적으로 열립니다. 낯선 사람이 당신의 문을 두드릴 수는 있지만, 당신의 거실을 가득 채울 수는 없습니다. 낯선 이를 위한 선택적 우편 요금 (Optional postage for strangers): 서버는 첫 접촉에 대해 402 응답을 보낼 수 있습니다. 이는 메일박스별로 설정 가능하며, 이를 통해 콜드 스팸 (cold spamming)의 비용이 0이 되는 것을 방지합니다.
6. 읽기 방식 또한 지정됩니다
이메일은 전송 (SMTP)과 읽기 (IMAP/POP)를 별개의 세계로 표준화했습니다. 우리는 새로운 것을 발명할 필요가 없습니다. JSON/HTTP를 통해 메일박스를 읽고, 동기화하고, 검색하는 문제는 이미 IETF에 의해 해결되었고 표준화되어 있습니다. 그것을 JMAP이라고 부릅니다. HMTP는 전달 (delivery)을 정의할 것이며, 읽기는 하나의 새로운 객체 유형이 추가된 JMAP이 될 것입니다. SSE 또는 WebPush를 통해 클라이언트로 푸시합니다. 전체 사이클 (전송, 전달, 읽기, 동기화)은 HTTP 상에 머뭅니다.
결론
이메일의 모든 문제에는 이미 배포되어 작동 중인 해결책이 있습니다: Mastodon의 발견 (discovery), ActivityPub의 전달 (delivery), IndieWeb의 검증 (verification), Bluesky의 교체 가능한 정체성 (rotatable identity), Fastmail의 읽기 (reading), Signal의 동의 (consent). 이메일의 업그레이드는 이미 존재하지만, 아무도 이를 조립하지 않았을 뿐입니다.
우리는 우아하고 현대적인 솔루션으로 많은 문제를 해결합니다:
평판 및 사회적 허가 (Reputation and social permission) (SPF, DKIM, DMARC, 역방향 PTR, 차단 목록, 수개월간의 IP 워밍업): 모든 메시지에 대한 암호화 검증, 하나의 서명, 그리고 발신자의 .well-known에 대한 하나의 GET 요청으로 대체됩니다. 검증 가능한 속성은 평판을 필요로 하지 않습니다. 발신자 사칭 (Sender spoofing): 구조적으로 불가능합니다. 수신자는 from에 게시된 키를 통해 서명을 확인합니다.
도메인에 있으며, 전달될 때도 서명이 메시지와 함께 이동합니다. 메일 위임 (Mail delegation) (MX 레코드): .well-known에 있는 정적 문서로, 사용자별 위임이 가능하며 DNS 변경이 필요 없습니다. 콘텐츠 프라이버시 (Content privacy) (아무도 설정하지 않았던 PGP): 기본적으로 종단간 암호화 (end-to-end encryption)를 제공하며, 수신 서버는 읽을 수 없는 본문을 저장합니다. 스팸 (Spam) (사후 통계적 필터링): 첫 접촉 동의 (낯선 사람이 우편함으로 바로 들어오는 것이 아니라 문을 두드리는 방식), 도메인에 고정된 비용이 드는 신원 확인, 그리고 402를 통한 선택적 우편 요금 부과. 재시도 시 중복 (Duplicates on retry): 메시지 ID가 콘텐츠의 해시(hash)이므로, 재시도는 멱등성 (idempotent)을 가지며 수신자는 구조적으로 중복을 제거합니다. 휴리스틱으로 재구성된 스레드 (Threads rebuilt with heuristics): in_reply_to가 부모 메시지의 해시를 가리키므로, 대화는 검증 가능한 그래프 (verifiable graph)가 됩니다. 가벼운 메일함 (Light mailboxes): 첨부 파일은 참조 방식 (해시 + URL)으로 처리되어 필요할 때만 다운로드됩니다. 단순하고 친숙한 인프라 (Simple, familiar infrastructure): 모든 것이 표준 HTTPS를 통해 전달되며, 이미 웹사이트를 서비스하고 있는 동일한 Nginx와 동일한 인증서 뒤에서 작동합니다. 키 로테이션 (Key rotation) (DKIM의 운영상 악몽): 명령어 하나로 해결됩니다. 아무도 당신의 키를 고정(pin)하지 않기 때문에, 새 키는 즉시 신뢰받고 탈취된 키는 그만큼 빠르게 무용지물이 됩니다.
말은 쉽기에, 저는 Python으로 작동하는 프로토타입을 구현했습니다: github.com/tanrax/hmtp. 모두 단일 파일로 구성되어 있습니다. 이 프로토타입은 서명된 전달, 소스에서의 검증, 종단간 암호화, 첫 접촉 동의, 중복 제거, 스레드, 지수 백오프 (exponential backoff)가 적용된 큐, 그리고 명령어 하나로 실행되는 키 로테이션까지 전체 전송 과정을 다룹니다. 주변부의 요소들은 의도적으로 제외했습니다: 서명된 로테이션 체인 (수신자가 키를 고정하는 대신 매 전달 시마다 실시간으로 키를 가져오므로, 노드가 키를 캐싱하기 시작할 때부터 체인의 이점이 발생함), 402...
우편 요금(postage), 참조를 통한 첨부 파일(attachments by reference), 그리고 JMAP 읽기(JMAP reading)를 지원합니다. README에는 퀵스타트(2분 만에 첫 메시지 보내기, 자신에게 메일 보내기), 로컬 머신에서 두 노드가 암호화된 메일을 교환하는 데모, 그리고 DNS부터 systemd까지 아우르는 전체 프로덕션 가이드가 포함되어 있습니다. 이 프로젝트는 검증되지 않은 암호화(unaudited cryptography)를 사용하는 설계 실험이라는 점을 명심하세요. 누군가가 의존하는 비밀 정보를 다루는 데 사용하지 마십시오. 비록 여러분이 떠올리는 어떤 생태계에서든 가벼운 통신 시스템으로 활용될 수는 있겠지만 말입니다.
이 여정을 즐기셨기를 바랍니다. 만약 여러분이 첫 HMTP 메시지를 보내게 된다면, 꼭 소식을 듣고 싶습니다.
- 자재 명세서 (The bill of materials)
-
- 발견 및 위임 (더 나은 MX)
-
- 키 로테이션 (key rotation) 중에도 유지되는 신원 (Identity)
-
- 큐를 이용한 전달 (store-and-forward)
-
- 이미 보유한 키를 이용한 서명 및 암호화
-
- 계층형 스팸 방지 (Layered anti-spam)
-
- 읽기 방식의 구체화
- 결론
이 저작물은 Attribution-NonCommercial-NoDerivatives 4.0 International 라이선스 하에 제공됩니다.
커피 한 잔 사주시겠어요?
이것이 제가 광고나 유료 결제 장벽 없이 글을 계속 써 내려가는 방법입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기