GitHub Actions 강좌 #10 운영 패턴: 경로 필터, concurrency, 디버깅, 비용 점검
문법과 파이프라인은 갖춰졌습니다. 마지막 편은 그것을 매일 굴릴 때 필요한 운영 습관들입니다. 하나하나는 작은 설정이지만, 없으면 “문서만 고쳤는데 전체 CI가 돈다”, “배포 두 개가 겹쳐서 꼬였다”, “멈춘 잡이 여섯 시간 과금됐다” 같은 잔사고가 계속됩니다. 시리즈 곳곳에서 스쳐 간 조각들을 운영 관점으로 모아 정리하겠습니다.
paths 필터: 바뀐 것만 깨우기 #
모노레포(또는 문서와 코드가 한 저장소인 보통의 프로젝트)에서 모든 푸시가 모든 워크플로를 깨우면 시간과 비용이 낭비됩니다. 트리거에 경로 조건을 겁니다.
on:
push:
branches: [main]
paths:
- "backend/**"
- ".github/workflows/backend.yml" # 워크플로 자신의 변경도 포함paths-ignore로 반대 방향(문서 변경 제외 등)도 됩니다. 관례 하나를 권하면, 워크플로 자신의 경로를 paths에 포함하는 것입니다. 워크플로를 고친 푸시가 그 워크플로를 깨우지 않아 “고쳤는데 검증이 안 된” 채 병합되는 헛발질을 막아 줍니다. 주의할 것은 필수 체크와의 조합입니다. 브랜치 보호로 “이 체크는 반드시 통과"를 걸어 둔 워크플로가 paths에 걸려 아예 실행되지 않으면 PR이 영원히 대기합니다. 이 경우 해당 체크를 조건부로 만들지 말거나, 경로별 조건은 잡 수준 if로 옮기는 조정이 필요합니다. 테라폼 운영 강좌 #1에서 인프라 경로에만 plan을 걸었던 것이 이 필터의 실전 사례입니다.
concurrency: 겹침을 정책으로 #
같은 대상에 실행이 겹칠 때의 정책이 concurrency입니다. 그룹 키가 같은 실행은 동시에 하나만 돌고, 대기 중인 것은 최신 하나만 남습니다.
# CI: 같은 PR의 이전 실행은 취소 (최신 커밋만 의미 있음)
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
# 배포: 진행 중인 배포는 끝까지 (중단이 더 위험)
concurrency:
group: deploy-prod
cancel-in-progress: false판단 기준은 중단해도 되는 작업인가입니다. PR CI는 옛 커밋의 결과가 무의미하니 취소가 이득이고, 배포·마이그레이션·테라폼 apply는 중간에 끊기면 어중간한 상태가 남으니 끝까지 돌리고 다음이 기다리게 합니다. 그룹 키 설계도 같은 논리입니다. PR별로 나눌 것(github.ref)인지, 전역 하나(deploy-prod)로 직렬화할 것인지가 “무엇이 겹치면 안 되는가"의 답과 일치해야 합니다.
timeout: 기본값 6시간을 믿지 않기 #
잡의 기본 타임아웃은 6시간(360분)입니다. 멈춘 테스트, 응답 없는 외부 API를 기다리는 스텝이 있으면 여섯 시간 동안 러너를 잡고 과금됩니다. 모든 잡에 상한을 명시하는 것을 습관으로 삼습니다.
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15값은 “정상 실행의 두세 배” 정도로 잡으면 됩니다. 타임아웃으로 죽는 잡은 어차피 비정상이고, 일찍 죽어야 일찍 발견됩니다.
디버깅: 로그를 더 키우는 법 #
실패 로그가 부족할 때 쓸 도구를 순서대로 정리합니다.
- 재실행: 실행 화면의 Re-run 메뉴는 실패한 잡만 다시 돌리는 옵션을 줍니다. 일시적 네트워크 실패 판별의 첫 수단입니다.
- 디버그 로그: 저장소 secrets(또는 variables)에
ACTIONS_STEP_DEBUG를true로 넣으면 스텝 내부의 상세 로그가,ACTIONS_RUNNER_DEBUG는 러너 수준 로그가 켜집니다. 재실행 다이얼로그의 “Enable debug logging” 체크로 일회성으로 켤 수도 있어 이쪽이 더 간편합니다. - 컨텍스트 덤프: #2의
toJSON()출력은 “왜 if가 기대와 다르게 평가됐나” 계열의 디버깅에 가장 빠른 길입니다. - 로컬 실행 도구: act 같은 로컬 실행 도구로 푸시 없이 워크플로를 굴려 볼 수 있습니다. 러너 환경과 완전히 같지는 않아 최종 확인은 실제 실행이 필요하지만, YAML 문법 시행착오의 왕복 시간을 크게 줄여 줍니다.
비용 점검: 어디서 새는지 보는 화면 #
조직·계정 Settings의 Billing에서 Actions 사용량을 저장소·워크플로·러너 OS별로 확인할 수 있습니다. 점검 순서는 단순합니다. 사용량 상위 워크플로를 열어 #4의 도구들이 적용됐는지 봅니다. 캐시가 없는 의존성 설치, 불필요한 매트릭스 축(특히 macOS), paths 필터 없는 전량 실행, 타임아웃 없는 장시간 잡이 단골 누수 지점입니다. 프라이빗 저장소의 실행량이 계속 늘면 #8의 셀프호스티드 손익분기 검토가 다음 단계입니다.
시리즈를 마치며 #
열 편을 정리하면 이렇습니다. 구조와 문법을 잡고(#1〜#2), 비밀과 관문을 세우고(#3), 실행을 늘리고 줄이는 법을 배우고(#4), 부품화하고(#5), 이미지 빌드와 AWS 배포 파이프라인을 조립하고(#6〜#7), 러너와 보안의 원칙을 세우고(#8〜#9), 오늘 운영 습관으로 마감했습니다. 이 시리즈의 워크플로들이 실제 인프라와 만나는 사례는 테라폼 트랙에 있고, GitHub 자체를 자격증으로 정리하고 싶다면 GitHub Foundations가 이웃 시리즈입니다.
이번 글에서 다룬 내용입니다.
- paths 필터로 바뀐 부분만 깨우되, 워크플로 자신의 경로를 포함하고 필수 체크와의 조합을 주의합니다
- concurrency의 기준은 “중단해도 되는가"입니다. CI는 취소, 배포는 완주 후 직렬화입니다
- 기본 타임아웃 6시간을 믿지 말고 모든 잡에 timeout-minutes를 명시합니다
- 디버깅은 재실행, 디버그 로그 토글, 컨텍스트 덤프, 로컬 실행 도구 순서로 씁니다
- 비용은 Billing 화면에서 상위 워크플로부터 점검합니다. 캐시 부재, macOS 매트릭스, 필터 없는 실행이 단골 누수입니다