GitHub Actions 완벽 가이드 | CI/CD·자동화·Workflow·배포·실전 활용
이 글의 핵심
GitHub Actions 완벽 가이드에 대해 정리한 개발 블로그 글입니다. GitHub Actions로 CI/CD를 구축하는 완벽 가이드입니다. Workflow 작성, 테스트 자동화, 배포 파이프라인, Secrets 관리에 더해 Runner 실행 환경, 매트릭스 전략, 캐시·아티팩트,… 개념과 예제 코드를 단계적으로 다루며, 실무·학습에 참고할 수 있도록 구성했습니다. 관련 키워드:…
이 글의 핵심
GitHub Actions로 CI/CD를 구축하는 완벽 가이드입니다. Workflow 작성, 테스트 자동화, 배포 파이프라인, Secrets 관리에 더해 Runner 실행 환경, 매트릭스 전략, 캐시·아티팩트, GITHUB_TOKEN 권한, 프로덕션 운영 패턴까지 심화 내용을 담았습니다.
실무 경험 공유: Jenkins에서 GitHub Actions로 전환하면서, 설정이 간소화되고 배포 속도가 3배 빨라진 경험을 공유합니다.
들어가며: “CI/CD가 복잡해요”
실무 문제 시나리오
시나리오 1: Jenkins 설정이 어려워요
서버 관리가 필요합니다. GitHub Actions는 클라우드 기반입니다. 시나리오 2: 배포가 느려요
순차 실행이 느립니다. GitHub Actions는 병렬 실행을 지원합니다. 시나리오 3: 비용이 높아요
서버 비용이 듭니다. GitHub Actions는 Public 저장소는 무료입니다.
1. GitHub Actions란?
핵심 특징
GitHub Actions는 CI/CD 자동화 플랫폼입니다. 주요 장점:
- Git 통합: GitHub 네이티브
- 무료: Public 저장소 무료
- Marketplace: 수천 개의 Action
- 병렬 실행: 빠른 빌드
- 간단한 설정: YAML 파일
2. 기본 Workflow
Hello World
# .github/workflows/hello.yml
name: Hello World
on:
push:
branches: [main]
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Say hello
run: echo "Hello, GitHub Actions!"
3. CI Workflow
Node.js 테스트
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build
run: npm run build
4. 배포 Workflow
Vercel 배포
# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install -g vercel
- name: Deploy to Vercel
run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Docker 배포
name: Build and Push Docker
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: user/app:latest
5. Secrets 관리
설정
# GitHub → Settings → Secrets and variables → Actions
# New repository secret
사용
steps:
- name: Deploy
run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
6. 조건부 실행
if 조건
jobs:
deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy
run: ./deploy.sh
notify:
runs-on: ubuntu-latest
if: failure()
steps:
- name: Send notification
run: ./notify.sh
7. 캐싱
의존성 캐싱
# 실행 예제
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
커스텀 캐싱
steps:
- uses: actions/cache@v3
with:
path: |
~/.npm
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-nextjs-
8. Marketplace Actions
인기 Actions
# Checkout
- uses: actions/checkout@v4
# Node.js 설정
- uses: actions/setup-node@v4
# 캐싱
- uses: actions/cache@v3
# 아티팩트 업로드
- uses: actions/upload-artifact@v3
with:
name: build
path: dist/
# 슬랙 알림
- uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Deployment successful!"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
9. 실전 예제
Monorepo CI
name: Monorepo CI
on: [push, pull_request]
jobs:
changes:
runs-on: ubuntu-latest
outputs:
web: ${{ steps.filter.outputs.web }}
api: ${{ steps.filter.outputs.api }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
web:
- 'apps/web/**'
api:
- 'apps/api/**'
test-web:
needs: changes
if: needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test --workspace=web
test-api:
needs: changes
if: needs.changes.outputs.api == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test --workspace=api
10. Workflow 실행 환경(Runner)의 내부
GitHub Actions에서 Job은 반드시 Runner 위에서 실행됩니다. 호스트형(GitHub 호스티드) Runner는 Job 시작 시 깨끗한 실행 환경을 제공하는 것이 기본 철학이며, 이는 “이전 빌드 잔재”로 인한 비결정적 실패를 줄이기 위한 설계입니다.
호스트형 Runner의 특성
runs-on:ubuntu-latest,windows-latest,macos-latest등 이미지 라벨로 OS·런타임 스택이 결정됩니다. 동일 라벨이라도 시간이 지나면 기본 소프트웨어 구성이 바뀔 수 있으므로, 재현성이 중요하면 컨테이너 Job(container:) 또는 툴체인을 명시적으로 고정하는 편이 안전합니다.- 에페메럴(ephemeral)에 가까운 동작: Job 단위로 작업 디렉터리와 러너 프로세스가 분리됩니다. 같은 Runner 인스턴스를 여러 팀이 공유한다는 느낌이 아니라, Job마다 새로운 머신에서 시작한다에 가깝게 이해하면 운영 관점이 정리됩니다(셀프호스티드는 예외적으로 정책이 다름).
- 환경 변수:
GITHUB_REPOSITORY,GITHUB_REF,GITHUB_SHA,GITHUB_WORKFLOW,RUNNER_OS,RUNNER_ARCH등은 스크립트에서 조건 분기·아티팩트 이름·캐시 키에 자주 쓰입니다.CI=true는 대부분의 CI에서 관례적으로 설정됩니다. - 네트워크: 인터넷 아웃바운드는 일반적으로 가능하지만, 조직 정책·방화벽·프록시 이슈는 셀프호스티드에서 특히 드러납니다. 아티팩트·캐시 업로드/다운로드는 GitHub의 관리형 엔드포인트와 통신합니다.
컨테이너 Job과 서비스 컨테이너
애플리케이션이 특정 리눅스 배포판/라이브러리 버전에 묶여 있으면 container: 이미지로 실행 환경을 고정할 수 있습니다. 데이터베이스·Redis 등은 services:로 사이드카 컨테이너를 띄워 통합 테스트를 구성합니다. 이 패턴은 “호스트 이미지 업그레이드로 테스트가 갑자기 깨짐”을 줄입니다.
jobs:
integration:
runs-on: ubuntu-latest
container:
image: node:20-bookworm
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app_test
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
셀프호스티드 Runner 한 줄 요약
조직 내부망 리소스 접근·GPU·대용량 빌드가 필요할 때 쓰입니다. 격리·자동 패치·토큰 유출 방지를 운영 정책으로 명시하지 않으면 사고로 이어지기 쉬우므로, 프로덕션에서는 Runner 그룹 권한, 라벨 기반 라우팅, 정기 이미지 리셋을 함께 설계합니다.
11. 매트릭스 전략과 조합
strategy.matrix는 동일 Job 정의를 여러 축으로 복제해 병렬 검증을 수행합니다. 단순히 node-version만 두는 수준을 넘어, 운영체제 × 런타임 × 플래그 조합까지 표현할 수 있습니다.
기본 매트릭스와 fail-fast
fail-fast 기본값은 true입니다. 매트릭스 조합 하나라도 실패하면 나머지 조합을 즉시 취소합니다. 빠른 피드백에는 유리하지만, “어떤 OS에서만 깨지는지”를 한 번에 보고 싶다면 fail-fast: false를 고려합니다.
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 4
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci && npm test
include로 조합 확장, exclude로 제거
include: 존재하지 않던 축 조합을 추가하거나, 특정 조합에만 변수를 덧입힙니다(예: 특정 OS에서만extra-env설정).exclude: 불필요한 조합(예: Windows × 구버전 Node)을 빌드 낭비 없이 제거합니다.
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
node: [18, 20]
include:
- os: ubuntu-latest
node: 22
experimental: true
exclude:
- os: macos-latest
node: 18
동적 매트릭스
리포지토리 구조나 패키지 목록이 자주 바뀌면, 선행 Job에서 JSON을 생성해 fromJSON으로 매트릭스를 채우는 패턴이 있습니다. 이 경우 출력 크기 제한과 가독성(디버깅 시 어떤 조합이 생성됐는지)을 함께 챙겨야 합니다.
12. 아티팩트와 캐시 메커니즘
둘 다 “빌드를 빠르게”와 연관되지만, 목적과 수명·일관성 모델이 다릅니다. 혼동하면 캐시 오염이나 보안 사고로 이어질 수 있습니다.
캐시(actions/cache 계열)
- 목적: 의존성·빌드 중간 산출물을 키 기반으로 복원해 네트워크·CPU를 아낍니다.
- 키 설계:
hashFiles('**/package-lock.json')처럼 입력 파일 해시를 섞으면 lockfile이 바뀔 때만 새 캐시가 생깁니다.restore-keys로 부분 일치 복원을 허용할 수 있으나, 완전 재현은 보장되지 않을 수 있음을 전제해야 합니다. - 범위: 캐시는 브랜치·워크플로 특성에 따라 공유·격리 규칙이 적용됩니다. “언제나 최신 캐시”가 아니라 적중률과 안전성의 트레이드오프로 이해하는 것이 좋습니다.
- 민감 정보 금지: 캐시에는 시크릿이나 토큰을 넣지 않습니다. 암호화 저장소가 아니라 속도 최적화용 스토리지입니다.
아티팩트(upload-artifact / download-artifact)
- 목적: Job 간·워크플로 간에 빌드 산출물을 전달합니다(예:
dist/, 테스트 리포트, 컨테이너 이미지 tar). - 수명: 보존 기간(retention)이 있으며, 저장 용량은 조직 정책에 영향을 받습니다. 장기 보관이 필요하면 릴리스 자산이나 외부 객체 스토리지로 옮기는 편이 맞습니다.
- 압축: 대용량 디렉터리는 불필요한 파일을 제외하고, 필요하면 아카이브 단계를 별도로 둡니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: web-dist
path: dist/
retention-days: 7
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: web-dist
path: dist/
- name: Deploy
run: ./deploy.sh
정리: 무엇을 어디에 둘까
| 구분 | 캐시 | 아티팩트 |
|---|---|---|
| 주 목적 | 재빌드 가속 | Job 간 산출물 전달 |
| 키/이름 | 해시 기반 키 | 아티팩트 이름·버전 |
| 민감 데이터 | 금지 | 금지(동일) |
13. GITHUB_TOKEN과 권한(permissions)
각 Job은 기본적으로 GITHUB_TOKEN으로 GitHub API에 접근합니다. 이 토큰은 편리하지만 강력하므로, 최소 권한 원칙을 Workflow에 명시하는 것이 프로덕션 기본값입니다.
기본 동작과 위험
과거에는 광범위한 권한이 기본이었으나, 저장소 설정과 워크플로 설계에 따라 기본 권한을 읽기 전용으로 낮추는 구성이 권장됩니다. Workflow가 Issue/PR에 코멘트를 달거나 릴리스를 올리지 않는다면 contents: read만으로 충분한 경우가 많습니다.
permissions 블록으로 최소화
워크플로 전체 또는 Job 단위에 permissions를 둡니다. 예: 콘텐츠 배포가 필요할 때만 쓰기 권한을 부여합니다.
permissions:
contents: read
pull-requests: read
jobs:
release:
permissions:
contents: write # 이 Job에서만 태그/릴리스에 필요한 쓰기 허용
id-token: write # OIDC로 클라우드에 키 없이 인증할 때
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ...
OIDC(id-token: write)
클라우드 공급자(AWS, Azure, GCP 등)와 단기 자격 증명을 주고받을 때 id-token: write가 필요합니다. 장기 액세스 키를 Secrets에 장기 보관하는 것보다 OIDC 연동이 운영·감사 측면에서 유리한 경우가 많습니다.
포크 PR과의 주의
포크에서 오는 pull_request 이벤트는 쓰기 권한이 제한되는 경우가 있습니다. “봇이 라벨을 달거나 코멘트에 리포트를 남긴다” 같은 기능은 이벤트 종류·권한 모델을 함께 설계해야 합니다.
14. 프로덕션에서 통하는 GitHub Actions 패턴
동시성 제어(concurrency)
동일 브랜치에 연속 푸시가 쌓일 때, 이전 배포가 끝나기 전에 새 배포가 겹치면 상태가 꼬일 수 있습니다. concurrency.group와 cancel-in-progress로 최신 커밋만 살리거나, 반대로 파이프라인을 직렬화합니다.
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true
환경(Environments)과 승인 게이트
environment: production처럼 환경을 지정하면 GitHub의 필수 리뷰어·대기 시간·배포 브랜치 제한을 걸 수 있습니다. 인프라 팀이 좋아하는 이유는 “YAML만이 아니라 플랫폼 정책으로 배포를 제어할 수 있다”는 점입니다.
재사용 워크플로(workflow_call)
여러 저장소에서 동일한 빌드 파이프라인을 쓰면 workflow_call로 중앙 워크플로에 입력(inputs)·시크릿(secrets)을 넘기는 구조가 깔끔합니다. 변경 한 번으로 조직 전체 표준이 따라옵니다.
액션 고정(Pinning)
@v4 태그는 편하지만, 공급망 관점에서는 @ 커밋 SHA로 고정하고 릴리스 노트를 따라가는 팀도 많습니다. Dependabot으로 업데이트 PR을 자동화하면 편의성과 재현성을 같이 가져갈 수 있습니다.
분리된 Job 설계
- lint/test는 빠르게, build는 산출물을 아티팩트로, deploy는 환경 승인과 OIDC로. 한 Job에 모든 것을 넣으면 실패 시 원인 추적과 재시도 단위가 커집니다.
관측 가능성
workflow_dispatch 입력, Job 요약, 실패 시 아티팩트로 로그·리포트를 남기면, 온콜이 재현에 쓸 정보를 빠르게 얻습니다.
정리 및 체크리스트
핵심 요약
- GitHub Actions: CI/CD 자동화
- Git 통합: GitHub 네이티브
- 무료: Public 저장소 무료
- Marketplace: 수천 개의 Action
- 병렬 실행: 빠른 빌드
- 간단한 설정: YAML 파일
- 실행 환경: 호스트형 Runner의 에페메럴 특성, 컨테이너·서비스로 재현성 확보
- 매트릭스:
include/exclude,fail-fast, 동적 매트릭스로 조합 관리 - 캐시 vs 아티팩트: 가속용 캐시와 Job 간 전달용 아티팩트를 목적에 맞게 분리
- 권한:
permissions와 OIDC로GITHUB_TOKEN최소화 - 프로덕션:
concurrency, Environments, 재사용 워크플로, 액션 고정
구현 체크리스트
- Workflow 파일 작성
- CI 구현
- 배포 파이프라인 구현
- Secrets 설정
- 캐싱 추가
- 조건부 실행 설정
- Marketplace Actions 활용
- Runner/OS·런타임 고정 전략(컨테이너 또는 명시적 버전) 검토
- 매트릭스 축·
fail-fast·병렬 상한(max-parallel) 정하기 - 아티팩트 보존 기간·캐시 키 설계(시크릿 미포함) 확인
-
permissions최소화 및 필요 시 OIDC 연동 -
concurrency·environment·재사용 워크플로 등 운영 패턴 적용
같이 보면 좋은 글
이 글에서 다루는 키워드
GitHub Actions, CI/CD, Automation, Workflow, DevOps, Deployment, Testing
내부 동작과 핵심 메커니즘
이 글의 주제는 「GitHub Actions 완벽 가이드 | CI/CD·자동화·Workflow·배포·실전 활용」입니다. 앞선 튜토리얼을 구현·런타임 관점에서 다시 압축합니다. 구성 요소 간 책임 분리와 관측 가능한 지점을 기준으로 “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)·동시성이 어디서 터지는가”를 한 장면으로 그리면 장애 분석이 빨라집니다.
처리 파이프라인(개념도)
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
경계에서의 지연·실패(시퀀스 관점)
sequenceDiagram participant C as 클라이언트/호출자 participant B as 경계(프로세스·런타임·게이트웨이) participant D as 의존성(외부 API·DB·큐) C->>B: 요청/이벤트 B->>D: 조회·쓰기·RPC D-->>B: 지연·부분 실패·재시도 가능 B-->>C: 응답 또는 오류(코드·상관 ID)
알고리즘·프로토콜·리소스 관점 체크포인트
- 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(버퍼 경계, 프로토콜 상태, 트랜잭션 격리, 파일 디스크립터 상한)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 동일 입력에 동일 출력이 보장되는 순수 층과, 시간·네트워크·스레드 스케줄에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합, GC·할당, 캐시 미스처럼 누적 비용을 의심 목록에 넣습니다.
- 백프레셔: 생산자가 소비자보다 빠를 때(소켓 버퍼, 큐 깊이, 스트림) 어디서 어떤 신호로 속도를 줄일지 정의합니다.
프로덕션 운영 패턴
실서비스에서는 기능과 함께 관측·배포·보안·비용·규제가 동시에 요구됩니다.
| 영역 | 운영 관점 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율/지연 분위수(p95/p99), 의존성 타임아웃·재시도가 대시보드에 보이는가 |
| 안전성 | 입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가 |
| 성능 | 캐시 계층·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리/블루그린, 마이그레이션 호환성·플래그가 문서화되어 있는가 |
| 용량 | 피크 트래픽·디스크·파일 디스크립터·스레드 풀 상한을 주기적으로 검증하는가 |
스테이징은 데이터 양·네트워크 RTT·동시성을 가능한 한 프로덕션에 가깝게 맞추는 것이 재현율을 높입니다.
확장 예시: 엔드투엔드 미니 시나리오
「GitHub Actions 완벽 가이드 | CI/CD·자동화·Workflow·배포·실전 활용」을 실제 배포·운영 흐름으로 옮긴 체크리스트형 시나리오입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.
- 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드 표를 API 또는 이벤트 경계에 둔다.
- 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 한 화면(로그+메트릭+트레이스)에서 추적한다.
- 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
- 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지(또는 피처 플래그) 확인한다.
- 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값이 기대 범위인지 본다.
의사코드 스케치(프레임워크 무관)
handle(request):
ctx = newCorrelationId()
validated = validateSchema(request) // 경계에서 거절
authorize(validated, ctx) // 권한·테넌트
result = domainCore(validated) // 순수에 가까운 규칙
persistOrEmit(result, idempotentKey) // I/O: 멱등·재시도 정책
recordMetrics(ctx, latency, outcome)
return result
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스, 타임아웃, 외부 의존성 불안정, DNS | 최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검 |
| 성능 저하 | N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납 | 상한·TTL·힙/FD 스냅샷 비교 |
| 빌드·배포만 실패 | 환경 변수, 권한, 플랫폼 차이, lockfile | CI 로그와 로컬 diff, 런타임·이미지 버전 핀 |
| 설정이 로컬과 다름 | 프로필·시크릿·기본값, 지역 리전 | 단일 소스(예: 스키마 검증된 설정)와 배포 매트릭스 표준화 |
| 데이터 불일치 | 비멱등 재시도, 부분 쓰기, 캐시 무효화 누락 | 멱등 키·아웃박스·트랜잭션 경계 재검토 |
권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.
자주 묻는 질문 (FAQ)
Q. Jenkins와 비교하면 어떤가요?
A. GitHub Actions가 훨씬 간단하고 GitHub 통합이 완벽합니다. Jenkins는 더 많은 커스터마이징을 제공합니다.
Q. 무료로 사용할 수 있나요?
A. 네, Public 저장소는 무료입니다. Private 저장소는 2,000분/월 무료입니다.
Q. Self-hosted Runner를 사용할 수 있나요?
A. 네, 자체 서버에서 실행할 수 있습니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, 수많은 오픈소스와 기업에서 사용하고 있습니다.
Q. 캐시와 아티팩트 중 무엇을 써야 하나요?
A. 의존성·중간 산출물 가속은 캐시, Job 간 빌드 결과물 전달은 아티팩트가 맞습니다. 시크릿은 둘 다 넣지 않습니다.
Q. GITHUB_TOKEN 권한은 어떻게 줄이나요?
A. 워크플로 또는 Job에 permissions를 선언해 읽기 위주로 두고, 릴리스·OIDC 등 필요한 Job에만 쓰기·id-token을 부여합니다.
Q. 매트릭스에서 일부 조합만 빼고 싶어요.
A. exclude로 조합을 제거하거나, include로 필요한 조합만 추가하는 방식으로 표현합니다. fail-fast로 실패 시 나머지 조합을 취소할지도 함께 정합니다.