Skip to content

필사 모드: DMARC가 11년 만에 표준이 되다 — RFC 9989의 트리 워크, pct 폐지, 그리고 p=reject 경고

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

들어가며 — 모두가 쓰는데 표준은 아니었던 프로토콜

이상한 사실 하나에서 시작합니다. Gmail과 Yahoo가 2024년부터 대량 발신자에게 DMARC를 사실상 강제해 왔고, 은행과 정부 기관이 도입 현황을 감사받고, 이메일 보안 스타트업 생태계 하나가 그 위에 세워져 있는데 — 정작 DMARC를 정의한 RFC 7489IETF 표준이 아니었습니다. 2015년 3월에 나온 이 문서는 IETF 워킹그룹 합의를 거치지 않은 Independent Submission이고, 분류도 Informational입니다. 문서 지위만 보면 "누군가 이렇게 하고 있다더라"를 기록한 문서 위에서 전 세계 이메일 인증이 11년을 굴러온 셈입니다.

2026년 5월, 이 상태가 끝났습니다. IETF DMARC 워킹그룹의 소위 DMARCbis 작업이 RFC 9989로 발행되면서 DMARC는 Standards Track 문서가 됐고, RFC 7489와 (PSD DMARC를 다뤘던 실험 문서) RFC 9091을 폐기(obsolete)했습니다. datatracker 기준으로 드래프트 리비전 41번, 본문 83쪽짜리 결과물입니다.

"표준 됐다니 축하할 일이네" 하고 넘기기에는, 이번 개정이 실제로 프로토콜의 동작을 바꿉니다. 조직 도메인을 찾는 알고리즘이 통째로 교체됐고, 태그 몇 개가 사라지고 생겼으며, 무엇보다 그동안 커뮤니티의 암묵지였던 운영 원칙들이 MUST와 SHOULD NOT의 언어로 처음 못 박혔습니다. 하나씩 보겠습니다. (SMTP와 DNS 자체가 낯설다면 DNS와 이메일 프로토콜 기초 정리를 먼저 봐도 좋습니다.)

무엇이 나왔나 — 세 문서로 쪼개진 DMARC

RFC 7489 하나였던 스펙이 세 문서로 분리됐습니다. 전부 2026년 5월에 함께 발행됐고, 전부 Standards Track입니다.

  • RFC 9989 — DMARC 본체. 정책 레코드 문법, 정렬(alignment) 평가, 정책 발견. RFC 7489와 RFC 9091을 폐기합니다. 편집자는 Valimail의 T. Herr와 Standcore의 J. Levine.
  • RFC 9990 — 집계 리포트(aggregate reporting). XML 리포트 포맷과 전송 방식이 이쪽으로 분리됐습니다.
  • RFC 9991 — 실패 리포트(failure reporting). RFC 6591을 갱신합니다.

리포트 스펙이 분리된 것은 단순한 문서 정리가 아니라 앞으로 리포트 포맷을 본체와 독립적으로 진화시키겠다는 구조 변경입니다. 참고로 RFC 7489에 11년간 쌓인 정오표(errata) 15건이 각각 어떻게 처리됐는지도 RFC 9989 부록 C.9에 항목별로 기록돼 있습니다.

안 바뀐 것부터 — 당신의 레코드는 그대로 유효하다

실무자에게 가장 중요한 사실은 이것입니다. 버전 문자열이 그대로입니다. RFC 9989의 v 태그 정의는 여전히 유일한 유효값으로 v=DMARC1을 명시합니다(대소문자 구분, 레코드의 첫 태그여야 함). 한때 커뮤니티에서 돌던 "DMARC2가 온다"는 이야기는 실현되지 않았습니다. 지금 DNS에 있는 레코드는 새 스펙에서도 그대로 유효하고, 마이그레이션 이벤트 같은 것은 없습니다.

이게 가능한 이유는 스펙의 확장 규칙에 있습니다 — 알 수 없는 태그는 무시해야 하므로(MUST), 새 태그 추가는 버전 승급을 요구하지 않습니다. 뒤에서 볼 t, np, psd 태그가 전부 v=DMARC1 안에서 추가된 이유입니다. 반대로 pct처럼 폐지된 태그는 신형 수신자에게 "알 수 없는 태그"가 되어 조용히 무시됩니다.

가장 큰 변화 — PSL이 빠지고 DNS 트리 워크가 들어왔다

RFC 7489에서 조직 도메인(Organizational Domain)을 판별하는 방법은 Public Suffix List(PSL)였습니다. 이 방식의 문제는 RFC 7489 스스로도 알고 있었습니다 — 어떤 PSL을 쓰라고 강제하지 않았고(publicsuffix.org를 제안만 함), 갱신 주기 지침도 없었으며, 수신자마다 다른 PSL을 쓰면 상호운용성 문제가 생긴다는 것을 인정하면서 "더 신뢰할 수 있는 방법이 생기면 교체돼야 한다"고 적어 뒀습니다. IETF 바깥에서 자원봉사로 관리되는 목록 파일이 전 세계 이메일 정책 판별의 기준점이라는 것은 늘 불편한 의존성이었습니다.

RFC 9989는 이것을 DNS 트리 워크로 교체했습니다. 외부 목록 대신, DNS 계층을 직접 걸어 올라가며 DMARC 레코드를 찾는 방식입니다.

동작은 이렇습니다. 먼저 _dmarc.를 붙인 발신자 도메인(RFC5322.From의 도메인)에서 TXT 레코드를 조회하고, 없으면 라벨을 하나씩 벗겨 가며 위로 올라갑니다. DoS 방지를 위해 쿼리 수에 상한이 있습니다 — 최대 8쿼리. 라벨이 8개를 넘는 도메인은 중간을 건너뛰고 오른쪽 7개 라벨 지점으로 점프합니다. RFC의 예시를 그대로 옮기면, 라벨 13개짜리 도메인의 전체 트리 워크는 다음 8번의 조회로 끝납니다.

발신 도메인: a.b.c.d.e.f.g.h.i.j.mail.example.com

1. _dmarc.a.b.c.d.e.f.g.h.i.j.mail.example.com   (원래 도메인)
2. _dmarc.g.h.i.j.mail.example.com               (오른쪽 7개 라벨로 점프)
3. _dmarc.h.i.j.mail.example.com
4. _dmarc.i.j.mail.example.com
5. _dmarc.j.mail.example.com
6. _dmarc.mail.example.com
7. _dmarc.example.com
8. _dmarc.com

상한을 8로 정한 근거도 문서에 있습니다 — 발행 시점 관측 데이터상 실사용 발신 도메인은 라벨 7개까지 존재했고, 여유분 하나를 더한 값입니다.

걸어 올라가며 찾은 레코드들 중에서 조직 도메인을 고르는 규칙은 새 psd 태그와 엮여 있습니다. 요약하면 이렇습니다.

  • 유효한 레코드에 psd=n이 있으면 그 도메인이 조직 도메인. 끝.
  • 걷다가 만난 레코드에 psd=y가 있으면(공용 접미사 도메인이라는 선언) 그 한 라벨 아래 도메인이 조직 도메인.
  • 둘 다 없으면, 유효한 레코드가 발견된 이름 중 라벨 수가 가장 적은 것이 조직 도메인.

이 설계 덕에 RFC 9091이 실험적으로 시도했던 PSD DMARC(공용 접미사 수준의 정책, 예컨대 국가 TLD 운영자가 산하 비존재 도메인 사칭을 막는 것)가 별도 레지스트리 없이 본체에 흡수됐습니다. RFC 9989는 9091에 대해 "작성된 대로 구현되지 않았다"는 실험 결과를 담담히 기록하고 폐기 처리합니다.

전환기의 함정도 스펙에 명시돼 있습니다. RFC 7489 구현(PSL 기반) 수신자와 RFC 9989 구현(트리 워크) 수신자는 같은 메일에 대해 다른 조직 도메인, 따라서 다른 정책과 다른 정렬 판정에 도달할 수 있습니다. 스펙이 제시하는 회피책은 두 가지입니다 — 실제로 발신에 쓰는 모든 도메인에 명시적 DMARC 레코드를 게시할 것, 그리고 strict 정렬을 쓸 것. 발신 도메인 자체에 레코드가 있으면 어느 쪽 수신자든 걷기 전에 첫 쿼리에서 끝나므로 알고리즘 차이가 드러나지 않습니다.

태그 정리 — pct는 왜 죽었나

이번 개정에서 태그 세 개가 추가되고(np, psd, t) 세 개가 제거됐습니다(pct, rf, ri).

pct 폐지의 사연이 재미있습니다. 원래 의도는 "정책을 메일의 N%에만 적용해 달라"는 점진 전환 장치였는데, RFC 9989의 부록 A.6이 기록한 운영 경험은 이렇습니다 — 0과 100 말고는 정확히 적용되는 일이 드물었고, 구현마다 편차가 컸습니다. 그런데 그중 pct=0만은 전혀 다른 용도로 살아남았습니다. 일부 중개자(메일링 리스트 등)와 메일박스 제공자들이 pct=0을 "이 도메인이 곧 정책을 켤 예정"이라는 신호로 읽고, DMARC 실패를 피하도록 From 헤더를 재작성하는 트리거로 쓰기 시작한 겁니다. 도메인 소유자 입장에서는 pct=0을 켜기 전후의 집계 리포트를 비교하면 "From을 재작성하지 않는 중개자를 거치는 트래픽이 얼마나 되는지"를 추정할 수 있었고, 이는 enforcement로 넘어가도 되는지 판단하는 데 실제로 유용했습니다.

그래서 RFC 9989는 유효값이 사실상 둘뿐인 백분율 태그를 유지하는 대신, 그 살아남은 기능만 추려 t 태그(testing)로 대체했습니다. t=ypct=0에, 기본값인 t=npct=100에 대응합니다. t=y의 의미는 명확히 정의돼 있습니다 — 검증자에게 선언된 정책을 그대로 적용하지 말고 한 단계 낮춰 적용해 달라는 요청입니다. p=rejectt=y면 quarantine처럼, p=quarantinet=y면 none처럼 다뤄지고, 리포트 생성에는 영향을 주지 않습니다.

np 태그는 RFC 9091에서 수입된 것으로, 존재하지 않는 서브도메인(NXDOMAIN, RFC 8020 의미론 기준)에 대한 정책입니다. 폴백 순서는 np가 없으면 sp, sp도 없으면 p입니다. 실무적으로 이것은 서브도메인 사칭 방어에 바로 쓸 수 있는 도구입니다 — 실존 서브도메인은 sp=none으로 관찰하면서, 아예 존재하지 않는 이름의 사칭만 np=reject로 즉시 차단하는 조합이 가능해집니다.

_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; t=y; sp=none; np=reject; rua=mailto:dmarc-rpt@example.com"

rf(실패 리포트 포맷)와 ri(리포트 간격) 태그는 제거됐고, 리포트 URI에 최대 크기를 지정하는 문법도 사라졌습니다(구형 문법은 무시 대상). 리포트 관련 세부는 이제 RFC 9990/9991의 영역입니다.

표준이 처음으로 못 박은 운영 원칙들

제 생각에 이번 개정의 진짜 무게는 알고리즘보다 여기에 있습니다. 지난 10년간 "다들 그렇게 하는" 암묵지였던 것들이 처음으로 규범 언어(MUST/SHOULD)가 됐습니다. RFC 9989의 7.4절과 8절에서 발췌합니다.

첫째, p=reject 도메인은 SPF에만 의존해서는 안 됩니다(MUST NOT). DKIM 서명은 의무입니다(MUST). 이유는 포워딩입니다. 졸업생 메일 릴레이나 역할 기반 별칭처럼 메일을 중계하는 흐름에서 SPF는 거의 확실히 깨집니다 — 최종 수신자가 보는 발신 IP는 중계자의 것이니까요. 반면 DKIM 서명은 본문이 변형되지 않는 한 중계를 살아남습니다. SPF만으로 DMARC를 통과시키던 도메인이 p=reject를 켜면, 정상적인 중계 메일이 조용히 버려집니다.

둘째, 일반 사용자가 메일을 쓰는 도메인은 p=reject를 게시하지 말아야 합니다(SHOULD NOT). 직원·구성원이 인터넷 메일링 리스트에 글을 쓸 수 있는 도메인이라면, p=reject는 리스트와 구독자들에게 실질적 피해를 줍니다. 꼭 가려면 스펙이 절차까지 정해 줍니다 — p=none으로 최소 한 달, 이어서 p=quarantine으로 같은 기간을 두고 집계 리포트의 처분 결과를 비교한 뒤에 판단하라는 것입니다. 은행처럼 기계 발송 트랜잭션 메일만 나가는 도메인과, 사람이 자유롭게 메일을 쓰는 도메인은 다른 정책이 맞다는 이야기이기도 합니다.

셋째, 수신자는 p=reject라는 이유만으로 메일을 거부해서는 안 됩니다(MUST NOT). 다른 근거 분석 없이 DMARC 실패만 있다면 p=quarantine처럼 다루라고(MUST) 명시합니다. 발신 도메인의 정책 선언은 수신자에게 명령이 아니라 참고 입력이라는 것 — Gmail 같은 대형 수신자들이 실제로 해 온 방식이 표준 문장이 된 셈입니다.

그 외에 "완전한 DMARC 참여"의 체크리스트를 정의한 8절도 볼만합니다. 도메인 소유자는 정렬된 SPF 정렬된 DKIM을 둘 다 갖추고, 집계 리포트 수신함을 만들어 실제로 분석하고, 발신 도메인과 조직 도메인 양쪽에 레코드를 게시해야 합니다. 수신자는 집계 리포트를 최소 하루 단위로 보내야 합니다(SHOULD).

RFC가 스스로 인정하는 것 — 메일링 리스트 문제는 못 풀었다

7.4절에는 표준 문서에서 보기 드문 수준의 솔직한 문단이 있습니다. 요지를 옮기면 — 위의 조언에도 불구하고, 간접 메일 흐름에 완화 조치를 적용하는 수신자는 현실에서 거의 없고, 자기 사용자들의 간접 메일에 미칠 영향을 고려하는 조직도 거의 없으며, 이 문서의 어떤 조언도 그 현실을 바꿀 것 같지 않다는 것입니다. 그 결과 From을 수정하지 않고 메일링 리스트를 거친 메일은 p=reject 때문에 빈번히 거부되고 있고, 지난 10년간 리스트 소프트웨어들은 전부 From 재작성 우회책을 채택해 이제 그것이 기정사실이 됐다고 기록합니다.

그럼 From 재작성 없이 리스트를 살리는 기술은 어디까지 왔나. RFC 9989가 직접 거명하는 후보가 ARC(Authenticated Received Chain, RFC 8617)인데, 평가는 냉정합니다 — "none of the methods have become widely used" (아직 어떤 방법도 널리 쓰이지 못했다). 실제로 RFC 8617은 2019년 이후 지금도 Experimental 지위 그대로입니다. 널리 채택되는 날이 오면 그때 문서를 갱신하겠다는 문장으로 이 절은 끝납니다. 요컨대 DMARC의 가장 오래된 부작용은 표준화 이후에도 열린 문제로 남아 있고, 표준 스스로가 그렇게 말합니다.

SPF -all의 사각지대 — 리포트에 안 잡히는 거부

7.1절이 지적하는 운영 함정 하나는 따로 언급할 가치가 있습니다. SPF는 SMTP 트랜잭션 초반, 본문 전송 전에 평가될 수 있습니다. 그래서 SPF 레코드를 하드 페일(-all)로 끝내는 도메인의 메일은 DMARC 처리가 시작되기도 전에 거부될 수 있습니다. 문제는 두 겹입니다.

  • 정렬된 DKIM 서명이 있어서 DMARC로는 통과했을 메일이, SPF 단계에서 먼저 잘려 나갈 수 있습니다.
  • 이렇게 DATA 단계 이전에 거부된 메일은 From 도메인이 드러나기 전이므로 집계 리포트에 아예 나타나지 않습니다.

DMARC 집계 리포트로 발신 현황을 관제하고 있다면, -all로 인한 조기 거부는 그 관제망의 바깥에서 일어난다는 뜻입니다. "리포트가 깨끗하다"와 "메일이 다 들어가고 있다"가 다른 명제가 되는 지점이라, -all을 쓰는 도메인은 이 사각지대를 알고 있어야 합니다. 소프트 페일(~all)과 DKIM 정렬 확보 위에서 DMARC 정책으로 거부를 통제하는 쪽이 가시성 면에서는 낫습니다.

구현은 어디까지 왔나

발행 두 달째인 지금은 명백히 전환기입니다. 확인 가능한 지점 몇 개만 짚습니다.

  • OpenDMARC는 2026-05-27에 RFC 9989/9990/9991 대비 격차 분석 이슈를 열어 추적 중이고, 조직 도메인 탐색을 구형 7489 워크·PSL·9989 트리 워크·자동 중에서 고르게 하는 walk_mode 선택 기능 PR이 2026-06-21에 develop 브랜치에 병합됐습니다. 즉 참조급 오픈소스 구현에서도 트리 워크는 이제 막 개발 브랜치에 들어간 단계입니다.
  • 네덜란드 정부 계열 진단 도구 Internet.nlPSL을 트리 워크로 교체하는 이슈를 열어 둔 상태입니다.
  • Gmail의 발신자 가이드라인은 이 글 작성 시점 기준 여전히 2024년 체제 그대로입니다 — 하루 5,000통 이상을 Gmail 계정으로 보내는 발신자는 SPF와 DKIM을 둘 다 설정하고 DMARC를 게시해야 하며, 정책은 none이어도 됩니다(공식 문서). 페이지 어디에도 RFC 9989 언급은 없습니다.

대형 메일박스 제공자들이 내부적으로 트리 워크로 전환했는지는 공개된 자료가 없어서 여기서 단정하지 않겠습니다. 분명한 것은, 당분간 인터넷에는 PSL 기준 수신자와 트리 워크 기준 수신자가 공존한다는 사실이고, 그래서 위에서 말한 회피책 — 발신에 쓰는 모든 도메인에 명시적 레코드 게시 — 이 전환기의 실질적 방어가 됩니다.

실무 체크리스트 — 지금 할 일과 안 해도 되는 일

안 해도 되는 일부터. 레코드의 v=DMARC1은 그대로 둡니다. DMARC2로의 마이그레이션 같은 것은 존재하지 않습니다. 기존 배포는 계속 동작합니다.

할 일은 이 정도입니다.

  1. DKIM 정렬을 먼저 확보하세요. p=reject이거나 그리로 갈 계획이라면, 모든 발신 경로가 정렬된 DKIM 서명을 달고 있는지부터 확인해야 합니다. SPF 단독 통과에 기대는 p=reject는 이제 명시적인 표준 위반(MUST NOT)입니다.
  2. 레코드에서 pct, rf, ri를 정리하세요. 신형 수신자는 어차피 무시하지만, 구형 수신자는 pct를 계속 해석하므로 두 부류가 다르게 동작하는 원인이 됩니다. 점진 전환 신호가 필요하면 t=y로 옮기세요 — 단, 구형 수신자는 반대로 t를 모른다는 것까지 감안해야 합니다.
  3. 실제 발신에 쓰는 모든 도메인에 명시적 DMARC 레코드를 게시하세요. PSL 수신자와 트리 워크 수신자가 다른 답에 도달할 여지를 원천 차단하는, 스펙이 직접 권하는 방법입니다.
  4. 존재하지 않는 서브도메인 사칭이 걱정이라면 np를 쓰세요. 실존 서브도메인 정책(sp)과 분리해서, NXDOMAIN인 이름만 강하게 막을 수 있습니다.
  5. -all을 쓰고 있다면 집계 리포트의 사각지대를 인지하세요. DATA 이전에 거부된 메일은 리포트에 남지 않습니다.
  6. 일반 사용자 도메인의 p=reject는 다시 생각하세요. 표준이 정한 절차 — none 최소 한 달, quarantine 같은 기간, 리포트 비교 — 를 거치지 않은 reject 전환은 이제 근거 문서를 들이밀 수 있는 반대 사유가 됩니다.

마치며

프로토콜 비트만 보면 이번 표준화는 조용한 개정입니다 — 레코드는 그대로고, 통과/실패 판정 로직도 대부분 그대로입니다. 하지만 세 가지는 실질적으로 달라졌습니다. 조직 도메인 판별이 외부 목록(PSL) 의존에서 DNS 자체 탐색(트리 워크, 최대 8쿼리)으로 바뀌었고, 점진 전환 장치가 현실에서 검증된 형태(t 태그)로 교체됐으며, 운영 원칙들이 처음으로 인용 가능한 규범 문장이 됐습니다 — p=reject에는 DKIM이 의무다, 사용자 도메인의 reject는 하지 마라, 수신자는 reject 선언만으로 버리지 마라.

그리고 이 표준의 가장 미더운 부분은 자기 한계를 문서 안에 적어 뒀다는 점입니다. 메일링 리스트 문제는 여전히 미해결이고, ARC는 여전히 실험이며, 수신자들이 조언을 따르지 않으리라는 것까지 표준이 스스로 예측합니다. 11년 걸린 표준화의 결론이 "완성"이 아니라 "현실의 정직한 기록"이라는 것 — 이메일이라는 40년 된 시스템에는 그게 오히려 어울리는 결말 같습니다.

참고 자료

현재 단락 (1/71)

이상한 사실 하나에서 시작합니다. Gmail과 Yahoo가 2024년부터 대량 발신자에게 DMARC를 사실상 강제해 왔고, 은행과 정부 기관이 도입 현황을 감사받고, 이메일 보안 ...

작성 글자: 0원문 글자: 9,014작성 단락: 0/71