Cloudflare Workers 자동 배포: Workers Builds와 GitHub Actions

Cloudflare Workers로 만든 서비스가 하나둘 늘어나면 wrangler deploy를 직접 치는 게 슬슬 부담스러워지는데요. 누가 언제 어떤 커밋을 배포했는지 기록도 남지 않고, 테스트를 깜빡하고 배포하는 날도 생깁니다. 😅 결국 GitHub에 푸시하면 알아서 배포되는 흐름이 필요해집니다.

Workers를 GitHub와 연결하는 방법은 크게 두 가지입니다. 하나는 Cloudflare가 직접 빌드와 배포를 맡는 Workers Builds이고, 다른 하나는 GitHub Actions 워크플로우에서 Wrangler를 실행하는 방법입니다. 사실 두 방법 모두 결국 wrangler deploy를 실행합니다. 그 명령이 Cloudflare의 빌드 컨테이너에서 도느냐 GitHub의 러너에서 도느냐가 다를 뿐이죠. 이번 글에서는 두 방법으로 같은 Worker를 배포해 본 뒤, 둘 중 무엇을 쓰든 부딪히는 변수와 시크릿 관리, 풀 리퀘스트(pull request, 이하 PR)마다 프리뷰(preview)를 띄우는 설정까지 차례로 살펴보겠습니다.

Workers 자체가 처음이라면 Cloudflare Workers로 서버리스 애플리케이션 만들기를 먼저 읽고 오시면 좋습니다.

예제 Worker 준비

두 방법 모두 저장소 안에 Wrangler 설정 파일이 있다고 가정합니다.

wrangler.jsonc
{
  "name": "our-worker",
  "main": "src/index.ts",
  "account_id": "<계정 ID>",
  "compatibility_date": "2026-10-01",
}

account_id에는 배포할 Cloudflare 계정의 ID를 적습니다. 계정 ID는 대시보드 URL에도 그대로 보이는 식별자일 뿐 이것만으로는 아무것도 할 수 없으니, 시크릿으로 숨기지 말고 설정 파일에 커밋해 두면 로컬과 CI가 같은 계정을 바라보게 됩니다.

Wrangler는 전역 설치에 맡기지 말고 프로젝트의 개발 의존성으로 고정해 둡니다.

bun add -d wrangler

npm을 쓴다면 다음과 같이 설치합니다.

npm install -D wrangler

Workers Builds는 package.json에 적힌 Wrangler 버전으로 배포하기 때문에, 이렇게 해 두면 로컬과 CI가 같은 버전을 쓰게 됩니다. Wrangler 명령어가 낯설다면 Wrangler CLI 글을 참고하세요.

Workers Builds로 배포하기

Workers Builds는 Cloudflare에 내장된 CI/CD 기능입니다. GitHub 저장소를 Worker에 연결해 두면 푸시할 때마다 Cloudflare 쪽 빌드 환경에서 빌드 명령과 배포 명령을 차례로 실행합니다.

대시보드의 Workers & Pages에서 Worker를 선택하고, Settings 탭의 Builds 섹션에서 Connect를 누르면 GitHub 앱 설치 화면이 나옵니다. 조직 저장소라면 조직 소유자이거나 GitHub 앱 관리 권한이 있어야 하고, 앱이 접근할 저장소는 배포할 저장소만 골라 두는 편이 안전합니다. 앱을 설치하고 나면 다음 항목을 설정합니다.

  • Git repository: 연결할 저장소
  • Production branch: 운영 배포를 담당할 브랜치. 기본값은 저장소의 기본 브랜치
  • Build command: 빌드 단계가 필요할 때만 입력 (bun run build 등)
  • Deploy command: 기본값 npx wrangler deploy
  • Root directory: 모노레포에서 Worker가 있는 하위 디렉토리
  • API token: 비워 두면 Cloudflare가 빌드용 토큰을 만들어 사용. 연결할 때마다 새 토큰이 생기므로 두 번째 Worker부터는 기존 빌드 토큰 선택 권장

Workers Builds에 GitHub 저장소를 연결한 Worker의 Builds 설정 화면

저장하고 나면 운영 브랜치에 푸시할 때마다 빌드 명령, 배포 명령 순으로 실행됩니다. GitHub에서는 커밋 옆 상태 아이콘에 체크 런(check run)으로 결과가 붙습니다.

처음 연결할 때 가장 자주 막히는 지점은 이름입니다. 대시보드의 Worker 이름과 wrangler.jsonc의 name이 다르면 첫 빌드가 이름 불일치 오류로 실패하니, Worker를 대시보드에서 먼저 만들었다면 두 이름이 같은지 확인하세요.

한 저장소에 Worker가 여러 개 있는 모노레포라면 Worker마다 같은 저장소를 연결하고 Root directory를 각자 지정합니다. 이대로 두면 어느 폴더를 고치든 모든 Worker가 다시 빌드되므로, Builds 섹션의 빌드 감시 경로(build watch paths)에 workers/api/*처럼 각 Worker가 반응할 경로를 적어 둡니다.

GitHub Actions로 배포하기

이번에는 같은 일을 GitHub Actions로 해 보겠습니다. GitHub Actions에서는 Cloudflare가 아니라 GitHub 러너(runner)가 Wrangler를 실행하므로, Wrangler가 Cloudflare에 로그인할 토큰을 직접 넘겨 줘야 합니다.

Cloudflare 대시보드의 Manage account 메뉴에 있는 Account API tokens에서 Create Token을 누르고, Permission policies의 템플릿 중 Edit Cloudflare Workers를 고릅니다. 계정과 존(zone) 범위는 배포할 대상만 남도록 좁힙니다.

Account API tokens의 권한 정책 템플릿 목록과 Edit Cloudflare Workers 템플릿

만든 토큰은 GitHub Actions 시크릿으로 등록합니다. 명령을 실행하면 값을 입력하라는 프롬프트가 뜨므로 셸 기록에 토큰이 남지 않습니다.

gh secret set CLOUDFLARE_API_TOKEN

GitHub Actions 시크릿은 저장소, 환경(environment), 조직 단위로 등록할 수 있는데요, 위 명령은 가장 간단한 저장소 시크릿으로 등록합니다. 운영 배포를 더 엄격하게 관리하고 싶다면 --env production을 붙여 환경 시크릿으로 넣고 승인자나 허용 브랜치를 걸 수 있습니다. 다만 그러면 뒤에서 만들 프리뷰 워크플로우처럼 환경을 지정하지 않은 작업은 토큰을 읽지 못합니다. 여러 저장소가 같은 계정으로 배포한다면 조직 시크릿으로 한 번만 넣어 두는 방법도 있지만, 이름이 같으면 저장소 시크릿이 조직 시크릿보다 우선한다는 점과 강한 권한의 토큰은 필요한 저장소에만 공유해야 한다는 점을 기억하세요. 범위별 차이는 GitHub Actions 시크릿과 변수 관리하기에서 자세히 다뤘습니다.

이제 워크플로우 파일을 만듭니다. Cloudflare가 관리하는 cloudflare/wrangler-action을 쓰면 Wrangler 설치와 인증을 알아서 처리해 줍니다.

.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

permissions:
  contents: read

concurrency:
  group: deploy-production
  cancel-in-progress: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v7
      - uses: oven-sh/setup-bun@v2

      - run: bun install --frozen-lockfile
      - run: bun test

      - name: Deploy
        uses: cloudflare/wrangler-action@v4
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}

command를 지정하지 않으면 wrangler deploy가 실행되고, 패키지 매니저는 잠금 파일을 보고 고르므로 bun.lock이 있으면 Bun을 씁니다. 러너에는 Bun이 없으니 oven-sh/setup-bun으로 먼저 설치하고, 프레임워크를 쓰는 Worker라면 wrangler-action이 빌드를 대신해 주지 않으니 배포 앞에 bun run build를 넣어 두세요. 작업의 environment: production은 GitHub 환경을 지정하는 설정이고, 이름이 비슷한 wrangler-action의 environment 입력은 Wrangler 환경(--env)을 가리키는 별개의 설정입니다.

Workers Builds와 가장 크게 달라지는 부분은 배포 앞의 bun test입니다. 테스트가 실패하면 뒤 단계가 실행되지 않으므로 깨진 코드가 운영에 나가지 않고, 린트나 타입 검사, 마이그레이션 같은 단계도 자유롭게 끼워 넣을 수 있습니다. concurrency는 배포가 동시에 두 개 돌지 않게 막는데, cancel-in-progress를 false로 둬서 진행 중인 배포를 끊지 않고 뒤 커밋을 대기시킵니다.

변수와 시크릿 관리하기

자동 배포를 붙이고 나면 한동안 잘 돌다가 어느 날 Worker가 undefined를 읽기 시작하는 일이 생기는데요. 대부분 변수와 시크릿을 어디에 넣어야 하고, 배포가 그 값을 어떻게 다루는지 헷갈려서 생기는 문제입니다.

배포 과정에서 다루는 값은 언제 읽히느냐(런타임과 빌드)와 공개해도 되느냐(변수와 시크릿), 두 기준으로 나뉩니다.

변수 (공개해도 되는 값)시크릿 (노출되면 안 되는 값)
런타임 (Worker가 요청을 처리할 때)wrangler.jsonc의 varswrangler secret put이나 대시보드의 Runtime variables and secrets
빌드 (빌드 명령이 실행될 때)Builds 섹션의 Variables and secrets, 또는 GitHub Actions 변수Builds 섹션의 Variables and secrets, 또는 GitHub Actions 시크릿

시크릿을 Cloudflare에 넣을지 GitHub에 넣을지는 그 값을 누가 읽는지만 따져 보면 정해집니다. Worker 코드가 env.OPENAI_API_KEY로 읽는 런타임 시크릿은 결국 Cloudflare에 저장돼 있어야 합니다. GitHub Actions 시크릿은 워크플로우가 도는 동안 러너에만 주어지는 값이라 Worker가 직접 읽을 수는 없거든요. GitHub에 원본을 두고 싶다면 배포할 때 Cloudflare로 복사해 주면 되는데, 이 방법은 뒤에서 따로 다루겠습니다. 반대로 CLOUDFLARE_API_TOKEN은 Wrangler가 로그인할 때만 쓰는 배포 자격 증명이라 GitHub에 둡니다. Workers Builds를 쓴다면 이 토큰도 Cloudflare가 관리하므로 GitHub에 넣을 시크릿은 없습니다.

빌드 변수와 빌드 시크릿은 빌드하는 쪽, 즉 Wrangler가 실행되는 쪽에 둡니다. Workers Builds라면 저장소를 연결할 때 Builds 섹션에 새로 생기는 Variables and secrets에 넣습니다. Cloudflare가 직접 빌드하는 건 저장소가 연결됐을 때뿐이라 연결 전에는 이 항목이 보이지 않습니다. GitHub Actions라면 Actions 변수와 시크릿에 넣고 빌드 단계의 env로 넘깁니다. 빌드 시크릿을 코드에서 직접 읽으면 번들 결과물에 값이 그대로 박힐 수 있으니, Worker가 실행 중에 쓸 키는 반드시 런타임 시크릿으로 두세요.

대시보드에서는 Worker의 Settings 탭을 조심해야 합니다. Builds 섹션 안의 Variables and secrets와 위쪽의 Runtime variables and secrets는 라벨이 비슷해서, 런타임 시크릿을 Builds 쪽에 넣어 놓고 Worker에서 undefined가 나와 한참 헤매기 쉽습니다.

Worker 설정의 Runtime variables and secrets 섹션에 등록된 시크릿

런타임 변수와 런타임 시크릿은 배포를 대하는 방식이 정반대입니다. wrangler deploy는 기존 변수를 모두 지우고 wrangler.jsonc의 vars로 다시 채우기 때문에, 대시보드에서 급하게 고친 변수는 다음 푸시 때 조용히 되돌아갑니다. 설정 파일에 "keep_vars": true를 넣으면 이를 막을 수 있지만 실제 값을 설정 파일에서 확인할 수 없게 되니, 변수는 설정 파일에서만 고치는 편이 낫습니다. 반면 시크릿은 배포가 건드리지 않고 wrangler secret delete로 지우기 전까지 남으므로, 한 번만 등록해 두면 됩니다.

bunx wrangler secret put OPENAI_API_KEY

등록을 깜빡하는 실수는 secrets.required로 막을 수 있습니다. 여기에 적은 시크릿이 Worker에 없으면 wrangler deploy가 오류를 내고 멈추고, 로컬에서는 .dev.vars 파일에서 이 목록에 있는 키만 읽어 옵니다.

wrangler.jsonc
{
  "name": "our-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "vars": { "API_BASE_URL": "https://api.example.com" },
  "secrets": { "required": ["OPENAI_API_KEY"] },
}

.dev.vars에는 실제 키가 들어가니 반드시 .gitignore에 추가해 두세요.

PR마다 프리뷰 만들기

기능 브랜치를 운영에 올리기 전에 실제 Cloudflare 환경에서 확인하는 방법은 몇 가지가 있는데요, 브랜치마다 운영과 분리된 환경을 만들고 싶다면 wrangler preview를 씁니다. 스테이징 같은 상설 환경을 만드는 --env나 운영 Worker에 버전만 올려 두는 wrangler versions upload와의 차이는 Wrangler CLI 글에서 표로 비교했습니다.

wrangler preview는 Worker Previews 기능으로 브랜치마다 운영과 분리된 프리뷰를 만들고, 같은 브랜치에 다시 푸시하면 프리뷰 URL은 그대로 둔 채 내용만 갱신합니다. 2026년 10월 현재는 오픈 베타라서 실행하면 베타 경고가 출력되고 세부 동작이 바뀔 수 있습니다.

프리뷰는 운영의 변수, 바인딩, 시크릿을 하나도 물려받지 않습니다. 변수와 바인딩은 wrangler.jsonc의 previews 블록에 다시 적는데, 바인딩만이 아니라 vars도 빠짐없이 적어야 합니다.

wrangler.jsonc
{
  "name": "our-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-10-01",
  "vars": { "API_BASE_URL": "https://api.example.com" },
  "kv_namespaces": [{ "binding": "CACHE", "id": "<운영 KV ID>" }],
  "previews": {
    "vars": { "API_BASE_URL": "https://staging-api.example.com" },
    "kv_namespaces": [{ "binding": "CACHE", "id": "<테스트용 KV ID>" }],
  },
}

블록이 없거나 키가 빠지면 Wrangler가 필요한 키를 <REPLACE_ME>로 채운 제안 블록을 출력해 주니, 그대로 복사해서 테스트용 값으로 바꾸면 됩니다. 이때 KV 같은 리소스는 ID를 비워 두면 안 됩니다. 운영 배포에서는 Wrangler가 ID 없는 KV를 자동으로 만들어 주지만, 프리뷰에서는 그렇지 않아서 배포가 실패합니다. 테스트용 KV를 미리 만들고 출력된 ID를 previews 블록에 넣어 두세요.

bunx wrangler kv namespace create our-worker-preview-cache

시크릿은 모든 프리뷰가 함께 쓰는 기본 설정(base config)에 한 번 넣어 둡니다. 앞의 시크릿 화면에 있던 Previews Base 탭이 바로 이 설정입니다.

bunx wrangler preview base-config secret put OPENAI_API_KEY

Workers Builds에서는 Builds 섹션의 Production branch 아래 체크박스로 비운영 브랜치 빌드를 켭니다. 공식 문서에서는 Enable Preview Builds라고 부르고, 앞의 설정 화면처럼 기존 Worker에서는 Builds for non-production branches로 표시됩니다. 새로 연결한 Worker라면 켜 두는 것만으로 운영 브랜치가 아닌 브랜치에 푸시할 때마다 npx wrangler preview가 실행되고, Cloudflare 봇이 PR 댓글에 프리뷰 URL을 붙여 줍니다. 다만 체크박스는 비운영 브랜치 빌드를 켤 뿐이라 어떤 명령이 실행될지는 정하지 않습니다.

Worker Previews가 나오기 전부터 연결해 둔 Worker는 Version command에 들어 있는 npx wrangler versions upload로 프리뷰를 만드는데요, 이 글에서는 이를 버전 업로드 프리뷰라고 부르겠습니다. 버전 업로드 프리뷰는 PR 코드를 운영 Worker에 배포되지 않은 새 버전으로 올려 두기 때문에, 머지 전 코드가 운영 바인딩과 운영 시크릿으로 실행됩니다. 아래는 버전 업로드 프리뷰로 PR 브랜치를 빌드했을 때 Cloudflare 봇이 남긴 댓글입니다. Deployment successful이라고 떠도 운영에 배포된 것은 아닙니다.

PR 브랜치 빌드 결과를 알리는 Cloudflare 봇 댓글

바인딩도 시크릿도 없는 정적 사이트라면 큰 문제가 없지만, 그렇지 않다면 Builds 섹션의 Set up Worker Previews 배너에서 전환하세요. 한 번 전환하면 되돌릴 수 없습니다.

GitHub Actions에서는 PR 이벤트에 반응하는 워크플로우를 따로 만듭니다. wrangler-action으로 프리뷰를 만들려면 프로젝트의 Wrangler가 4.136.3 이상이어야 합니다.

.github/workflows/preview.yml
name: Preview

on:
  pull_request:
    types: [opened, synchronize, reopened, closed]

permissions:
  contents: read
  deployments: write

concurrency:
  group: preview-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  preview:
    if: github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile

      - name: Deploy preview
        id: preview
        uses: cloudflare/wrangler-action@v4
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: preview --name pr-${{ github.event.pull_request.number }}
          gitHubToken: ${{ secrets.GITHUB_TOKEN }}

      - name: Smoke test
        run: curl --fail "${{ steps.preview.outputs.preview-url }}/health"

  cleanup:
    if: github.event.action == 'closed' && github.event.pull_request.head.repo.full_name == github.repository
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile

      - name: Delete preview
        uses: cloudflare/wrangler-action@v4
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: preview delete --name pr-${{ github.event.pull_request.number }}

프리뷰 이름은 생략하면 브랜치 이름이 되지만, 여기서는 짧고 일정하게 유지되도록 PR 번호를 붙였습니다. gitHubToken을 넘기면 wrangler-action이 GitHub 배포(deployment) 기록과 작업 요약(job summary)을 만들어 PR 타임라인에서 프리뷰로 바로 들어갈 수 있게 해 주며, 이를 위해 deployments: write 권한이 필요합니다. 권한 설정은 GitHub Actions의 권한 설정을 참고하세요.

Workers Builds와 비교하면 손이 더 가지만 그만큼 할 수 있는 일도 많습니다. preview-url 출력값으로 실제 프리뷰에 요청을 보내 확인하는 스모크 테스트를 붙일 수 있고(예제의 /health는 Worker에 상태 확인 경로가 있다고 가정한 것입니다), 대신 PR이 닫힐 때 프리뷰를 지우는 cleanup 작업도 직접 챙겨야 합니다.

두 작업에 붙은 head.repo.full_name == github.repository 조건은 포크(fork)에서 올라온 PR을 걸러냅니다. 포크 PR에는 시크릿이 전달되지 않아 어차피 인증에서 실패하는데, 그렇다고 pull_request_target으로 바꿔 시크릿을 넘기면 외부인의 코드를 Cloudflare 토큰이 있는 환경에서 실행하게 됩니다. 자세한 내용은 GitHub Actions를 안전하게 사용하는 방법에서 다뤘습니다.

GitHub 시크릿을 Worker로 동기화하기

앞에서는 런타임 시크릿을 Cloudflare에 직접 등록했는데요, GitHub Actions를 쓴다면 시크릿 원본을 GitHub에 두고 배포할 때마다 Cloudflare로 복사하는 방법도 있습니다. 가장 간단한 방법은 wrangler-action의 secrets 입력에 이름을 나열하고 같은 이름의 환경 변수를 넘기는 것입니다.

.github/workflows/deploy.yml
- name: Deploy
  uses: cloudflare/wrangler-action@v4
  with:
    apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    secrets: |
      OPENAI_API_KEY
  env:
    OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

그런데 이 방법에는 함정이 있습니다. wrangler-action은 배포 명령보다 먼저 wrangler secret bulk로 시크릿만 따로 올리는데, 이 명령은 이름과 달리 최신 버전을 바탕으로 시크릿만 바꾼 새 버전을 만들어 바로 배포합니다. 버전 업로드 프리뷰를 쓰면 PR에 푸시할 때마다 운영 Worker에 버전이 올라가므로, PR을 머지한 직후에는 그 PR의 코드가 배포되지 않은 최신 버전으로 남아 있습니다. 이 상태에서 시크릿을 바꾸면 그 버전이 그대로 배포될 수 있어서 Cloudflare가 요청을 거부하고, 시크릿 단계에서 멈추면 배포 단계도 실행되지 않으니 직접 배포해 주기 전까지 다음 머지도 계속 실패합니다. 점진적 배포(gradual deployment)로 새 버전을 일부 트래픽에만 걸어 둔 상태에서도 같은 일이 생깁니다.

결국 문제는 배포할 때마다 시크릿을 배포와 별개로 다시 쓴다는 데 있습니다. 시크릿을 Cloudflare에 한 번만 등록해 두는 방식에서는 배포가 시크릿을 건드리지 않으니 이런 일이 없습니다. GitHub에 원본을 두고 싶다면 시크릿을 따로 올리지 말고 배포와 함께 올리세요. wrangler deploy --secrets-file은 지금 빌드한 코드와 시크릿으로 새 버전을 만들어 바로 배포하므로 최신 버전 상태와 무관하고, 파일에 없는 기존 시크릿은 그대로 남습니다.

.github/workflows/deploy.yml
- name: Write secrets file
  env:
    OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
  run: printf 'OPENAI_API_KEY=%s\n' "$OPENAI_API_KEY" > "$RUNNER_TEMP/secrets.env"

- name: Deploy
  uses: cloudflare/wrangler-action@v4
  with:
    apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    command: deploy --secrets-file ${{ runner.temp }}/secrets.env

시크릿 파일은 작업 디렉토리 밖인 $RUNNER_TEMP에 만들어서 실수로 커밋되거나 아티팩트에 섞이지 않게 합니다.

그렇다면 원본을 어디에 둘까요? 배포 토큰은 두 방식 모두 GitHub에 두고, 여기서는 런타임 시크릿의 원본을 어디에 두느냐만 비교합니다.

비교 항목Cloudflare에 직접 등록GitHub에 원본, 배포 때 동기화
런타임 시크릿이 있는 곳Cloudflare 한 곳GitHub와 Cloudflare 두 곳
값을 바꾸면wrangler secret put 즉시 반영GitHub 시크릿 수정 후 재배포해야 반영
관리 권한Cloudflare 계정 권한 필요GitHub 권한으로 충분
환경 분리Wrangler 환경마다 따로 등록GitHub 환경(production 등)별 시크릿 재사용
새 Worker로 옮길 때시크릿을 다시 등록배포 한 번이면 재현
대시보드에서 수정그대로 유지다음 배포 때 GitHub 값으로 되돌아감

특별한 이유가 없다면 런타임 시크릿은 Cloudflare에 직접 등록하고, GitHub에는 배포 토큰만 두는 구성을 권합니다. 값이 한 곳에만 있어 노출 지점이 적고, 키를 교체하면 바로 반영되며, 나중에 Workers Builds로 옮겨도 바꿀 게 없습니다. GitHub 원본 방식은 Cloudflare 계정이 없는 팀원도 GitHub에서 키를 관리해야 할 때 잘 맞는데, 이때는 대시보드에서 시크릿을 고치지 않는다는 규칙을 팀에 공유해 두세요. 관리하는 프로젝트가 많을 때도 GitHub 쪽이 낫습니다. Worker마다 시크릿을 따로 등록하면 같은 키가 여러 곳에 흩어지니, GitHub 조직 시크릿이나 1Password 같은 시크릿 관리 도구를 원본으로 두고 배포할 때 --secrets-file로 넣는 편이 관리하기 쉽습니다.

두 방법을 동시에 켜지 않기

Workers Builds를 쓰다가 GitHub Actions로 옮길 때 자주 하는 실수가 있습니다. 저장소 연결을 남겨 두면 main에 푸시할 때마다 Cloudflare와 GitHub가 각각 배포를 실행해서, GitHub Actions의 테스트가 실패해도 Workers Builds 쪽 배포는 그대로 나가 버립니다. PR 브랜치 빌드도 계속 도는데, 버전 업로드 프리뷰라면 이 빌드가 배포되지 않은 버전을 쌓아서 앞에서 본 시크릿 동기화까지 막습니다.

GitHub Actions로 옮긴다면 Builds 섹션에서 저장소 연결을 해제(Disconnect)하고, 반대로 Workers Builds로 돌아온다면 워크플로우 파일을 지우거나 트리거를 비활성화하세요.

무엇을 고를까?

두 방법의 차이를 표로 정리하면 다음과 같습니다.

항목Workers BuildsGitHub Actions
설정 위치Cloudflare 대시보드저장소의 워크플로우 파일
인증Cloudflare가 빌드 토큰 자동 관리API 토큰을 GitHub Actions 시크릿에 직접 등록
배포 전 테스트빌드 명령에 끼워 넣는 정도단계를 자유롭게 구성
PR 프리뷰체크박스와 previews 설정, PR 댓글 자동워크플로우 작성, 출력값으로 후속 작업
설정 이력대시보드 안에만 남음코드 리뷰와 Git 이력으로 관리
빌드 로그Cloudflare 계정 멤버만 볼 수 있음저장소를 볼 수 있으면 누구나 확인하고 재실행
모노레포Worker마다 Root directory와 감시 경로paths 필터와 workingDirectory 입력

개인 프로젝트나 작은 Worker라면 Workers Builds로 시작하는 걸 권합니다. 토큰을 만들 필요도, 워크플로우 파일을 관리할 필요도 없고, PR 프리뷰도 체크박스를 켜고 previews 설정만 준비하면 됩니다.

반면 팀이 함께 쓰는 서비스라면 GitHub Actions가 더 잘 맞습니다. 배포 전에 테스트와 타입 검사를 반드시 통과하게 만들 수 있고, 배포 설정이 코드로 남아 PR로 검토할 수 있습니다. 빌드 로그를 누가 보느냐도 큰 차이인데요, Workers Builds는 GitHub에 성공과 실패만 표시하고 로그는 Cloudflare 대시보드에 두기 때문에 Cloudflare 계정이 없는 기여자는 자기 PR이 왜 실패했는지 알 수 없습니다. 오픈 소스나 커뮤니티 저장소라면 이것만으로도 GitHub Actions를 고를 이유가 됩니다. 같은 이유로 팀원 대부분이 Cloudflare 계정이 없다면, 런타임 시크릿도 앞에서 본 GitHub 원본 방식을 검토해 볼 만합니다.

마치며

지금까지 Cloudflare Workers를 GitHub에 연결해 자동 배포하는 두 가지 방법을 살펴봤습니다. Workers Builds는 Cloudflare가 빌드와 배포, PR 프리뷰를 모두 맡아 주는 간편한 방법이고, GitHub Actions는 wrangler-action으로 테스트부터 프리뷰 검증, 정리까지 원하는 대로 엮을 수 있는 방법입니다. 어느 쪽을 고르든 런타임 시크릿은 특별한 이유가 없다면 Cloudflare에 직접 등록하고, 프리뷰에는 운영과 분리된 previews 설정을 꼭 넣어 두세요.

처음에는 Workers Builds로 가볍게 시작했다가, 배포 전 검증 단계가 필요해지거나 함께 작업하는 사람이 늘어나는 시점에 GitHub Actions로 옮겨도 늦지 않습니다. 🚀

더 자세한 내용은 Workers Builds 공식 문서와 wrangler-action 저장소를 참고하세요.

This work is licensed under CC BY 4.0CCBY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord