이런 경우에 맞습니다
- Zeabur에서 GitHub로 배포한 백엔드: Node.js·Python·Go API, LINE·Discord 봇
- 트래픽이 적어서, 아무도 쓰지 않을 때는 요금이 나가지 않았으면 할 때 (Cloud Run은 0까지 축소됩니다)
- 가까운 리전을 원할 때: 한국 사용자가 많다면
asia-northeast3(서울). 아래 예시는 테스트에 쓴asia-east1(대만) 기준입니다
맞지 않는 경우: 영구 디스크가 필요한 서비스(업로드 파일을 로컬 폴더에 저장하는 경우 등). Cloud Run의 파일 시스템은 임시라서 재배포하거나 0으로 축소되면 써 둔 파일이 사라집니다. 이런 서비스는 파일을 Cloud Storage나 R2에 저장하도록 바꾸거나 VPS를 쓰세요(n8n 편 참고).
0단계: 새 프로젝트 준비 (공식 문서 기준)
- gcloud CLI를 설치하고
gcloud init으로 로그인한 뒤 프로젝트를 고릅니다. 프로젝트에는 결제 계정이 연결되어 있어야 합니다 - API를 켭니다.
gcloud services enable run.googleapis.com cloudbuild.googleapis.com
- 소스에서 배포할 때 Cloud Build는 기본적으로 Compute Engine 기본 서비스 계정을 씁니다. 공식 문서는 이 계정에 Cloud Run Builder 역할을 부여하라고 안내합니다.
gcloud projects add-iam-policy-binding 프로젝트ID \
--member=serviceAccount:프로젝트번호[email protected] \
--role=roles/run.builder
문서에 따르면 이 권한이 적용되기까지 몇 분 걸립니다.
지금 어떤 프로젝트를 쓰고 있는지 꼭 확인하세요. 모든
gcloud명령어에--project=프로젝트ID를 붙이거나, 먼저gcloud config get-value project로 확인합니다. 저희 컴퓨터에도 프로젝트가 여러 개 있어서, 기본 프로젝트가 배포하려는 곳이 아닌 경우가 많습니다.
1단계: 앱이 PORT를 리슨하는지 확인
Zeabur와 Cloud Run 모두 어느 포트를 리슨할지 PORT 환경 변수로 앱에 알려 줍니다. Zeabur 문서대로 이미 $PORT를 쓰고 있다면 바꿀 것이 없습니다. 3000처럼 하드코딩되어 있다면 다음과 같이 바꿉니다.
app.listen(process.env.PORT || 3000);
2단계: 배포
프로젝트 루트에서 실행합니다(Dockerfile 불필요, Google buildpacks가 언어를 자동 감지).
gcloud run deploy my-api --source . --region asia-east1 \
--allow-unauthenticated \
--set-env-vars "NODE_ENV=production" \
--project=프로젝트ID
끝나면 Service URL: https://my-api-xxxx.asia-east1.run.app이 표시됩니다. 테스트에서는 Dockerfile 없는 Node 서비스가 첫 배포에서 바로 응답했습니다.
프로젝트 루트에 Dockerfile이 있으면 Cloud Run은 그것을 우선 사용합니다.
3단계: 키는 환경 변수가 아니라 Secret Manager에
--set-env-vars 값은 서비스 설정을 볼 수 있는 사람이라면 누구나 볼 수 있습니다. 데이터베이스 비밀번호와 API 키는 Secret Manager에 넣으세요.
# Secret 만들기 (printf는 끝에 줄바꿈을 붙이지 않음)
printf '%s' 'postgresql://...' | gcloud secrets create database-url --data-file=- --project=프로젝트ID
# 서비스에 마운트. 앱에서는 그대로 process.env.DATABASE_URL로 읽음
gcloud run services update my-api --region asia-east1 \
--set-secrets "DATABASE_URL=database-url:latest" --project=프로젝트ID
테스트에서 만난 오류
서비스 계정에 Secret을 읽을 권한이 없으면 배포가 실패합니다.
ERROR: (gcloud.run.deploy) ... Permission denied on secret: projects/.../secrets/database-url/versions/latest
for Revision service account [email protected]. The service account used must be granted
the 'Secret Manager Secret Accessor' role (roles/secretmanager.secretAccessor) at the secret, project or higher level.
해결 방법은 그 Secret 하나에만 권한을 주고(가장 좁은 범위) 다시 배포하는 것입니다.
gcloud secrets add-iam-policy-binding database-url \
--member="serviceAccount:오류 메시지에 나온 서비스 계정" \
--role="roles/secretmanager.secretAccessor" --project=프로젝트ID
테스트에서는 권한을 준 뒤 다시 배포하자 바로 성공했습니다.
4단계: 데이터베이스
Cloud Run에는 데이터베이스가 없습니다. PostgreSQL은 Neon, Supabase 같은 관리형 서비스나 Google Cloud SQL로 옮길 수 있습니다. 방법은 데이터베이스 편을 참고하세요.
5단계: LINE 봇의 Webhook URL 바꾸기
- LINE Developers 콘솔에서 채널을 고릅니다
- Messaging API 탭의 Webhook URL을 새 Cloud Run 주소(앱 경로 포함, 예:
/webhook)로 바꿉니다 - Verify를 눌러 성공하는지 확인합니다
Channel Secret과 Access Token도 이번에 함께 교체하기를 권합니다. 보안 편을 참고하세요.
6단계: 커스텀 도메인 연결
Cloud Run에 커스텀 도메인을 연결하는 방법은 여러 가지(Cloud Run 도메인 매핑, 부하 분산기, Firebase Hosting)이고 지원 리전과 비용이 다릅니다. Google 공식 문서를 보고 고르세요. 이 단계는 이번에 테스트하지 않았습니다. DNS 전환 시 주의점은 도메인과 DNS 편을 참고하세요.