
이메일 인증 메일이 안 와요 (내 서비스가 스팸 취급을 당하다니)
회원가입 버튼을 눌렀는데 메일이 안 옵니다. 스팸함에도 없습니다. Supabase 무료 SMTP의 한계와 Resend를 연동하여 이메일 전송 성공률을 99%로 높이는 방법을 정리해봤습니다.

회원가입 버튼을 눌렀는데 메일이 안 옵니다. 스팸함에도 없습니다. Supabase 무료 SMTP의 한계와 Resend를 연동하여 이메일 전송 성공률을 99%로 높이는 방법을 정리해봤습니다.
개발 중에 코드를 수정했는데 브라우저가 반응이 없나요? 새로고침을 백만 번 하다가 지쳐서 찾아낸 HMR(Hot Module Replacement)의 원리와 고장 원인, 그리고 해결 방법을 '노가다 개발자'의 시선으로 정리했습니다.

TypeScript/JavaScript에서 절대 경로 import 설정이 안 될 때의 원인을 '지도와 택시 기사' 비유로 설명합니다. CJS vs ESM 역사적 배경과 모노레포 설정, 팀 컨벤션까지 총정리.

개발 중 CORS 에러를 프록시로 해결하는 방법과 주의사항을 정리했습니다.

HTTP는 기억상실증 환자입니다. 서버가 클라이언트를 기억하게 만드는 두 가지 방법론의 차이와 현대의 JWT 인증 방식 비교.

서비스 런칭 첫날, 친구들에게 "가입 좀 해줘!"라고 부탁했습니다. 그런데 1분 뒤 카톡이 왔습니다. "야, 가입 눌렀는데 메일이 안 오는데?"
설마 싶어서 저도 다시 가입해봤습니다. 안 옵니다.
스팸 메일함을 뒤져봤습니다. 거기에도 없습니다.
Supabase 대시보드 로그를 봤습니다. Auth: Email sent라고 뜹니다.
이 순간, 저는 이메일 전송이라는 게 그냥 sendMail() 함수 하나 호출하면 끝나는 간단한 게 아니라는 걸 깨달았습니다.
내 소중한 인증 메일이 인터넷 망망대해 어딘가에서 '스팸'으로 찍혀 산화해버린 것입니다.
저는 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, 어제 이상한 도박 사이트 홍보 메일 보내던 곳이네? 차단."
제 서비스 이름으로 보낸 메일이 도매금으로 차단당한 것입니다.
이 상황을 친구가 "공용 우편함 vs 전용 배달부"로 비유해 줬을 때 이해가 확 됐습니다.
"아, 내 서비스가 '듣보잡' 취급을 안 당하려면 전용 배달부를 고용해야 하는구나." 이걸 깨닫고 바로 Custom SMTP 세팅을 시작했습니다.
AWS SES는 설정이 너무 복잡해서 포기했고, 개발자 친화적인 Resend를 선택했습니다. (하루 100건 무료면 초기엔 충분합니다)
Resend에 가입하고 제 도메인(codemapo.com)을 등록했습니다.
그러자 DNS 레코드 3개를 주더군요.
이걸 DNS 설정(Vercel, Cloudflare 등)에 복사해 넣어야 합니다. 이걸 안 하면? 전용 배달부에게 정장을 입혀놓고 신분증을 안 준 꼴입니다. 여전히 스팸 취급 당합니다.
Supabase 대시보드 -> Project Settings -> Auth -> SMTP Settings로 갑니다.
Resend를 켜는 게 아니라, Custom SMTP를 켜야 합니다.
noreply@codemapo.com (내 도메인 주소 필수! gmail.com 쓰면 안 됨)smtp.resend.com465 (SSL)resend설정 저장 후 다시 가입 메일을 보내봤습니다. 1초도 안 돼서 지메일 알림이 울렸습니다. "띵동!" 스팸함이 아니라 받은편지함에 당당히 꽂혔습니다. 이 쾌감이란!
이메일이 스팸으로 안 빠지려면 이 3가지 개념을 알아야 합니다.
1.2.3.4야. 이거 너네 직원 맞아?"라고 DNS에 물어봅니다. DNS에 v=spf1 include:resend.com이라고 되어 있으면 "어, Resend는 우리 직원 맞아"라고 확인해주는 겁니다.none(지켜보기만 함)으로 하다가 안정되면 quarantine으로 올립니다.초기 스타트업에게 가장 적합한 서비스는 무엇일까요?
| 서비스 | 무료 등급 | 특징 | 추천 대상 |
|---|---|---|---|
| Resend | 월 3,000건 | 개발자 경험(DX) 최고, React Email 제공 | 강력 추천 (초기 스타트업) |
| AWS SES | 월 62,000건 | 압도적인 가성비, But 설정이 지옥 | AWS 고수, 대규모 전송 |
| SendGrid | 하루 100건 | 전통의 강자, 기능 많음, UI가 올드함 | 이미 쓰고 있다면 유지 |
| Mailgun | 3개월 5,000건 | 개발자 친화적이었으나 유료화됨 | 비추천 |
저는 Resend를 강력 추천합니다. Vercel 팀 출신들이 만들어서 문서가 깔끔하고, React Email이라는 라이브러리로 이메일 HTML을 리액트 컴포넌트 짜듯이 짤 수 있습니다.
Custom SMTP를 쓴다고 만사가 해결되는 건 아닙니다.
도메인을 새로 샀다면(codemapo.com), 이 도메인은 "신생아" 상태입니다.
신생아가 갑자기 하루에 1만 통씩 메일을 보내면? 구글은 "스팸봇이다!"라고 차단합니다.
이메일 웜업 전략:
Unsubscribe 링크를 잘 보이게 넣으세요.로컬(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', // 명시적으로 지정
},
});