← Git 강의 목록으로
🔀
Git·GitHub 심화
workflow yml · triggers · matrix · cache · secrets

8단원 — GitHub Actions

GitHub Actions는 코드 push, PR 생성, 일정 시간 등 이벤트에 반응해 자동으로 빌드·테스트·배포를 실행하는 CI/CD 플랫폼입니다. YAML 파일 하나로 복잡한 파이프라인을 정의할 수 있으며, 오픈 소스 액션을 재사용해 빠르게 구성할 수 있습니다.

actionsciworkflow
소요 시간
1~2시간
난이도
📊 중급
선수 조건
🎯 7단원
결과물
GitHub Actions 로 CI 자동화

이 강의에서 배우는 것

  • 1GitHub Actions 워크플로우 YAML의 기본 구조를 이해하고 작성할 수 있다.
  • 2`push`·`pull_request` 트리거와 수동 트리거(`workflow_dispatch`)를 설정할 수 있다.
  • 3매트릭스(matrix)로 여러 OS/버전 조합에서 병렬 테스트를 실행할 수 있다.
  • 4의존성 캐시로 워크플로우 실행 시간을 단축할 수 있다.
  • 5artifacts로 빌드 산출물을 저장하고, secrets로 민감 정보를 안전하게 사용할 수 있다.

핵심 개념

1) 워크플로우 구조

yaml
name: 워크플로우 이름

on:                      # 트리거
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  job-name:
    runs-on: ubuntu-latest    # 실행 환경
    steps:
      - uses: actions/checkout@v4           # 액션 사용
      - name: 단계 이름
        run: echo "Hello"                   # 셸 명령

2) 트리거 종류

yaml
on:
  push:                         # push 이벤트
    branches: [main, develop]
    paths: ['src/**']           # 특정 경로 변경 시만
  pull_request:
    types: [opened, synchronize, reopened]
  schedule:
    - cron: '0 9 * * 1'        # 매주 월요일 09:00 UTC
  workflow_dispatch:            # 수동 실행 (UI 버튼)
    inputs:
      environment:
        type: choice
        options: [staging, production]

3) 매트릭스 전략

yaml
strategy:
  matrix:
    os: [ubuntu-latest, windows-latest, macos-latest]
    node: [18, 20, 22]
  fail-fast: false       # 하나 실패해도 나머지 계속 실행

runs-on: ${{ matrix.os }}
steps:
  - uses: actions/setup-node@v4
    with:
      node-version: ${{ matrix.node }}

4) 캐시

yaml
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

5) Artifacts

yaml
- uses: actions/upload-artifact@v4
  with:
    name: build-output
    path: dist/
    retention-days: 7

# 다운로드
- uses: actions/download-artifact@v4
  with:
    name: build-output

6) Secrets

yaml
env:
  API_KEY: ${{ secrets.API_KEY }}
  DB_URL: ${{ secrets.DATABASE_URL }}

# GitHub → 저장소 Settings → Secrets and variables → Actions → New repository secret

예제로 보기

예제 1 — `ex01_hello.yml` : push 시 "Hello" 출력

yaml
name: Hello World

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Say Hello
        run: |
          echo "Hello, GitHub Actions!"
          echo "Repo: ${{ github.repository }}"
          echo "Branch: ${{ github.ref_name }}"
          echo "Actor: ${{ github.actor }}"

**실행 결과 (Actions 탭에서 확인)**

text
Hello, GitHub Actions!
Repo: username/my-repo
Branch: main
Actor: username

핵심: `github` 컨텍스트로 저장소·브랜치·사용자 정보를 가져올 수 있다.

예제 2 — `ex02_test.yml` : Node.js 프로젝트 CI

yaml
name: Node.js CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - 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

핵심: `npm ci`는 `package-lock.json`을 기준으로 정확히 설치해 재현성을 보장한다.

예제 3 — `ex03_matrix.yml` : OS·Node 버전 매트릭스

yaml
name: Matrix Build

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node-version: [18, 20, 22]
        exclude:
          - os: windows-latest
            node-version: 18   # 특정 조합 제외

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install and test
        run: |
          npm ci
          npm test

핵심: 3 × 3 = 9개(제외 1개 포함 시 8개) 조합이 병렬로 실행된다.

예제 4 — `ex04_cache.yml` : 캐시로 설치 시간 단축 + artifacts 저장

yaml
name: Build with Cache

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'          # 내장 캐시 (actions/cache 자동 설정)

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist-${{ github.sha }}
          path: dist/
          retention-days: 7

  deploy:
    needs: build                 # build 완료 후 실행
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - name: Download artifact
        uses: actions/download-artifact@v4
        with:
          name: dist-${{ github.sha }}
          path: dist/

      - name: Deploy
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
        run: echo "Deploying with secret key (masked)"

핵심: `needs`로 job 간 순서를 지정하고, secrets으로 민감 정보를 안전하게 전달한다.

다른 시각으로 보기

Actions 개념비유
workflow공장 생산 라인 설계도
job생산 라인의 각 작업장
step작업장에서의 세부 작업
action (`uses`)기성품 도구
matrix여러 공장에서 동시 생산
artifact완성품 포장 박스
secrets금고에 잠긴 열쇠

자주 하는 실수

  1. **`actions/checkout` 없이 코드 접근** — 워크플로우는 코드를 자동으로 가져오지 않는다.
  2. **secrets를 `echo`로 출력** — GitHub가 마스킹하지만 로그에 남을 수 있다.
  3. **캐시 key를 고정** — 의존성이 바뀌어도 캐시가 갱신되지 않는다; `hashFiles`로 동적 키를 사용한다.
  4. **`fail-fast: true` 기본값 방치** — 하나 실패하면 모든 matrix job이 취소된다.
  5. **`on: push` 없이 `workflow_dispatch` 만 설정** — 자동 실행이 되지 않는다.

정리

  • 워크플로우는 `.github/workflows/*.yml` 에 저장하며 이벤트 → job → step 구조다.
  • 매트릭스로 여러 환경 조합을 병렬 실행해 테스트 커버리지를 높인다.
  • `cache`로 의존성 설치 시간을 단축하고, `artifact`로 빌드 결과물을 저장한다.
  • `secrets`는 GitHub UI에서 설정하고, 워크플로우에서 `${{ secrets.NAME }}`으로 참조한다.
  • `needs`로 job 간 의존 관계를 설정해 순서를 제어한다.

직접 해 보기

bash
# Actions yml 파일은 GitHub 저장소에서 실행됩니다.
# 아래 명령으로 파일을 워크플로우 디렉토리에 복사하세요.
mkdir -p .github/workflows
cp 08_GitHub_Actions/src/ex01_hello.yml .github/workflows/
git add .github/workflows/ex01_hello.yml
git commit -m "ci: add hello workflow"
git push
# → GitHub 저장소 Actions 탭에서 결과를 확인하세요.

응용:

  1. `workflow_dispatch` 에 `input` 파라미터를 추가해 수동 실행 시 환경을 선택하게 해 보세요.
  2. `schedule` 트리거로 매일 자정에 실행되는 워크플로우를 만들어 보세요.

💻 예제 (examples)

실제로 실행해 결과를 확인할 수 있는 예제입니다.

ex01_hello.ymlpush 시 "Hello" 출력
CODE
name: Hello World

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Print environment info
        run: |
          echo "=== Hello, GitHub Actions! ==="
          echo "Repository : ${{ github.repository }}"
          echo "Branch     : ${{ github.ref_name }}"
          echo "Actor      : ${{ github.actor }}"
          echo "Commit SHA : ${{ github.sha }}"
          echo "Runner OS  : ${{ runner.os }}"

      - name: List files
        run: ls -la
ex02_test.ymlNode.js 프로젝트 CI
CODE
name: Node.js CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js 20
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint --if-present

      - name: Run tests
        run: npm test --if-present

      - name: Build
        run: npm run build --if-present

      - name: Report status
        if: always()
        run: |
          echo "Job status: ${{ job.status }}"
ex03_matrix.ymlOS·Node 버전 매트릭스
CODE
name: Matrix Build

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Test on ${{ matrix.os }} / Node ${{ matrix.node-version }}
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node-version: [18, 20, 22]
        exclude:
          - os: windows-latest
            node-version: 18

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}

      - name: Show environment
        run: |
          node --version
          npm --version

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test --if-present

  summary:
    name: Matrix Summary
    needs: test
    runs-on: ubuntu-latest
    if: always()
    steps:
      - name: Print result
        run: echo "All matrix jobs completed with status ${{ needs.test.result }}"
ex04_cache.yml캐시로 설치 시간 단축 + artifacts 저장
CODE
name: Build with Cache and Artifacts

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js with npm cache
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test --if-present

      - name: Build
        run: npm run build --if-present

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist-${{ github.sha }}
          path: |
            dist/
            !dist/**/*.map
          retention-days: 7
          if-no-files-found: warn

  deploy:
    name: Deploy to production
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    environment: production

    steps:
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          name: dist-${{ github.sha }}
          path: dist/

      - name: Deploy
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
          TARGET_HOST: ${{ secrets.TARGET_HOST }}
        run: |
          echo "Deploying to $TARGET_HOST..."
          echo "Token length: ${#DEPLOY_TOKEN} chars"
          echo "Deploy complete!"

📝 과제 (exercises)

직접 풀어보고, 막힐 때 정답을 펼쳐 비교해보세요.

과제 1

문제 1 (hw01.yml)

목표: push 시 bash 스크립트를 실행하고 결과를 artifact로 저장하는 워크플로우를 작성하세요.

요구사항
  • 파일명: hw01.yml
입출력 예시
# 예시 구조
name: CI Report
on:
  push:
    branches: [main]
  workflow_dispatch:
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      ...
정답 코드 펼치기 / 접기
SOLUTION
name: CI Report

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  report:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Generate report
        run: |
          {
            echo "=== Build Report ==="
            echo "Date: $(date)"
            echo ""
            echo "=== System Info ==="
            uname -a
            echo ""
            echo "=== Recent Commits ==="
            git log --oneline -5
          } > report.txt
          cat report.txt

      - name: Upload report artifact
        uses: actions/upload-artifact@v4
        with:
          name: ci-report
          path: report.txt
          retention-days: 3
▶ 실행 결과
# 예시 구조
name: CI Report
on:
  push:
    branches: [main]
  workflow_dispatch:
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      ...
과제 2

문제 2 (hw02.yml)

목표: Python 프로젝트를 위한 매트릭스 CI 워크플로우를 작성하세요.

요구사항
  • 파일명: hw02.yml
정답 코드 펼치기 / 접기
SOLUTION
name: Python Matrix CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest]
        python-version: ['3.10', '3.11', '3.12']

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements.txt ]; then
            pip install -r requirements.txt
          else
            echo "requirements.txt 없음 — 건너뜀"
          fi

      - name: Run tests
        run: |
          if python -m pytest --version 2>/dev/null; then
            python -m pytest
          else
            echo "pytest 없음 — 테스트 건너뜀"
          fi

      - name: Show Python version
        run: python --version
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗