홈시리즈멘토링

© 2026 정기창. All rights reserved.

본 블로그의 콘텐츠는 CC BY-NC-SA 4.0 라이선스를 따릅니다.

☕후원하기소개JSON Formatter러닝 대기질개인정보처리방침이용약관

© 2026 정기창. All rights reserved.

콘텐츠: CC BY-NC-SA 4.0

☕후원하기
소개|JSON Formatter|러닝 대기질|개인정보처리방침|이용약관

다 만들어놓고 전부 껐습니다 — 쿼터를 태운 범인은 macOS 10배 배수였습니다

정기창·2026년 8월 13일

2주가 걸렸습니다. 러너 네 대짜리 함대를 만들었고, 절전에 실패해 밤중에 전원 버튼을 눌렀고, 성능을 재고 오진을 하나 바로잡았습니다. 그러는 동안 저는 첫날 던졌어야 할 질문에 계속 답하지 않고 있었습니다.

나는 무료 사용량 안에서 쓰고 있다고 믿었는데, 그렇다면 왜 부족했는가.

총량으로 보면 아무것도 안 보입니다

그동안 제가 본 것은 "이번 달 얼마나 썼는가"라는 숫자 하나였습니다. 2,000분 한도에 2,041분. 초과했다는 사실만 있고 왜 초과했는지는 없습니다. 이 숫자만 보면 결론은 하나로 수렴합니다. 내 CI가 너무 많이 돈다는 것이고, 그렇다면 답은 러너를 늘리거나 돈을 내는 것입니다. 저는 전자를 골랐고, 2주를 썼습니다.

이번에는 청구 내역을 저장소별로, 그리고 머신 종류별로 쪼개서 봤습니다. 여기서 제가 몰랐던 사실 하나가 튀어나왔습니다.

운영체제마다 배수가 다릅니다

GitHub Actions는 사용 시간을 그대로 차감하지 않습니다. 어떤 운영체제에서 돌았느냐에 따라 배수를 곱합니다.

운영체제 배수
Linux 1배
Windows 2배
macOS 10배

문서에 적혀 있는 내용이고 저도 어렴풋이 알고는 있었습니다. 다만 알고 있는 것과 그것이 내 청구서에서 무엇을 하고 있는지 아는 것은 다른 일이었습니다. 분해한 결과는 이랬습니다.

머신 종류 실제 사용 배수 쿼터 소모
macOS 99.4분 10배 994분 (49%)
Linux 621분 1배 621분 (30%)
Windows 190분 2배 380분 (19%)
기타 저장소 46분 1배 46분

99.4분이 994분이 되어 있었습니다. 그 자체로 월 한도의 절반입니다. macOS와 Windows를 합치면 전체 소모의 68%인데, 실제로 돌아간 시간은 290분 남짓에 불과합니다. 반대로 제가 매일 쓰는 진짜 CI 부하, 그러니까 리눅스에서 도는 테스트와 빌드는 621분으로 쿼터의 30%밖에 쓰지 않고 있었습니다.

범인은 제가 이미 고쳐둔 것이었습니다

그 macOS 작업이 어디서 나왔는지 찾아보니, 세 가지 운영체제에서 병렬로 도는 빌드였습니다. 짐작하셨겠지만 이 시리즈 2편에서 제가 조용히 고쳐둔 바로 그 워크플로우입니다.

그때 저는 그것을 "self-hosted로 옮기면 안 돌아갈 워크플로우"로만 봤습니다. 호환성 문제로 분류하고 손봐서 넘어갔습니다. 같은 것을 비용 관점에서 한 번만 봤다면, 그러니까 내 무료 사용량을 이 세 갈래 중 어디가 얼마나 먹고 있나를 물었다면, 저는 그날 답을 얻었을 것입니다. 범인은 처음부터 제 손안에 있었고, 저는 그걸 다른 이유로 처리하고 지나갔습니다.

검증도 됐습니다. 그 워크플로우가 정리된 다음 달 청구 내역에는 macOS와 Windows 항목이 아예 없습니다. 리눅스 사용분과 저장 공간 요금뿐입니다.

그래서 계산을 다시 했습니다

배수를 태우던 두 다리가 사라진 지금 구조에서 제 실사용은 리눅스 600분대입니다. 무료 한도는 2,000분입니다. 여유롭습니다.

그리고 하나 더 확인한 게 있습니다. 무료 계정도 동시에 20개의 작업을 돌릴 수 있습니다. 제 워크플로우가 다섯 개 작업으로 이뤄져 있으니, PR 네 개가 완전히 병렬로 처리된다는 뜻입니다. 제가 러너를 늘려서 해결하려던 그 병렬성 문제는 애초에 존재하지 않았습니다. 문제는 러너 수가 아니라 쿼터였고, 쿼터 문제는 배수를 태우는 다리 하나 때문이었습니다.

보류한 지출 목록

이 진단 전까지 제가 검토하고 있던 것들입니다.

  • 씽크패드 메모리 증설 — 약 10만 원
  • GitHub 유료 플랜 — 월 4달러, 3,000분
  • USB 랜 어댑터 — 1만 5천 원 (앞 편에서 이미 무의미하다고 밝혀진 것)
  • 원격 전원용 스마트플러그 — 1만 5천 원

전부 사지 않았습니다. 무료로 운영하겠다는 원칙은 지켜졌는데, 솔직히 말하면 원칙을 잘 지킨 게 아니라 원인을 늦게 안 덕분에 지출 직전에 멈춘 것에 가깝습니다.

참고로 확인해둔 사실이 하나 있습니다. self-hosted 러너 사용 자체는 청구 내역에 나타나지 않습니다. 한 달에 500회 넘게 제 기계에서 돌렸는데 관련 항목은 0건이었습니다. 무료로 CI를 늘리는 수단으로서 self-hosted가 유효하다는 것은 사실입니다. 다만 저에게는 그 필요가 없었을 뿐입니다.

그래서 전부 껐습니다

최종 결정은 이렇습니다. 노트북 두 대는 전원을 껐습니다. 다만 러너 등록은 지우지 않았습니다.

여기서 3편에서 만든 설계가 배당금을 냈습니다. 꺼진 러너는 GitHub이 알아서 배정 대상에서 제외하므로, 전원을 끄는 것만으로 구성에서 빠집니다. 설정을 되돌릴 필요도, 등록을 해제할 필요도 없습니다. 다시 필요해지면 전원만 켜면 그 자리로 돌아옵니다. 라벨로 폴백을 표현해둔 덕분에 철수도 라벨 없이 가능했던 셈입니다.

자동 전환기도 그대로 뒀습니다. 언젠가 쿼터가 다시 위험해지면 맥북 쪽으로 넘어가 CI가 완전히 멈추는 일만은 막아줍니다. 비용이 들지 않는 안전망은 남겨두는 게 맞다고 판단했습니다.

용량이 정말 부족해지면 순서도 정해뒀습니다. 월 4달러짜리 유료 플랜이 첫 번째고, 그다음이 초과분만큼만 내는 종량 과금이고, 그다음이 이미 만들어둔 맥북 폴백입니다. 클라우드 컨테이너 서비스로 러너를 돌리는 방안도 검토했지만, 러너는 계속 대기하며 일감을 기다리는 상주 프로그램이라 잠깐 실행되고 사라지는 용도로 설계된 서비스와는 성격이 맞지 않았습니다. 매번 처음부터 파일을 받아야 하니, 앞 편에서 본 콜드 스타트 문제를 새 플랫폼에서 반복하는 셈이기도 했습니다.

돌아가니 숨어 있던 버그가 드러났습니다

예상 못 한 소득이 하나 있었습니다. hosted로 돌아오자 그동안 통과하던 테스트 하나가 실패하기 시작했습니다.

조사해보니 새로 생긴 버그가 아니라 원래 있던 결함이었습니다. 화면이 백그라운드로 전환될 때 잠금을 명시적으로 풀어주지 않아 잠금이 남는 문제였는데, 맥북 러너에서는 타이밍이 우연히 맞아떨어져 계속 통과하고 있었습니다. 더 느린 hosted 머신으로 옮기자 타이밍이 어긋나면서 드러난 것입니다.

러너를 바꾸는 것만으로 레이스 컨디션이 숨었다 나타났다 합니다. 테스트가 초록불이라는 것은 코드가 옳다는 뜻이 아니라, 이 환경에서 이번에는 타이밍이 맞았다는 뜻일 수 있습니다. 인프라를 바꿔보는 일이 코드 검증의 한 방법이 될 수도 있겠다는 생각이 들었습니다.

2주를 정리하며

남는 교훈은 셋입니다.

첫째, 총량은 원인을 감춥니다. 2,041분이라는 숫자는 참이지만 아무것도 알려주지 않았습니다. 같은 데이터를 저장소별, 머신별로 쪼개자 범인이 한 줄로 드러났습니다. 이 블로그에서 전에도 비슷한 실수를 한 적이 있는데, 그때는 28일 총계가 하루의 절벽을 뭉개고 있었습니다. 뭉쳐진 숫자를 믿으면 안 된다는 것을 저는 두 번 배웠습니다.

둘째, 원인을 모른 채 세운 대책은 필요 이상으로 커집니다. 저는 "쿼터가 부족하다"는 증상에 맞춰 대책을 설계했고, 그래서 나온 답이 러너 네 대짜리 함대였습니다. 원인이 "워크플로우 한 곳의 macOS 다리"였다는 것을 알았다면 답은 그 다리를 떼는 것 하나였습니다. 대책의 크기는 문제의 크기가 아니라 내 이해의 흐릿함에 비례한다는 생각이 들었습니다.

셋째, 만들어놓고 쓰지 않기로 하는 것도 결론입니다. 2주를 들인 것을 끄는 데는 저항이 따랐습니다. 아까우니 조금이라도 쓰자는 생각이 들었고, 실제로 한동안 "가벼운 작업만 분담시키면 어떨까"를 검토했습니다. 다만 그건 만든 것을 정당화하려는 마음이지 판단이 아니었습니다. 필요 없어진 인프라를 끄지 못하면 그것은 자산이 아니라 부채가 됩니다.

그럼에도 남은 것이 없지는 않습니다. 폴백이 실제로 작동하는지 강제로 돌려서 확인해봤고, 그 과정에서 평상시라면 쿼터가 바닥나는 순간에야 알았을 결함들을 미리 찾아냈습니다. 검증하지 않은 폴백은 폴백이 아니라 폴백이 있다는 믿음일 뿐입니다. 지금 그 두 노트북은 꺼져 있지만, 켜면 동작한다는 것은 확인된 상태입니다.

그리고 애석하게도, 그 확인을 위해 제가 지불한 값은 2주와 밤 열한 시의 전원 버튼이었습니다. 첫날에 청구서를 한 번 쪼개봤다면 훨씬 쌌을 것입니다.

GitHub ActionsCI비용 최적화원인 분석self-hosted runner인프라

관련 글

CI가 전부 멈췄고, 저는 원인을 확인하지 않았습니다 — 30분 만에 끝난 대응의 함정

GitHub Actions hosted 러너가 새벽에 전면 차단됐습니다. 변수 한 줄과 self-hosted 러너로 30분 만에 우회했지만, 에러 메시지를 원인으로 착각한 탓에 진짜 이유는 2주 뒤에야 알게 됐습니다.

관련도 97%

집에서 놀던 노트북 두 대를 CI 러너로 만들었습니다 — 라벨로 폴백을 만드는 법

맥북 한 대로는 CI 큐가 밀렸습니다. 방치돼 있던 Proxmox 홈랩 서버와 윈도우 노트북을 러너로 붙이면서, 네이티브 폴백이 없는 GitHub Actions에서 라벨만으로 폴백을 만든 과정을 정리합니다.

관련도 96%

캐시를 껐더니 CI가 빨라졌습니다 — 최적화가 손해가 되는 조건

의존성 캐시를 끄자 작업당 4분이 사라졌습니다. 캐시는 매번 새로 만들어지는 기계를 전제로 설계된 장치인데, 제 러너는 사라지지 않는 기계였습니다. 전제가 다르면 최적화는 순손실이 됩니다.

관련도 96%