Skip to content

Cloud Scheduler 설정 가이드

개요

Spective는 Google Cloud Scheduler를 사용하여 이용권 관련 배치 작업을 자동으로 실행합니다.

Job스케줄설명
spective-ticket-expire매일 00:01 KSTAVAILABLE/RESTORED 이용권 만료 처리
spective-ticket-recover매일 00:01 KST미사용 RESERVED 이용권 자동 복구 (US-3)

빠른 시작 (스크립트)

설정 스크립트로 CRON_SECRET 생성과 Job 설정을 한 번에 처리할 수 있습니다.

bash
# 사전 요구사항: 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

스크립트는 다음을 자동으로 처리합니다:

  1. gcloud CLI 설치/인증 확인
  2. Cloud Scheduler API 활성화 확인
  3. CRON_SECRET 생성 및 Cloud Run 환경변수 설정
  4. 각 Job의 존재 여부를 확인하여 생성(create) 또는 업데이트(update)
  5. 수동 테스트용 curl 명령어 출력

참고: 스크립트 실행 후 출력되는 CRON_SECRET 값을 .env.secrets.<환경>에도 반영해야 합니다.

새 Job 추가하기

1. 엔드포인트 구현

apps/web/server/api/ 하위에 CRON 엔드포인트를 생성합니다. 기존 엔드포인트(tickets/expire.post.ts)를 참고하세요.

필수 사항:

  • CRON_SECRET Bearer 토큰 인증 (timingSafeEqual 사용)
  • @repo/logger로 로깅
  • 성공/실패 응답 반환

2. 스크립트에 Job 등록

scripts/setup-cloud-scheduler.shJOBS 배열에 한 줄 추가합니다:

bash
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. 스크립트 실행

bash
./scripts/setup-cloud-scheduler.sh dev
./scripts/setup-cloud-scheduler.sh prod

사전 요구사항

bash
# gcloud CLI 설치 및 인증
gcloud auth login
gcloud config set project <PROJECT_ID>

# Cloud Scheduler API 활성화 (스크립트가 자동으로 처리)
gcloud services enable cloudscheduler.googleapis.com

환경별 설정

환경PROJECT_IDCloud Run URLLocation
devspective-devhttps://spective-web-xf3kugqnca-du.a.run.appasia-northeast3
prodspective-prodhttps://spective-web-771785464554.asia-northeast3.run.appasia-northeast3

CRON_SECRET 설정

모든 CRON 엔드포인트는 CRON_SECRET 환경변수를 사용하여 인증합니다.

스크립트가 자동으로 처리하지만, 수동으로 설정하려면:

bash
# 안전한 시크릿 생성
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 환경

bash
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-dev

Production 환경

bash
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 환경

bash
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-dev

Production 환경

bash
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-prod

Job 관리

bash
# 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

미사용 이용권 복구 후 만료 처리를 순서대로 실행합니다.

처리 순서:

  1. recoverUnusedTickets(): RESERVED 이용권 중 진단 종료일 경과 + 미시작 건 처리
    • expiresAt > now → RESTORED (복구)
    • expiresAt <= now → EXPIRED (소멸)
  2. processExpiredTickets(): AVAILABLE/RESTORED 이용권 중 만료일 경과 건 → EXPIRED

응답 예시:

json
{
  "success": true,
  "restoredCount": 5,
  "expiredByRecoveryCount": 2,
  "expiredByExpiryCount": 3
}

POST /api/tickets/expire

만료일이 지난 이용권을 일괄 EXPIRED 처리합니다.

응답 예시:

json
{
  "success": true,
  "expiredCount": 10
}

오류 응답

상태 코드원인
401CRON_SECRET 불일치
500CRON_SECRET 미설정 또는 DB 오류

수동 테스트

bash
# 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로 인한 타임아웃을 방지하려면:

bash
gcloud run services update spective-web \
  --region=asia-northeast3 \
  --min-instances=1 \
  --project=<PROJECT_ID>

주의사항

  • 처리 순서: recover endpoint는 recoverUnusedTicketsprocessExpiredTickets 순서로 실행합니다. 복구된 이용권이 만료 대상이 될 수 있으므로 순서가 중요합니다.
  • 재시도: 개별 항목 재시도는 없으며, 전체 배치 단위로 재시도합니다. Cloud Scheduler의 재시도 정책을 활용하세요.
  • Cold Start: Cloud Run cold start로 인한 지연을 방지하려면 min-instances=1 설정을 권장합니다.
  • 무료 한도: Cloud Scheduler는 프로젝트당 월 3개 job까지 무료입니다.