Cloud Scheduler 설정 가이드
개요
Spective는 Google Cloud Scheduler를 사용하여 이용권 관련 배치 작업을 자동으로 실행합니다.
| Job | 스케줄 | 설명 |
|---|---|---|
spective-ticket-expire | 매일 00:01 KST | AVAILABLE/RESTORED 이용권 만료 처리 |
spective-ticket-recover | 매일 00:01 KST | 미사용 RESERVED 이용권 자동 복구 (US-3) |
빠른 시작 (스크립트)
설정 스크립트로 CRON_SECRET 생성과 Job 설정을 한 번에 처리할 수 있습니다.
# 사전 요구사항: gcloud CLI 설치 및 인증
gcloud auth login
# Dev 환경 전체 설정 (CRON_SECRET 생성 + Job upsert)
./scripts/setup-cloud-scheduler.sh dev
# Prod 환경 전체 설정
./scripts/setup-cloud-scheduler.sh prod
# Job만 upsert (CRON_SECRET 설정 건너뛰기)
./scripts/setup-cloud-scheduler.sh dev --skip-secret
# 실제 실행 없이 명령어만 확인
./scripts/setup-cloud-scheduler.sh dev --dry-run스크립트는 다음을 자동으로 처리합니다:
- gcloud CLI 설치/인증 확인
- Cloud Scheduler API 활성화 확인
CRON_SECRET생성 및 Cloud Run 환경변수 설정- 각 Job의 존재 여부를 확인하여 생성(create) 또는 업데이트(update)
- 수동 테스트용 curl 명령어 출력
참고: 스크립트 실행 후 출력되는
CRON_SECRET값을.env.secrets.<환경>에도 반영해야 합니다.
새 Job 추가하기
1. 엔드포인트 구현
apps/web/server/api/ 하위에 CRON 엔드포인트를 생성합니다. 기존 엔드포인트(tickets/expire.post.ts)를 참고하세요.
필수 사항:
CRON_SECRETBearer 토큰 인증 (timingSafeEqual사용)@repo/logger로 로깅- 성공/실패 응답 반환
2. 스크립트에 Job 등록
scripts/setup-cloud-scheduler.sh의 JOBS 배열에 한 줄 추가합니다:
JOBS=(
"spective-ticket-expire|/api/tickets/expire|1 0 * * *|만료 이용권 처리"
"spective-ticket-recover|/api/tickets/recover|1 0 * * *|미사용 이용권 자동 복구"
# 새 Job 추가
"spective-new-job|/api/new-endpoint|0 3 * * *|새 배치 작업 설명"
)형식: Job이름|엔드포인트경로|cron스케줄|설명
3. 스크립트 실행
./scripts/setup-cloud-scheduler.sh dev
./scripts/setup-cloud-scheduler.sh prod사전 요구사항
# gcloud CLI 설치 및 인증
gcloud auth login
gcloud config set project <PROJECT_ID>
# Cloud Scheduler API 활성화 (스크립트가 자동으로 처리)
gcloud services enable cloudscheduler.googleapis.com환경별 설정
| 환경 | PROJECT_ID | Cloud Run URL | Location |
|---|---|---|---|
| dev | spective-dev | https://spective-web-xf3kugqnca-du.a.run.app | asia-northeast3 |
| prod | spective-prod | https://spective-web-771785464554.asia-northeast3.run.app | asia-northeast3 |
CRON_SECRET 설정
모든 CRON 엔드포인트는 CRON_SECRET 환경변수를 사용하여 인증합니다.
스크립트가 자동으로 처리하지만, 수동으로 설정하려면:
# 안전한 시크릿 생성
openssl rand -hex 32
# Cloud Run 서비스에 환경변수 설정
gcloud run services update spective-web \
--region=asia-northeast3 \
--update-env-vars="CRON_SECRET=<생성한_값>" \
--project=<PROJECT_ID>
# dotenvx로 로컬 secrets 파일에도 반영
cd apps/web && bunx dotenvx set CRON_SECRET "<생성한_값>" -f .env.secrets.<환경>수동 설정 (스크립트 미사용 시)
미사용 이용권 자동 복구 (US-3)
Development 환경
gcloud scheduler jobs create http spective-ticket-recover-dev \
--location=asia-northeast3 \
--schedule="1 0 * * *" \
--time-zone="Asia/Seoul" \
--uri="https://spective-web-xf3kugqnca-du.a.run.app/api/tickets/recover" \
--http-method=POST \
--headers="Authorization=Bearer ${CRON_SECRET}" \
--project=spective-devProduction 환경
gcloud scheduler jobs create http spective-ticket-recover-prod \
--location=asia-northeast3 \
--schedule="1 0 * * *" \
--time-zone="Asia/Seoul" \
--uri="https://spective-web-771785464554.asia-northeast3.run.app/api/tickets/recover" \
--http-method=POST \
--headers="Authorization=Bearer ${CRON_SECRET}" \
--project=spective-prod만료 이용권 처리
Development 환경
gcloud scheduler jobs create http spective-ticket-expire-dev \
--location=asia-northeast3 \
--schedule="1 0 * * *" \
--time-zone="Asia/Seoul" \
--uri="https://spective-web-xf3kugqnca-du.a.run.app/api/tickets/expire" \
--http-method=POST \
--headers="Authorization=Bearer ${CRON_SECRET}" \
--project=spective-devProduction 환경
gcloud scheduler jobs create http spective-ticket-expire-prod \
--location=asia-northeast3 \
--schedule="1 0 * * *" \
--time-zone="Asia/Seoul" \
--uri="https://spective-web-771785464554.asia-northeast3.run.app/api/tickets/expire" \
--http-method=POST \
--headers="Authorization=Bearer ${CRON_SECRET}" \
--project=spective-prodJob 관리
# Job 목록 조회
gcloud scheduler jobs list --location=asia-northeast3
# Job 수동 실행 (테스트)
gcloud scheduler jobs run spective-ticket-recover-dev \
--location=asia-northeast3
# Job 일시 중지
gcloud scheduler jobs pause spective-ticket-recover-dev \
--location=asia-northeast3
# Job 재개
gcloud scheduler jobs resume spective-ticket-recover-dev \
--location=asia-northeast3
# Job 삭제
gcloud scheduler jobs delete spective-ticket-recover-dev \
--location=asia-northeast3엔드포인트 동작
POST /api/tickets/recover
미사용 이용권 복구 후 만료 처리를 순서대로 실행합니다.
처리 순서:
recoverUnusedTickets(): RESERVED 이용권 중 진단 종료일 경과 + 미시작 건 처리expiresAt > now→ RESTORED (복구)expiresAt <= now→ EXPIRED (소멸)
processExpiredTickets(): AVAILABLE/RESTORED 이용권 중 만료일 경과 건 → EXPIRED
응답 예시:
{
"success": true,
"restoredCount": 5,
"expiredByRecoveryCount": 2,
"expiredByExpiryCount": 3
}POST /api/tickets/expire
만료일이 지난 이용권을 일괄 EXPIRED 처리합니다.
응답 예시:
{
"success": true,
"expiredCount": 10
}오류 응답
| 상태 코드 | 원인 |
|---|---|
401 | CRON_SECRET 불일치 |
500 | CRON_SECRET 미설정 또는 DB 오류 |
수동 테스트
# Dev 환경 직접 호출
curl -X POST \
-H "Authorization: Bearer ${CRON_SECRET}" \
https://spective-web-xf3kugqnca-du.a.run.app/api/tickets/recover
curl -X POST \
-H "Authorization: Bearer ${CRON_SECRET}" \
https://spective-web-xf3kugqnca-du.a.run.app/api/tickets/expire
# 로컬 개발 환경
curl -X POST \
-H "Authorization: Bearer ${CRON_SECRET}" \
http://localhost:3800/api/tickets/recover트러블슈팅
Cloud Scheduler API 비활성화 오류
ERROR: (gcloud.scheduler.jobs.create) FAILED_PRECONDITION: Cloud Scheduler API has not been used해결: gcloud services enable cloudscheduler.googleapis.com --project=<PROJECT_ID>
권한 부족 오류
ERROR: (gcloud.scheduler.jobs.create) PERMISSION_DENIED해결: 현재 계정에 cloudscheduler.jobs.create 권한이 필요합니다. roles/cloudscheduler.admin 역할을 부여하세요.
Cloud Run 서비스를 찾을 수 없음
ERROR: (gcloud.run.services.update) NOT_FOUND해결: Cloud Run 서비스가 배포되어 있는지 확인하세요. gcloud run services list --region=asia-northeast3 --project=<PROJECT_ID>
CRON_SECRET 불일치 (401 응답)
- Cloud Run 환경변수의
CRON_SECRET과 Cloud Scheduler의Authorization헤더 값이 일치하는지 확인 gcloud run services describe spective-web --region=asia-northeast3 --format="value(spec.template.spec.containers[0].env)"로 현재 설정값 확인
Cold Start 지연
Cloud Run cold start로 인한 타임아웃을 방지하려면:
gcloud run services update spective-web \
--region=asia-northeast3 \
--min-instances=1 \
--project=<PROJECT_ID>주의사항
- 처리 순서: recover endpoint는
recoverUnusedTickets→processExpiredTickets순서로 실행합니다. 복구된 이용권이 만료 대상이 될 수 있으므로 순서가 중요합니다. - 재시도: 개별 항목 재시도는 없으며, 전체 배치 단위로 재시도합니다. Cloud Scheduler의 재시도 정책을 활용하세요.
- Cold Start: Cloud Run cold start로 인한 지연을 방지하려면
min-instances=1설정을 권장합니다. - 무료 한도: Cloud Scheduler는 프로젝트당 월 3개 job까지 무료입니다.