이 문서는 이슈 #50의 백엔드 코드를 실제 Supabase 프로젝트와 Gmail 발송 계정에 연결하는 순서다. 비밀값은 GitHub, 문서, 채팅, 프론트엔드 환경 변수에 넣지 않는다.
- 알림 발송 전용 Gmail 계정을 만든다. 개인 메일 계정은 사용하지 않는다.
- Google Cloud Console에서 프로젝트를 만들고 Gmail API를 활성화한다.
- OAuth 동의 화면을 설정한다.
- OAuth Client ID와 Client Secret을 만든다.
- 전용 Gmail 계정으로
https://www.googleapis.com/auth/gmail.send범위를 한 번 승인하고, 오프라인 발송에 사용할 refresh token을 발급한다. - 테스트 상태의 OAuth 앱은 refresh token 만료 제한이 생길 수 있으므로 실제 운영 전 Production 전환과 Google 검증 필요 여부를 확인한다.
현재 탐라모아의 Google 로그인 Client ID와 Gmail 발송용 OAuth Client는 역할이 다르다. 로그인 사용자가 Gmail 발송 권한을 승인하는 것이 아니라 전용 발송 계정 한 개만 승인한다.
Supabase CLI로 연결된 원격 DB에 새 마이그레이션을 순서대로 반영한다.
supabase db push --linked반영 후 확인할 것:
user_settings.email_enabled가 기본값false로 생성됨bookmarks에email_sent_day_markers등 이메일 상태 필드가 생성됨claim_bookmark_email_notification,mark_bookmark_email_notification_sent,mark_bookmark_email_notification_failed함수가 생성됨- Vault 준비 후
20260720091000_schedule_deadline_email_function.sql을 적용하면send-deadline-emails-dailyCron이 생성됨 20260720092000_grant_email_worker_access.sql로 서비스 역할에 북마크·설정 읽기 권한만 부여됨
Supabase Dashboard → Edge Functions → Secrets에서 다음 값을 등록한다.
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET
GOOGLE_REFRESH_TOKEN
GMAIL_SENDER_EMAIL
EMAIL_CRON_SECRET
EMAIL_CRON_SECRET은 다른 곳에서 사용하지 않는 충분히 긴 임의 문자열로 만든다. SUPABASE_URL과 Supabase secret/service role key는 배포된 Edge Function에 기본 제공되므로 별도로 코드에 넣지 않는다.
Supabase CLI에서 프로젝트를 연결한 뒤 배포한다.
supabase functions deploy send-deadline-emailssupabase/config.toml에서 플랫폼 JWT 검사는 끄지만, 함수 자체가 x-cron-secret을 비교해 허용된 Cron 요청만 처리한다.
Supabase Dashboard의 Edge Function 테스트 기능 또는 HTTP 요청으로 POST 호출한다.
POST https://프로젝트주소.supabase.co/functions/v1/send-deadline-emails
x-cron-secret: Supabase Secrets에 등록한 EMAIL_CRON_SECRET
정상 응답 예:
{
"candidates": 1,
"sent": 1,
"failed": 0,
"skipped": 0,
"deferred": 0
}잘못된 시크릿이면 HTTP 401이어야 한다.
개인 Gmail의 일일 발송 제한을 보호하기 위해 한 번 실행할 때 마감이 가까운 순서로 최대 450통을 처리한다. deferred가 1 이상이면 처리하지 못한 후보가 있다는 뜻이므로 다음 실행 결과와 Gmail 발송 한도를 확인한다.
프로젝트 Vault에 아래 두 값을 저장한다. 실제 시크릿은 문서나 SQL 마이그레이션 파일에 직접 쓰지 않는다.
email_function_url:https://프로젝트주소.supabase.co/functions/v1/send-deadline-emailsemail_cron_secret: Edge Function Secrets의EMAIL_CRON_SECRET과 같은 값
그다음 supabase/migrations/20260720091000_schedule_deadline_email_function.sql을 적용한다. 이 마이그레이션은 다음 Cron을 만든다.
- 이름:
send-deadline-emails-daily - 일정:
0 0 * * * - 의미: 매일
00:00 UTC, 한국 시간 오전 9시 - 방식: Vault의 함수 URL로 POST
- 헤더: Vault의
email_cron_secret을x-cron-secret으로 전달
Supabase Dashboard → Integrations → Cron에서 생성 여부를 확인하고, Run now로 한 번 실행한 뒤 Cron 실행 기록과 Edge Function 로그를 확인한다.
프론트엔드 수신 동의 UI가 합쳐지기 전에는 Supabase Table Editor에서 테스트 사용자의 user_settings.email_enabled를 true로 바꾼다. 운영 사용자의 값을 동의 없이 바꾸면 안 된다.
테스트가 끝나면 docs/tasks.md의 “이슈 #50 Gmail 이메일 알림 완료 후 테스트 방법”을 순서대로 확인한다.