“구독 완료”라고 뜨는데 메일은 한 통도 갈 수 없었다 — 뉴스레터를 꺼 둔 이유
오늘 배울 것 화면의 ‘완료’는 내 쪽 일이 끝났다는 뜻일 뿐이라, 결과가 정말 도착했는지는 받는 쪽에서 따로 확인해야 합니다.
이 글은 이렇게 만들었습니다AI 활용 원칙
나 “뉴스레터 기능이 제대로 작동해? 아니라면 일단 빼두는 게 좋겠는데?”라고 물었고, 작동하지 않으면 빼 두기로 정했습니다. 다시 켤지는 아직 정하지 않았어요.
AI 구독자 명단·메일 설정·새 글 알림 작업·공개된 도메인 기록을 읽기만 해서 확인하고, 스위치 하나로 뉴스레터를 껐습니다. 이 글의 글감 선정·초안·그림도 AI가 맡았어요.
결과부터 — 화면은 “구독 완료”, 메일은 한 통도 갈 수 없었다
이 블로그에는 뉴스레터 구독 칸이 있었어요. 뉴스레터는 새 글 소식을 메일로 보내 주는 기능입니다. 이메일 주소를 적고 ‘구독하기’를 누르면, 초록색 상자에 “구독 완료! 감사합니다.”가 뜨게 돼 있었어요.
10월 18일에 확인해 보니, 방문자에게는 메일이 한 통도 도착할 수 없는 상태였습니다. 환영 메일도, 새 글 알림도요.
구독자: 0명
9월에 공개한 글 9편 가운데 ‘알림 보냄’ 표시가 남은 글: 0편
메일 서비스가 확인하는 도메인 인증 기록: 하나도 없음
그래서 그날 뉴스레터를 꺼 뒀습니다. 지금 구독 칸이 보이지 않는 이유예요. 다행히 구독자가 0명이었고, 나간 알림 메일도 없었습니다.
무엇이 문제였나 — 우체국에 ‘보내는 사람’ 증명이 없었다
AI는 구독자 명단이 든 데이터베이스(정리된 서랍장 같은 저장소)를 비롯해 네 곳을 읽기만 해서 확인했어요.
메일 보내기는 편지를 우체국에 맡기는 일과 비슷합니다. 사이트는 메일을 메일 발송 서비스라는 우체국에 맡겨요. 이 블로그는 Resend를 씁니다.
이 우체국은 보내는 사람 주소가 정말 이 사람 것인지부터 확인합니다. 이걸 도메인 인증이라고 해요. 도메인은 huns-dev.kr 같은 인터넷 주소입니다. 메일 서비스가 확인 문구를 주면, 그 문구를 집 문패에 붙여 두는 식이에요.
인터넷의 문패가 DNS(도메인 이름 시스템) 기록이고, 누구나 들여다볼 수 있습니다. 비유와 다른 점도 있어요. DNS 기록은 집 앞이 아니라, 도메인을 관리하는 서비스의 설정 화면에서 붙입니다.

AI는 먼저 사이트의 메일 열쇠(API 키)로 도메인 상태를 물었지만, ‘보내기 전용’ 열쇠라 거절당했어요. 그래서 공개된 DNS 기록을 직접 조회했습니다. 메일 서비스가 확인하는 기록이 하나도 없었어요. 도메인 인증이 안 돼 있었던 겁니다.
보내는 사람 주소 설정도 제 컴퓨터 설정 파일에는 없었어요. 이 항목이 비면 메일 서비스가 빌려주는 연습용 발신자로 나가는데, 그 메일은 계정 주인에게만 도착합니다. 운영 서버(사이트가 실제로 돌아가는 컴퓨터)의 설정은 AI가 볼 수 없었습니다. 그래도 결론은 같아요. 도메인 인증이 없으면 방문자의 받은편지함까지는 갈 수 없습니다.
새 글 알림 작업도 이상했습니다. 하루 한 번 자동으로 도는 예약 작업, 크론이에요. 최근 7일 안에 공개된 글이 있으면 구독자에게 메일을 보내고 그 글에 ‘알림 보냄’ 표시를 남깁니다. 구독자가 0명이어도 표시는 남기게 돼 있었어요.
그런데 9월에 공개한 글 9편에는 표시가 하나도 없었습니다. 8월 5일 이후 이 작업이 끝까지 돈 흔적이 없다는 뜻이에요. 원인은 확인하지 못했습니다. 작업 기록도 운영 서버에 있었거든요. 가장 그럴듯한 추정은 이 작업이 문을 통과할 때 내는 암호가 서버에 없어 돌려보내졌다는 것입니다.
왜 몰랐나 — 화면은 성공한 절반만 알려 줬다
‘구독하기’를 누르면 서버는 두 가지 일을 합니다. 먼저 주소를 구독자 명단에 적고, 그다음 환영 메일을 보냅니다. 코드를 간추리면 이렇게 생겼어요.
// 1) 주소를 구독자 명단에 적는다
await supabase.from("newsletter_subscribers").insert({ email });
// 2) 환영 메일을 보낸다 — 실패해도 서버 기록에 한 줄 남기고 넘어간다
await sendWelcome(email);
// 3) 메일 결과와 상관없이 "성공(201)"이라고 답한다 → 화면에 "구독 완료!"
return NextResponse.json({ success: true }, { status: 201 });
화면의 “구독 완료!”는 첫 번째 일만 성공하면 떴습니다. 환영 메일이 실패해도 서버는 똑같이 ‘성공’이라고 답했어요. 메일 실패는 운영 서버 기록에 한 줄 남을 뿐이었습니다.
이렇게 만든 것 자체가 틀린 건 아니에요. 메일이 잠깐 실패했다고 구독까지 취소할 필요는 없으니까요. 문제는 메일이 잠깐이 아니라, 방문자에게는 늘 실패하는 상태였다는 점입니다.
알림 작업도 비슷했어요. 문제를 알아챈 것도 글마다 있어야 할 표시가 비어 있는 걸 보고서였습니다. 화면만 봐서는 둘 다 보이지 않았어요.
어떻게 풀었나 — 지우지 않고 스위치로 꺼 뒀다
결정은 처음 질문 안에 있었어요. ‘작동하지 않으면 일단 빼 둔다.’ AI는 나중에 되살리기 쉽게, 코드를 지우지 않고 스위치로 껐습니다. 뉴스레터 스위치만 간추리면 이렇게 생겼어요.
// 기능 스위치 — 켜고 끄는 곳을 한 군데로 모은다.
export const features = {
newsletter: false, // 2026-10-18 끔
} as const;
이 한 줄을 화면, 구독 창구(신청을 받는 서버 쪽 입구), 알림 작업이 함께 봅니다.
화면에서 구독 칸을 숨겼습니다. 홈·바닥글·머리글·모바일 메뉴에서 구독 칸과 ‘구독’ 버튼이 사라집니다.
이렇게 보이면 성공: 컴퓨터와 휴대폰 모두, 홈·블로그·프로젝트·소개 페이지에 구독 칸이 없습니다.
구독 창구도 닫았습니다. 화면을 거치지 않고 서버에 바로 보낸 요청도 명단에 적기 전에 돌려보냅니다.
이렇게 보이면 성공: 가짜 주소로 요청해도 거절되고, 구독자는 0명 그대로입니다.
알림 작업의 문 잠금을 고쳤습니다. 예전 코드는 암호 설정이 비면 ‘undefined’(프로그램에서 ‘값 없음’을 뜻하는 말)라는 글자를 암호로 여겼어요. 앞의 추정이 맞다면 매일 오는 정식 호출은 막히고, 그 글자를 댄 낯선 요청은 통과하던 셈입니다. 이제는 설정이 비면 무조건 막습니다.
이렇게 보이면 성공: 암호 없이 부르든, ‘undefined’를 대고 부르든 거절됩니다.
구독 해지 페이지는 남겼습니다. 이미 받은 메일에 해지 링크가 있을 수 있어서입니다.
이렇게 보이면 성공: 해지 페이지가 정상으로 열립니다.
다시 켜려면
스위치가 꺼진 채로는 구독도 알림도 시험할 수 없어서, 시험용 주소(따로 띄운 미리보기 사이트)에서 먼저 켭니다.
메일 서비스에 도메인을 등록하고, 받은 확인 문구를 DNS 기록으로 붙입니다.
이렇게 보이면 성공: 메일 서비스 화면에 인증이 끝났다고 나옵니다.
운영 서버와 시험용 주소 모두에 보내는 사람 주소와 알림 작업 암호를 설정합니다.
이렇게 보이면 성공: 서버 설정에 두 값이 들어가 있습니다.
스위치를 켠 코드를 시험용 주소에 올립니다.
이렇게 보이면 성공: 시험용 주소에만 구독 칸이 보입니다.
내 주소로 직접 구독해 봅니다.
이렇게 보이면 성공: 환영 메일이 오고, 보낸 사람이 연습용이 아닌 내 도메인 주소입니다.
7일 안에 낸 글이 있을 때 알림 작업을 손으로 돌립니다.
이렇게 보이면 성공: 새 글 알림 메일이 내 받은편지함에 옵니다. 그다음 운영 사이트에 켭니다.
4번이 핵심이에요. 화면의 ‘완료’가 아니라 메일이 도착할 곳에서 확인하는 단계입니다.
‘완료’는 보낸 쪽이 하는 말이고, ‘도착’은 받는 쪽에서만 확인할 수 있습니다. 확인할 수 없는 기능이라면 고칠 때까지 꺼 두는 편이 방문자에게 정직합니다.
용어 풀이
도메인 인터넷의 집 주소입니다. 정확히는 huns-dev.kr 처럼 사이트를 찾아가는 이름이에요.
DNS(도메인 이름 시스템) 인터넷 주소마다 달린 문패입니다. 정확히는 도메인에 딸린 기록을 누구나 조회하는 체계예요.
도메인 인증 우체국에 ‘이 주소는 내 것’이라고 증명하는 일입니다. 정확히는 메일 서비스가 준 문구를 DNS 기록에 붙여, 그 이름으로 메일을 보내도 된다고 확인받는 절차예요.
API 키 프로그램용 출입증입니다. 정확히는 프로그램이 서비스에 자기를 증명하는 비밀 문자열이고, 키마다 할 수 있는 일이 정해져 있어요.
크론 매일 같은 시각에 울리는 알람 같은 것입니다. 정확히는 정해 둔 일정에 맞춰 서버가 작업을 자동으로 실행하는 기능이에요.
데이터베이스 정리된 서랍장 같은 저장소입니다. 정확히는 정보를 표 모양으로 저장하고 꺼내 쓰는 프로그램이에요.
기능 스위치 전등 스위치처럼 기능을 켜고 끄는 한 곳입니다. 정확히는 코드를 지우지 않고 설정 한 줄로 기능을 숨기거나 되살리는 장치예요.
이 글의 프로젝트
Hun's DEV정식 출시비개발자인 제가 AI로 만드는 과정을 기록하는 사이트마지막 작업 2일 전최근 30일 작업일지 6개
프로젝트 보기 →같은 주제의 다른 글
댓글
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요.