1. 도입: "신용카드 없는 무료 체험"이 $1,000 청구서로 돌아온 이야기

CI가 느려서 답답해 본 사람이라면 한 번쯤 GitHub Actions 대체재를 검색해 봤을 거다. PR이 쌓이고 빌드 큐가 밀리면 "더 빠른 러너 없나"부터 찾게 되니까. 이번에 화제가 된 글은 그 흔한 동기에서 시작한다. PR 처리량이 늘면서 GitHub Actions 기반 CI가 너무 느리고 비싸졌고, 드롭인 대체재를 표방하는 Blacksmith로 갈아탔다는 거다.

전환 자체는 성공적이었다. GitHub 설정을 그대로 가져왔고 CI는 실제로 빨라졌다. 문제는 과금이었다. 신용카드 없이 시작한 무료 체험이었는데:

  • 무료 분(minute) 80% 사용 알림 → "서비스 중단을 피하려면 카드 등록하라"는 이메일
  • 그런데 작업은 멈추지 않고 계속 실행됨
  • 몇 주 뒤 $500.60 사용 알림
  • 이어서 $1,081.45 청구서 + 연체 안내

핵심 충돌은 여기다. 대부분의 엔지니어는 "신용카드 없는 무료 체험"이라면 한도에 도달했을 때 서비스가 멈춘다(하드캡)고 기대한다. 그런데 Blacksmith 지원팀의 설명에 따르면 "서비스 중단"은 작업 자동 중단이 아니라 의심 활동 검토나 정지 검토를 뜻했고, 무료 한도 초과 후에도 워크플로는 공개 요율로 계속 누적됐다.

이건 단순 사건 사고가 아니라, CI/CD 파이프라인을 운영하는 사람이라면 누구나 한 번쯤 밟을 수 있는 지뢰다. 이 글에서는 동작 구조를 뜯어보고, 실무에서 비용 폭탄을 어떻게 방어하는지 명령어 수준으로 정리한다.

2. 핵심: Blacksmith는 어떻게 GitHub Actions를 "그대로" 대체하는가

먼저 왜 이런 서비스가 빠른지부터 이해해야 과금 구조도 보인다. GitHub Actions 워크플로 YAML을 보면 작업이 어디서 실행될지를 runs-on 으로 지정한다. 보통은 GitHub가 제공하는 호스티드 러너를 쓴다.

# 기존 GitHub 호스티드 러너
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./build.sh

Blacksmith 같은 대체 러너 서비스의 트릭은 이 runs-on 한 줄만 바꾸면 자기네 인프라에서 같은 워크플로가 돌게 만든다는 거다. 그래서 "드롭인 대체재(drop-in replacement)"라고 부른다.

# 러너 라벨만 교체 — 나머지 스텝은 그대로
jobs:
  build:
    runs-on: blacksmith-4vcpu-ubuntu-2204
    steps:
      - uses: actions/checkout@v4
      - run: ./build.sh

비유하자면 이렇다. 콘센트 규격(GitHub Actions의 워크플로 인터페이스)은 그대로 두고, 뒤에 연결된 발전소(실제 컴퓨트)만 더 빠르고 싼 곳으로 바꾸는 거다. 코드 입장에서는 자기가 어느 발전소에 물려 있는지 모른다. runs-on 라벨이 가리키는 곳으로 잡(job)이 디스패치될 뿐이다.

속도가 빨라지는 이유는 대체로 (1) 더 빠른 vCPU/디스크, (2) 자체 캐시 레이어, (3) 큐 대기 시간 단축 같은 요소다. 원문에서도 "개발 주기의 답답한 병목을 더 빠르게 만들기 때문에 빠르게 성장했다"고 평가한다.

여기서 과금 구조의 본질이 드러난다. 이런 서비스는 GitHub처럼 "사용 시간(분) × 머신 등급"으로 과금한다. blacksmith-4vcpu 처럼 더 큰 러너를 쓰면 분당 단가가 올라간다. 그런데 GitHub 호스티드 러너에 익숙한 사람은 "Actions 무료 분 다 쓰면 그냥 큐에서 안 돌겠지"라는 멘탈 모델을 그대로 가져온다. 이 멘탈 모델과 실제 후불 누적 과금이 충돌하는 지점이 이번 사건의 핵심이다.

참고로 원문 댓글에서 한 사용자가 지적했듯, $1,000 청구서가 나오려면 CI 시간을 정말 많이 써야 한다. 6명이 여러 저장소에서 Rust 빌드까지 빡세게 돌려도 월 $150 수준이라는 사례가 있었다. 즉 이건 취미 수준 사용량이 아니라 실질적인 컴퓨트 수요가 있는 팀이 실제 비용을 마주한 케이스에 가깝다. 그렇다 해도 "무료 체험"이라는 라벨과 후불 청구의 충돌은 별개 문제다.

3. 무료 한도 초과 후에도 작업이 계속 돈 이유 — 과금 메커니즘의 허점

왜 멈추지 않았을까. 기술적으로 보면 과금/계량 시스템과 프로비저닝(잡 실행) 시스템이 분리되어 있고, 그 사이를 실시간으로 끊는 하드 게이트가 없었기 때문으로 보인다. 원문 댓글 중에도 "과금과 계량은 어렵고, 실제 서비스보다 더 큰 공학 작업일 수 있다"는 평가가 나온다.

흔한 SaaS 패턴은 두 가지다.

  • 선불/하드캡형: 한도 도달 → 즉시 잡 거부. McDonald's 식 선결제. 사용자 기대와 일치.
  • 후불/누적형: 한도 초과 → 공개 요율로 계속 과금 → 나중에 청구서. 앉아서 먹는 식당 식 후결제.

원문 댓글의 표현을 빌리면, "관례상 선불인 서비스에 후불 가격 책정을 적용하면 완벽한 사기가 된다"는 거다. CI 무료 체험은 통념상 선불·하드캡이라고 기대하는데, 실제 동작은 후불 누적이었던 셈이다.

실무에서 더 무서운 건 "의심 활동/정지 검토"라는 표현이 "잡 자동 중단"으로 읽힌다는 점이다. 이메일에 "서비스 중단을 피하려면 카드 등록하라"고 적혀 있으면, 대부분은 "안 넣으면 알아서 멈추겠지"라고 해석한다. 그런데 멈추는 건 계정 상태 검토이지 워크플로 실행이 아니었다. 이 어휘의 갭이 $1,000을 만들었다.

4. 실무 관점: CI 비용 폭탄을 막는 방어선

이건 남의 일이 아니다. 우리도 새 CI 서비스를 PoC할 때 이런 함정에 빠진다. 방어선을 레이어별로 깔아야 한다.

4-1. 1차 방어선: 가상 카드 + 사용량 제한

원문 댓글의 한 사용자는 "무료 체험에 카드를 요구하는 곳에는 항상 가상 카드를 쓰고 취소한다"고 했다. 한도 걸린 일회용 가상 카드(Privacy.com, 토스/카카오 등 국내 가상카드 기능 등)를 쓰면, 후불 청구가 와도 결제 자체가 막힌다. 다만 이건 결제만 막을 뿐 약관상 채무가 사라지는 건 아니니, 어디까지나 보조 수단으로 본다.

또한 Depot 창업자가 댓글에서 밝혔듯, 정상적인 서비스라면 "예기치 않게 비용이 폭주하지 않도록 사용량 제한(spending cap)" 기능을 제공한다. PoC 시작 전에 이 옵션이 있는지부터 확인하는 게 1순위다.

4-2. 2차 방어선: GitHub Actions 사용량을 직접 계량해 알림

대체재의 청구서를 그대로 믿지 말고, 내가 직접 우리 워크플로가 분을 얼마나 먹는지 측정해야 한다. GitHub API로 워크플로 실행 시간을 뽑는 예시다.

# 특정 워크플로의 최근 실행별 소요 시간(ms) 뽑기
gh api \
  -H "Accept: application/vnd.github+json" \
  "/repos/OWNER/REPO/actions/runs?per_page=20" \
  --jq '.workflow_runs[] | {name, status, run_started_at, id}'

실행 출력 예시:

{"id":12345678901,"name":"CI","run_started_at":"2024-06-01T09:12:03Z","status":"completed"}
{"id":12345678902,"name":"CI","run_started_at":"2024-06-01T10:44:51Z","status":"completed"}
{"id":12345678903,"name":"Deploy","run_started_at":"2024-06-01T11:02:10Z","status":"completed"}

개별 실행의 청구 시간(billable time)은 timing 엔드포인트로 본다.

# 특정 run의 빌링 가능한 시간(밀리초) 확인
gh api "/repos/OWNER/REPO/actions/runs/12345678901/timing" \
  --jq '.billable'

출력 예시:

{
  "UBUNTU": {
    "total_ms": 540000,
    "jobs": 3
  }
}

total_ms가 540000이면 9분(=540000/1000/60)이다. 이런 수치를 매일 슬랙으로 쏘는 워크플로 하나만 만들어 둬도, "어느 날 갑자기 빌드 시간이 3배로 튀었다" 같은 이상 징후를 청구서가 오기 전에 잡을 수 있다. 원문 댓글에도 "실행 후 시간 측정 작업을 두고 GitHub Markdown의 Mermaid Gantt 차트로 표현했다"는 사례가 나온다.

4-3. 3차 방어선: 권한과 트리거를 조여 폭주 자체를 막기

비용 폭주는 대개 "의도치 않게 워크플로가 너무 많이 돌 때" 생긴다. 흔한 원인이 push 트리거에 동시성 제어가 없어서, 빠른 연속 커밋마다 빌드가 중첩으로 도는 경우다. 동시성(concurrency)으로 진행 중인 옛 실행을 취소하면 분이 크게 절약된다.

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

on:
  push:
    branches: [main]
  pull_request:

그리고 큰 러너의 함정 하나. 원문 댓글에서 짚었듯 "2배 실행기가 빌드를 2배 빠르게 해 주지는 않는다." 4vcpu8vcpu로 올리면 단가는 2배인데 빌드는 1.3배밖에 안 빨라지는 경우가 흔하다. 병렬화가 안 되는 빌드 스텝(직렬 의존성)이 많으면 vCPU만 늘려도 돈만 더 나간다. 캐싱(TypeScript라면 Nx, Rust라면 sccache 등)부터 챙기는 게 큰 러너로 도망가는 것보다 비용 효율이 낫다.

4-4. 흔한 함정 — 실제로 마주칠 에러

러너 서비스의 무료 한도가 막혀서 잡이 픽업되지 못하면, GitHub Actions UI에서 잡이 큐 상태로 멈춘 채 이런 메시지를 자주 본다:

This job is waiting for a runner to come online.
Waiting for a runner to pick up this job...

또는 자체 호스팅/대체 러너 라벨을 매칭하는 러너가 없을 때:

Error: No runner matching the specified labels was found: blacksmith-4vcpu-ubuntu-2204

이런 메시지가 뜨면 대개 (1) 무료/유료 한도 소진, (2) 결제 수단 미등록으로 인한 계정 정지, (3) 러너 라벨 오타 중 하나다. 그런데 이번 사건처럼 한도를 넘어도 막지 않는 구조라면, 위 에러조차 안 뜨고 그냥 조용히 과금이 누적된다. 에러가 안 나는 게 오히려 위험 신호일 수 있다는 게 이 케이스의 교훈이다.

4-5. 대안 비교

원문과 댓글에 등장한 대체재들이다. 모두 GitHub보다 저렴한 GHA 러너를 표방한다는 공통점이 있고, 과금 정책은 제각각이다.

  • GitHub Actions(원본): 통합이 가장 매끄럽지만 느리고 분당 단가가 높다는 게 출발점의 불만.
  • Blacksmith: 빠르지만 이번 후불 누적 과금이 논란. 댓글의 한 사용자는 결국 우호적 응대를 받고 다시 쓸 가능성이 높다고 정리.
  • Depot: 창업자가 직접 댓글에서 "시간 기준의 진짜 무료 체험"과 "사용량 제한"을 강조.
  • Warp build: 댓글 사용자가 GitHub 대비 50% 저렴, 6명 팀이 Rust 빌드 포함 월 $150 수준이라고 언급.
  • Ubicloud: 만족스럽게 써봤다는 댓글 존재.
  • 전용 서버 자체 호스팅: 사용량이 정말 크면 이게 더 쌌을지 검토할 가치가 있다는 의견.

여기 적힌 가격/배수는 모두 원문 댓글의 개별 사용자 경험치이고, 우리 환경(언어, 캐시 전략, 동시성)에 따라 크게 달라진다. 반드시 직접 PoC로 검증해야 한다.

5. 정리: 한 줄 요약과 의사결정

한 줄 요약: "무료 체험"과 "신용카드 불필요"는 하드캡을 보장하지 않는다. 후불 누적형 과금이라면 한도 초과 후에도 돈이 계속 쌓인다.

누가 언제 써야 하나:

  • 대체 러너를 도입할 팀: 속도 개선은 분명한 가치다. 단, PoC 전에 spending cap / 하드캡 옵션 유무를 약관 수준에서 확인하고, 가상 카드 + 자체 사용량 계량 알림을 깔아라.
  • SaaS를 만드는 입장: 원문 결론처럼 "대부분의 사용자는 무료 계정이 초과 누적 전에 정지될 것을 기대한다." 후불 청구는 단기 매출을 올릴 수 있어도 호의 상실과 평판 손상이 더 클 수 있다. "72시간 안에 카드 미등록 시 CI 중단" 같은 명시적 경고가 정직한 길이다.
  • 지금 Blacksmith를 시험 중인 사람: 원문 조언대로, 당분간은 체험 한도에 도달하기 전에 사용을 줄이는 편이 안전하다.

마지막으로 벤더 종속(lock-in) 관점. 댓글의 지적처럼 스타트업 CI 서비스는 빠르게 성장하다가도 그냥 실패할 수 있다. 성공이 분명해지기 전까지는 플랫폼 고유 기능에 깊게 종속되지 말고, runs-on 라벨만 바꾸면 원본 GitHub Actions로 즉시 돌아갈 수 있는 상태를 유지하는 게 안전한 운영 전략이다.

참고 자료

728x90

+ Recent posts