이메일 인증 메일이 안 와요 (내 서비스가 스팸 취급을 당하다니)
1. "가입했는데 메일이 안 와요..."
서비스 런칭 첫날, 친구들에게 "가입 좀 해줘!"라고 부탁했습니다. 그런데 1분 뒤 카톡이 왔습니다. "야, 가입 눌렀는데 메일이 안 오는데?"
설마 싶어서 저도 다시 가입해봤습니다. 안 옵니다.
스팸 메일함을 뒤져봤습니다. 거기에도 없습니다.
Supabase 대시보드 로그를 봤습니다. Auth: Email sent라고 뜹니다.
"보냈다는데 왜 안 온 거야?"
이 순간, 저는 이메일 전송이라는 게 그냥 sendMail() 함수 하나 호출하면 끝나는 간단한 게 아니라는 걸 깨달았습니다.
내 소중한 인증 메일이 인터넷 망망대해 어딘가에서 '스팸'으로 찍혀 산화해버린 것입니다.
2. 처음엔 뭐가 이해가 안 갔나? (Supabase 배신감)
저는 Supabase가 "Backend-as-a-Service"니까, 이메일 전송도 완벽하게 알아서 해줄 줄 알았습니다. Docs에도 "Email Auth는 기본으로 켜져 있습니다"라고 되어 있었으니까요.
하지만 제가 간과한 문구가 있었습니다.
"Supabase provides a default SMTP for testing purposes only. Rate limits apply."
Supabase가 기본 제공하는 이메일 서버는 "테스트용"입니다. 전 세계 수만 명의 Supabase 무료 유저들이 이 하나의 서버를 공유합니다. 누군가가 이 서버로 스팸을 보내면, 이 서버의 IP 평판(Reputation)이 나락으로 떨어집니다.
결국 네이버, 지메일, 아웃룩 같은 수신 측 서버들은 Supabase 기본 서버에서 오는 메일을 아주 깐깐하게 봅니다. "어? 이 IP, 어제 이상한 도박 사이트 홍보 메일 보내던 곳이네? 차단."
제 서비스 이름으로 보낸 메일이 도매금으로 차단당한 것입니다.
3. 어떤 포인트에서 이해가 됐나? (우편배달부 비유)
이 상황을 친구가 "공용 우편함 vs 전용 배달부"로 비유해 줬을 때 이해가 확 됐습니다.
- Supabase 기본 SMTP: 동네에 하나 있는 무료 공용 우편함입니다. 누구나 쓸 수 있다 보니, 누군가 쓰레기를 잔뜩 넣기도 하고, 폭탄을 넣기도 합니다. 우체국(Gmail)은 이 우편함에서 오는 편지는 일단 의심하고 봅니다. 심지어 하루에 보낼 수 있는 편지 수 제한(Rate Limit)도 빡빡합니다 (시간당 3통인가 그렇습니다).
- Custom SMTP (Resend, AWS SES): 돈 내고 고용한 정장 입은 전용 배달부입니다. 신원이 확실하고(도메인 인증), 옷차림도 깔끔해서(DKIM/SPF), 우체국이 프리패스로 통과시켜 줍니다.
"아, 내 서비스가 '듣보잡' 취급을 안 당하려면 전용 배달부를 고용해야 하는구나." 이걸 깨닫고 바로 Custom SMTP 세팅을 시작했습니다.
4. 해결 과정 - Resend 연동하기
AWS SES는 설정이 너무 복잡해서 포기했고, 개발자 친화적인 Resend를 선택했습니다. (하루 100건 무료면 초기엔 충분합니다)
1단계 - 도메인 인증 (가장 중요)
Resend에 가입하고 제 도메인(codemapo.com)을 등록했습니다.
그러자 DNS 레코드 3개를 주더군요.
- DKIM (DomainKeys Identified Mail): "이 메일은 진짜 codemapo.com에서 보낸 거 맞음"이라는 디지털 서명.
- SPF (Sender Policy Framework): "Resend 서버는 내 도메인을 대신해 메일을 보낼 자격이 있음".
이걸 DNS 설정(Vercel, Cloudflare 등)에 복사해 넣어야 합니다. 이걸 안 하면? 전용 배달부에게 정장을 입혀놓고 신분증을 안 준 꼴입니다. 여전히 스팸 취급 당합니다.
2단계 - Supabase 연동
Supabase 대시보드 -> Project Settings -> Auth -> SMTP Settings로 갑니다.
Resend를 켜는 게 아니라, Custom SMTP를 켜야 합니다.
- Sender Email:
noreply@codemapo.com(내 도메인 주소 필수!gmail.com쓰면 안 됨) - Host:
smtp.resend.com - Port:
465(SSL) - User:
resend - Pass: (Resend에서 발급받은 API Key)
3단계 - 테스트
설정 저장 후 다시 가입 메일을 보내봤습니다. 1초도 안 돼서 지메일 알림이 울렸습니다. "띵동!" 스팸함이 아니라 받은편지함에 당당히 꽂혔습니다. 이 쾌감이란!
5. 깊이 파고들기 - 이메일 전송의 3대장 (SPF, DKIM, DMARC)
이메일이 스팸으로 안 빠지려면 이 3가지 개념을 알아야 합니다.
-
SPF (Sender Policy Framework)
- 의미: "우리 회사 사원증 가진 사람 명단"
- 작동: 수신 측에서 "너네 도메인으로 메일 왔다는데, 발송 IP가
1.2.3.4야. 이거 너네 직원 맞아?"라고 DNS에 물어봅니다. DNS에v=spf1 include:resend.com이라고 되어 있으면 "어, Resend는 우리 직원 맞아"라고 확인해주는 겁니다.
-
DKIM (DomainKeys Identified Mail)
- 의미: "편지 봉투에 찍힌 인장(Sealing)"
- 작동: 메일 헤더에 암호화된 서명을 붙입니다. 수신 측은 퍼블릭 키로 이걸 해독해서 "오, 배달 중에 내용이 조작되지 않았군"이라고 검증합니다.
-
DMARC
- 의미: "가짜가 나타나면 어떻게 할까요?" (지침서)
- 작동: SPF나 DKIM 검사에 실패했을 때, "그냥 스팸함에 넣어주세요(quarantine)" 또는 "아예 반송시켜주세요(reject)"라고 지시하는 정책입니다. 초기엔
none(지켜보기만 함)으로 하다가 안정되면quarantine으로 올립니다.
6. Custom SMTP 서비스 비교 (Resend vs SES vs SendGrid) 제대로 파보기
초기 스타트업에게 가장 적합한 서비스는 무엇일까요?
| 서비스 | 무료 등급 | 특징 | 추천 대상 |
|---|---|---|---|
| Resend | 월 3,000건 | 개발자 경험(DX) 최고, React Email 제공 | 강력 추천 (초기 스타트업) |
| AWS SES | 월 62,000건 | 압도적인 가성비, But 설정이 지옥 | AWS 고수, 대규모 전송 |
| SendGrid | 하루 100건 | 전통의 강자, 기능 많음, UI가 올드함 | 이미 쓰고 있다면 유지 |
| Mailgun | 3개월 5,000건 | 개발자 친화적이었으나 유료화됨 | 비추천 |
저는 Resend를 강력 추천합니다. Vercel 팀 출신들이 만들어서 문서가 깔끔하고, React Email이라는 라이브러리로 이메일 HTML을 리액트 컴포넌트 짜듯이 짤 수 있습니다.
7. 이메일 웜업 (Warm-up)과 평판 관리 제대로 이해하기
Custom SMTP를 쓴다고 만사가 해결되는 건 아닙니다.
도메인을 새로 샀다면(codemapo.com), 이 도메인은 "신생아" 상태입니다.
신생아가 갑자기 하루에 1만 통씩 메일을 보내면? 구글은 "스팸봇이다!"라고 차단합니다.
이메일 웜업 전략:
- 점진적 증가: 첫날은 50통, 둘째 날은 100통, 셋째 날은 200통... 이렇게 서서히 늘려야 합니다.
- 반송률 관리 (Bounce Rate): 존재하지 않는 이메일로 계속 보내면 평판이 깎입니다. 이메일 유효성 검사를 꼭 하세요.
- 스팸 신고율: 사용자가 "스팸 신고" 버튼을 누르면 치명적입니다.
Unsubscribe링크를 잘 보이게 넣으세요.
8. Tip: 로컬 개발 환경에서의 함정
로컬(localhost:3000)에서 테스트할 때 주의할 점이 있습니다.
이메일 링크(Confirm your email)를 클릭하면 Supabase는 사용자를 Site URL로 리다이렉트 시킵니다.
만약 Site URL이 프로덕션(https://codemapo.com)으로 되어 있으면, 로컬에서 가입했는데 인증 후에는 실제 사이트로 날아가서 로그인이 안 된 것처럼 보일 수 있습니다.
해결책:
Supabase Auth 설정의 Redirect URLs에 http://localhost:3000/**를 꼭 추가하세요.
그리고 클라이언트 코드에서 signUp 할 때 emailRedirectTo 옵션을 명시해야 합니다.
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: 'http://localhost:3000/auth/callback', // 명시적으로 지정
},
});
9. 한 줄 요약
Supabase 기본 이메일은 장난감이다. 서비스 출시를 생각한다면 1일 차부터 Resend 같은 Custom SMTP를 연동하고, SPF/DKIM 설정으로 '신분증'을 챙겨라.