Blog
6 min

Vercel + Koyeb + Supabase 무료 배포 조합기

프론트엔드는 Vercel, 백엔드는 Koyeb, DB는 Supabase로 무료 배포 환경을 구축하고 Koyeb의 Scale-to-Zero 문제를 GitHub Actions로 해결한 경험을 공유합니다.

DevOps 배포

무료 배포 조합기

Mail-On 프로젝트를 배포하면서 겪은 시행착오를 정리합니다. 특히 무료 클라우드 환경의 제약을 기술적으로 어떻게 해결했는지에 초점을 맞췄습니다.

조합 선택 이유

구성플랫폼이유
FrontendVercelVite/Next.js 최적화, 자동 배포, Preview 배포
BackendKoyeb무료 티어 제공, Docker 컨테이너 지원
DatabaseSupabasePostgreSQL + 실시간 구독 + 인증 시스템

가장 큰 문제: Koyeb의 Scale-to-Zero

배포 당시에는 Koyeb 무료 티어가 일정 시간 외부 요청이 없으면 자동으로 슬립 상태(Scale-to-Zero)로 전환된다는 점을 모르고 있었습니다. 그래서 백엔드 내부의 node-cron 스케줄러도 배포만 해두면 계속 동작할 것이라고 생각했습니다.

하지만 Mail-On의 핵심 기능인 자동 크롤링에서 치명적인 문제가 발생했습니다. 백엔드 내부의 node-cron 스케줄러가 서버와 함께 멈추면서 백엔드로 들어오는 외부 요청이 없는 시간에는 크롤링 자체가 실행되지 않는 것이었습니다. 취업 게시물은 언제 올라올지 모르기 때문에, 크롤링이 멈추면 서비스의 존재 이유가 사라집니다.

해결: 크롤링 트리거를 GitHub Actions로 외부화

스케줄러를 서버 내부에서 외부로 분리하는 구조 변경을 했습니다.

변경 전:

Koyeb 서버 (node-cron) → 크롤링 실행 → 메일 발송
                ↑
        서버 슬립 시 함께 멈춤

변경 후:

GitHub Actions (cron schedule) → Koyeb API 호출 → 크롤링 실행 → 메일 발송
                ↑
        서버 상태와 무관하게 동작

GitHub Actions의 schedule 이벤트로 정해진 시간에 Koyeb 백엔드의 크롤링 엔드포인트를 호출하도록 설정했습니다. 서버가 슬립 상태라면 API 호출 시 자동으로 깨어나고, 크롤링을 실행한 뒤 다시 슬립에 들어갑니다.

결과: 크롤링 주기 8배 정밀화

외부화 덕분에 크롤링 주기를 유연하게 조절할 수 있게 되었습니다.

  • 변경 전: 평일 3회(10시, 14시, 18시) — 서버가 깨어 있을 때만 동작
  • 변경 후: 매일 09시~21시, 30분 간격 — 서버 상태와 무관하게 동작

서버 비용은 0원을 유지하면서도 크롤링의 신뢰성을 확보한 셈입니다.

배포 과정에서 배운 것들

CORS 설정

Koyeb 환경변수에 프론트엔드 URL을 등록할 때, 끝에 슬래시(/)가 하나 붙어 있어서 CORS 에러가 발생했습니다.

❌ https://mail-on.vercel.app/
✅ https://mail-on.vercel.app

사소하지만 원인을 찾기까지 시간이 걸렸습니다.

모노레포 환경 설정

Mail-On은 frontend와 backend가 하나의 레포에 있는 모노레포 구조입니다. 배포 시 주의할 점이 몇 가지 있었습니다.

  1. Root Directory 설정 — Vercel에서는 frontend, Koyeb에서는 backend를 각각 지정해야 합니다
  2. 환경 변수 접두사 — 프론트엔드에서 사용하는 환경 변수에는 VITE_ 접두사가 필수입니다
  3. package-lock.json 동기화 — workspaces 환경에서 루트와 하위 폴더의 lock 파일이 충돌하는 경우가 있었습니다

Gmail SMTP 설정

Nodemailer로 메일을 발송할 때 일반 Gmail 비밀번호로는 인증이 되지 않습니다. Google 계정에서 앱 비밀번호를 별도 생성하여 환경 변수에 등록해야 합니다.

마무리

무료 클라우드 환경은 편리하지만 각 플랫폼의 제약을 이해하지 않으면 예상치 못한 문제에 부딪힙니다. 특히 Koyeb의 Scale-to-Zero는 스케줄링 기반 서비스에서 치명적이었고, 이를 GitHub Actions로 외부화한 것이 이 프로젝트에서 가장 의미 있는 기술적 판단이었습니다.

배포는 코드 작성보다 인프라의 특성을 이해하는 데서 시작된다는 것을 체감했습니다.