---
title: "SMTP를 HTTP 위에서 다시 만든다면? 기존 부품만 조립한 현대식 이메일 실험"
published: 2026-07-27T08:27:21.000Z
canonical: https://jeff.news/article/5142
---
# SMTP를 HTTP 위에서 다시 만든다면? 기존 부품만 조립한 현대식 이메일 실험

글쓴이는 SMTP를 대체하려는 게 아니라, HTTP·WebFinger·Ed25519·HPKE·JMAP 같은 이미 검증된 기술로 이메일의 문제를 다시 설계해보는 HMTP 실험을 소개해. 핵심은 주소 형태만 user@domain으로 유지하고, 전송·발견·서명·암호화·스팸 방어·읽기 모델을 전부 현대 웹 인프라 위에 얹는 거야.

- 이 글은 “이메일을 HTTP 위에서 다시 설계하면 어떨까?”라는 꽤 개발자다운 장난에서 출발함
  - 목표는 Gmail이나 기존 SMTP 세계와 호환되는 새 메일 시스템을 만드는 게 아님
  - 주소 모양만 `user@domain`으로 남기고, 전송·수신·키·위임·스팸 방어를 전부 다시 조립해보자는 실험임

- 이름은 HMTP, Hypertext Mail Transfer Protocol임
  - SMTP의 Simple 대신 HTTP의 H가 들어간다는 농담 섞인 작명임
  - 하지만 내용은 꽤 진지함. HTTP, TLS, WebFinger, ActivityPub, Webmention, Ed25519, HPKE, sigchain, JMAP 같은 이미 배포된 기술만 사용하자는 설계임

- HTTP를 고른 이유는 단순히 익숙해서가 아니라, 새 프로토콜이 언젠가 만들어야 할 걸 이미 갖고 있기 때문임
  - TLS, 가상 호스팅, SNI는 그냥 따라옴
  - `202 Accepted`는 큐에 들어감, `429 Too Many Requests`와 `Retry-After`는 속도 제한, `404/410`은 메일함 없음, `413`은 너무 큼, 심지어 `402 Payment Required`는 유료 안티스팸에 딱 맞음
  - Nginx, 프록시, 로드밸런서, 언어별 HTTP 라이브러리도 그대로 쓸 수 있음

### MX 대신 .well-known

- HMTP의 사용자 발견은 DNS MX 대신 정적 문서로 처리함
  - 예를 들어 `https://example.com/.well-known/hmtp/ana`를 GET하면 Ana의 inbox URL, 키, 기기 목록을 JSON으로 받는 식임
  - inbox는 `mail.migadu.example` 같은 다른 호스트에 있어도 되고, 정적 블로그가 JSON 하나로 메일 제공자에게 위임하는 것도 가능함

- 이 방식은 MX가 못 하던 사용자별 위임도 가능하게 함
  - 같은 도메인의 각 메일함이 서로 다른 제공자에 붙을 수 있음
  - 굳이 새 라우트를 만들 필요도 없음. WebFinger(RFC 7033)가 이미 비슷한 발견 문제를 풀고 있고, Mastodon이 대규모에서 돌아간다는 걸 보여줬음

### 정체성은 키 하나에 걸면 안 됨

- 글쓴이는 정체성을 암호키 자체로 보면 안 된다고 봄
  - 키는 잃어버릴 수 있고, 만료될 수 있고, 교체될 수 있음
  - 그래서 현재 키와 키 교체 체인을 discovery 문서에 공개하고, 새 키는 이전 키가 서명하는 sigchain 구조를 제안함

- 그래도 키를 완전히 잃어버리면 도메인 통제권이 fallback이 됨
  - 예를 들어 노트북을 도난당해 서명된 회전을 못 하면, 도메인이 새 키를 선언하되 30일 같은 공지 기간을 둠
  - 이때 서버는 “서명이 아니라 도메인으로 정체성이 다시 고정됐다”는 경고를 보여줄 수 있음

> [!WARNING]
> 도메인 기반 정체성의 약점은 도메인이 소유물이 아니라 임대물이라는 점임. 도메인을 놓치면 새 등록자가 `.well-known`에 자기 키를 올리고 메일을 받거나 서명할 수 있는데, 이 문제는 ATProto가 DID로 풀려는 바로 그 지점임.

### 배달은 POST, 책임은 발신자 서버

- HMTP 배달은 수신자 inbox로 HTTP POST를 보내는 구조임
  - 다만 클라이언트가 직접 상대 서버로 보내는 게 아니라, 자기 서버의 outbox에 인증된 POST를 넣음
  - 그다음 발신자 서버가 큐에 넣고, 실패하면 지수 백오프(exponential backoff)로 재시도하고, `Retry-After`도 존중함

- 여기서는 SMTP의 MUA/MSA/MTA 분리가 옳았다고 인정함
  - 목적지 서버가 다운돼도 내 서버가 며칠 동안 재시도하고, 사용자는 잊고 살아도 되는 구조가 이메일의 조용한 장점이라는 거임
  - HMTP는 그 장점을 유지하되, 메시지 ID를 콘텐츠 해시로 만들어 재시도 중복 문제를 줄임

```mermaid
sequenceDiagram
    autonumber
    participant 발신자클라이언트 as 발신자 클라이언트
    participant 발신자서버 as 발신자 서버
    participant 수신자서버 as 수신자 서버
    발신자클라이언트->>발신자서버: outbox에 서명된 메시지 POST
    발신자서버-->>발신자클라이언트: 202 큐 등록
    발신자서버->>수신자서버: .well-known으로 inbox와 키 조회
    발신자서버->>수신자서버: inbox에 봉인된 본문 POST
    Note over 수신자서버: 첫 시도 실패
    발신자서버->>수신자서버: 같은 ID로 재시도
    수신자서버->>발신자서버: 발신자 키 조회 후 서명 검증
    수신자서버-->>발신자서버: 201 배달 완료
```

### 서명, 암호화, 스팸 방어도 프로토콜 안으로

- 메시지는 그냥 텍스트가 아니라 서명된 객체임
  - `id`, `from`, `to`, `date`, `in_reply_to`, `subject`, 암호화된 `body`, `signature`를 가진 JSON 객체에 가까움
  - 저장된 메일 자체가 암호학적 증명을 갖고 있어서, 전달된 메일도 원래 서명을 보존할 수 있음

- 발신자 검증은 DKIM 대신 `.well-known`에서 키를 가져와 확인함
  - 수신 서버가 `from` 도메인의 키 문서를 GET하고, 그 키로 서명이 맞는지 검증함
  - 본문은 X25519 키와 HPKE로 봉인하고, envelope만 라우팅과 필터링을 위해 보이게 둠

- 첨부파일은 메시지 안에 base64로 우겨넣지 않음
  - `{hash, url, size}` 형태로 발신자 서버의 파일을 가리키고, 수신자는 필요할 때 다운로드함
  - 수신자 서버가 원하면 미러링할 수 있어서, 메일함이 첨부파일 때문에 무거워지는 문제도 줄어듦

- 스팸 방어는 여러 층으로 쌓음
  - 도메인에 정체성을 묶어 독립 신원 생성 비용을 올림
  - 모르는 발신자는 바로 inbox가 아니라 Signal의 메시지 요청처럼 requests 박스에 들어감
  - 원하면 첫 연락에 `402 Payment Required`를 돌려서 콜드 스팸 비용을 0이 아니게 만들 수 있음

> [!IMPORTANT]
> 글쓴이의 결론은 “검증 가능한 속성은 평판에 기대지 않아도 된다”는 것임. SPF, DKIM, DMARC, PTR, 블록리스트, IP 워밍업을 쌓는 대신, 메시지마다 서명 하나와 `.well-known` GET 하나로 발신자 증명을 하자는 주장임.

### 읽기는 JMAP에 맡김

- HMTP는 배달을 정의하고, 읽기·동기화·검색은 JMAP을 쓰자는 입장임
  - SMTP와 IMAP/POP처럼 세계가 갈라지는 대신, 전체 사이클을 JSON/HTTP 위에 올림
  - 클라이언트 푸시는 SSE나 WebPush를 붙이면 됨

- 글쓴이는 실제 Python 프로토타입도 만들었음
  - 단일 파일 구현이고, 서명된 배달, 원본 키 검증, 엔드투엔드 암호화, 첫 연락 consent, 중복 제거, 스레드, 지수 백오프 큐, 키 회전을 포함함
  - 빠진 건 서명된 키 회전 체인, 402 postage, 참조형 첨부파일, JMAP 읽기 쪽임
  - 암호화는 감사를 받지 않았으니 실제 중요한 비밀에는 쓰지 말라고 선을 그음

---

## 기술 맥락

- HMTP의 가장 큰 기술적 선택은 새 서버 생태계를 만들지 않고 HTTP 규약 위의 관습으로 남겠다는 거예요. 그래서 TLS, 상태 코드, 프록시, 로드밸런서, 기존 운영 도구를 그대로 먹을 수 있고, 프로토콜 채택 비용을 낮추는 게 핵심이에요.

- MX 레코드 대신 `.well-known`이나 WebFinger를 쓰는 이유는 DNS가 도메인 단위 위임에는 강하지만 사용자별 위임에는 둔하기 때문이에요. 정적 JSON 문서로 inbox와 키를 발견하면, 정적 사이트를 쓰는 사람도 메일 처리를 외부 제공자에게 넘길 수 있어요.

- 메시지 ID를 콘텐츠 해시로 만드는 건 재시도 설계에서 꽤 중요한 포인트예요. 네트워크에서 ACK가 사라지면 같은 메일이 두 번 들어가는 고전 문제가 생기는데, 같은 본문은 같은 ID를 갖게 하면 수신 서버가 구조적으로 dedupe할 수 있거든요.

- 스팸 방어를 필터링 이후가 아니라 첫 접촉 단계로 당기는 것도 중요한 차이예요. 모르는 사람의 메일을 일단 inbox에 넣고 나중에 분류하는 대신, 요청함과 선택적 비용을 두면 낯선 발신자가 문은 두드릴 수 있지만 방 안을 채우지는 못해요.

## 핵심 포인트

- HMTP는 새 기술을 발명하기보다 HTTP, TLS, WebFinger, ActivityPub, HPKE, JMAP 같은 기존 표준을 조립하는 설계임
- MX 레코드 대신 .well-known 문서로 사용자별 inbox와 키를 발견하고 위임할 수 있음
- 메시지는 콘텐츠 해시 기반 ID를 가져 재시도 중복 문제를 구조적으로 줄임
- 서명과 엔드투엔드 암호화를 기본 모델에 넣고, 낯선 발신자는 요청함이나 402 Payment Required로 제어함
- 글쓴이는 Python 단일 파일 프로토타입까지 구현했지만, 암호화는 감사를 받지 않았으니 실제 비밀 통신에 쓰지 말라고 못박음

## 인사이트

이 글의 재미는 ‘이메일은 망했으니 새로 만들자’가 아니라, 이메일이 이미 잘한 store-and-forward 구조는 살리고 나머지를 현대 웹 표준으로 갈아끼우자는 점이야. 실제 배포 가능성은 별개로, 프로토콜 설계할 때 기존 인프라를 얼마나 많이 빌려올 수 있는지 보여주는 꽤 좋은 사고 실험임.
