앞 글에서 GitHub Actions의 실행 파이프라인 구조와, 측정 → 실행 횟수 줄이기 → 캐시 → 병렬화 → 러너 선택 순서의 튜닝 기법을 정리했습니다. 이 글은 그 기법을 제 개인 저장소 다섯 곳에 적용하며 측정한 기록입니다. 기법의 원리와 주의점은 앞 글에 있으므로, 여기서는 각 저장소에서 무엇을 적용했고 결과가 어땠는지에 집중합니다.
대상은 benelog/flashcard, benelog/spider-silk, benelog/pdf-refinery, benelog/spring-jdbc-book, benelog/til입니다. 모두 공개 저장소라 4 vCPU / 16GB 사양의 표준 Linux 러너에서 실행됐습니다. 측정값은 2026년 8월 28일에 확인한 실제 실행 기록에서 가져왔습니다.
1. spider-silk: 측정으로 찾은 병목
spider-silk의 Publish 워크플로에 앞 글의 gh run view 명령을 돌린 결과입니다.
JOB publish: 354s
Set up job: 3s
Run actions/checkout@v7: 1s
Run actions/setup-java@v4: 0s
Run gradle/actions/setup-gradle@v6: 9s
Run ./gradlew build: 58s
Run ./gradlew publishAllPublicationsToGitHubPackagesRepository: 276s
Post Run gradle/actions/setup-gradle@v6: 3s
전체 354초 중 276초를 GitHub Packages에 아티팩트를 올리는 데 씁니다. 빌드는 58초입니다. Gradle 빌드 캐시를 아무리 잘 맞춰도 이 워크플로는 6분에서 5분으로밖에 줄지 않습니다. 측정하지 않고 "Gradle 빌드가 느리다"고 짐작해서 캐시 설정부터 손댔다면, 효과가 거의 없는 곳에 시간을 쓰게 됐을 것입니다.
2. flashcard: 트리거 필터와 중복 실행 취소
flashcard의 CI는 Go 코드를 검사하는 워크플로라, 원고 디렉터리만 고쳤을 때는 실행하지 않도록 paths-ignore를 걸었습니다.
on:
push:
branches: [main, release]
paths-ignore:
- 'book/**'
- 'book-template/**'
pull_request:
paths-ignore:
- 'book/**'
- 'book-template/**'
workflow_dispatch:
같은 브랜치에 커밋을 연달아 밀 때의 중복 실행은 concurrency로 취소합니다.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
대기 시간도 확인했습니다.
실행 생성이 14:04:15Z, 잡 시작이 14:04:18Z로 대기가 3초였습니다.
개인 저장소라 러너 배정 대기는 문제가 아니었고, 튜닝 대상은 실행 시간 쪽임을 확인했습니다.
잡 분리의 준비 비용도 이 저장소에서 확인할 수 있습니다.
Set up job 1초, 체크아웃 2초, actions/setup-go 7초로 실제 작업 전에 10초를 씁니다.
잡을 나누면 이 10초를 잡마다 다시 내므로, 이 정도 규모의 워크플로에서는 잡 분리가 이득이 되기 어렵습니다.
3. spring-jdbc-book: 경로 필터와 캐시 손익 실험
spring-jdbc-book은 예제 코드가 바뀔 때만 테스트를 돌리도록 paths로 대상을 지정했습니다.
워크플로 파일 자신을 목록에 넣어 둔 점이 중요합니다. 이렇게 해야 워크플로를 고쳤을 때 그 변경이 검증됩니다.
on:
push:
branches: [main]
paths:
- 'examples/**'
- '.github/workflows/test-examples.yml'
3.1. 캐시가 잡 시간을 줄이지 못한 실험
이 저장소의 테스트 워크플로를 4분 간격으로 두 번 실행해 캐시의 손익을 쟀습니다. 첫 실행에는 복원할 캐시가 없었고, 두 번째 실행은 첫 실행이 저장해 둔 캐시를 복원했습니다.
| 단계 | 1회차 | 2회차 |
|---|---|---|
Set up Gradle (캐시 복원) |
3초 |
13초 |
Run tests |
113초 |
99초 |
Post Set up Gradle (캐시 저장) |
39초 |
40초 |
잡 전체 |
161초 |
159초 |
캐시 덕분에 테스트 실행은 113초에서 99초로 14초 줄었습니다. 그런데 복원에 10초가 더 들고 저장 시간은 그대로라, 잡 전체로는 161초에서 159초가 되어 차이가 없었습니다. 이 저장소의 예제는 의존성이 적고 Testcontainers로 PostgreSQL을 띄우는 시간이 테스트 시간의 대부분이라, 캐시로 줄일 수 있는 몫이 애초에 작았습니다. 두 번만 비교한 값이라 테스트 시간 14초 차이에는 러너 성능 편차도 섞여 있을 수 있습니다. 그래도 캐시 저장에 매번 40초 가까이 든다는 점은 두 실행에서 같았습니다.
3.2. 실패했을 때만 올리는 테스트 리포트
아티팩트는 필요할 때만 올립니다. 이 워크플로는 테스트 리포트를 실패했을 때만 업로드합니다. 성공한 실행에서는 이 단계가 0초로 끝납니다.
- name: Upload test reports on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-reports
path: examples/*/build/reports/tests/test
4. pdf-refinery: 매트릭스 병렬화와 캐시 후보
pdf-refinery는 Python 세 버전을 매트릭스로 돌립니다.
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
실행 기록을 보면 세 잡이 각각 305초, 240초, 308초 걸렸습니다. 러너 사용 시간의 합은 853초지만, 세 잡이 동시에 시작해서 실제로 기다린 시간은 가장 느린 308초입니다. 버전별 검증이라는 목적을 러너 준비 비용(잡당 10초 안팎)만 더 내고 체감 시간 증가 없이 달성한 셈입니다.
캐시는 아직 붙이지 않았습니다.
매 실행마다 pip install -e '.[dev]'에 41~50초를 쓰는데, 이 시간은 거의 전부 다운로드라서 캐시를 붙이면 줄어들 가능성이 높습니다.
spring-jdbc-book과 달리 이쪽은 캐시가 이득일 후보입니다.
5. til: 배포 워크플로의 concurrency 설정
til의 Cloud Run 배포 워크플로는 중간에 취소되면 어중간한 상태로 남을 수 있습니다.
그래서 cancel-in-progress를 켜지 않고, 그룹만 묶어 한 번에 하나만 돌게 했습니다.
# 연달아 푸시해도 배포가 서로 앞지르지 않게 한 번에 하나만 돌린다.
concurrency:
group: deploy-cloud-run
cancel-in-progress: false
이 설정에서 진행 중인 실행은 끝까지 돌고 새 실행은 대기합니다.
다만 기본값으로는 한 그룹에서 대기할 수 있는 실행이 하나뿐이라, 커밋 세 개를 연달아 밀면 첫 번째는 배포되고 두 번째는 취소되며 세 번째만 배포됩니다.
중간 실행까지 모두 돌려야 하는 워크플로라면 앞 글에서 다룬 queue: max를 고려해야 합니다.
6. 정리
다섯 저장소에 적용한 내용과 결과입니다.
| 저장소 | 적용·측정한 것 | 결과 |
|---|---|---|
spider-silk |
단계별 소요 시간 측정 |
병목은 빌드(58초)가 아니라 GitHub Packages 업로드(276초). 캐시 튜닝으로는 줄일 수 없는 구조 |
flashcard |
|
원고만 고친 커밋은 실행 생략. 대기는 3초라 문제가 아님 |
spring-jdbc-book |
|
캐시를 붙여도 잡 전체는 161초 → 159초로 효과 없음 |
pdf-refinery |
매트릭스 병렬화 |
러너 시간 합 853초를 체감 308초로. |
til |
배포 워크플로의 |
|
다섯 저장소에서 공통으로 확인한 것은 측정이 먼저라는 점입니다. spider-silk처럼 병목이 짐작과 다른 곳에 있기도 하고, spring-jdbc-book처럼 정석으로 알려진 캐시가 측정해 보면 이득이 없기도 합니다. 기법을 적용하기 전과 후의 잡 전체 시간을 비교하는 습관이 어떤 설정보다 효과가 컸습니다.
7. 참고 자료
-
GitHub Actions의 실행 구조와 워크플로 튜닝 기법 — 이 글에서 적용한 기법들의 원리와 주의점
이 포스트는 Claude Code와 정상혁이 함께 작성했습니다.
Twitter
Facebook
Reddit
LinkedIn
Email