ToolPal
Close-up of rusty industrial pipes and valves, showcasing aging machinery in a factory setting.

GitHub Actions 튜토리얼: 2026년 CI/CD 자동화 실전 가이드

📷 Pixabay / Pexels

GitHub Actions 튜토리얼: 2026년 CI/CD 자동화 실전 가이드

GitHub Actions 단계별 튜토리얼. Node.js, Python 실전 예제로 테스트, 빌드, 배포 자동화를 배워보세요.

D작성: Daniel Park2026년 3월 17일5분 소요

CI/CD란 무엇이고 왜 중요한가?

CI/CD는 지속적 통합(Continuous Integration)과 지속적 배포(Continuous Deployment)의 약자입니다. 핵심은 코드가 변경될 때마다 발생하는 반복적인 단계를 자동화하는 것입니다:

  • 지속적 통합(CI): 코드가 push되거나 풀 리퀘스트가 열릴 때 자동으로 테스트와 검사를 실행합니다. 이렇게 하면 깨진 코드가 병합되기 전에 발견됩니다.
  • 지속적 배포(CD): 코드가 모든 검사를 통과하면 스테이징 또는 프로덕션 환경에 자동으로 배포됩니다.

CI/CD 없이는 팀이 테스트 실행, 애플리케이션 빌드, 서버 배포를 수동으로 기억해야 합니다. 이는 오류가 발생하기 쉽고 느립니다. CI/CD를 통해 이 단계들이 자동으로 일관되게 실행됩니다.

GitHub Actions는 GitHub의 내장 CI/CD 플랫폼입니다. 저장소에 깊이 통합되어 있으며, 공개 저장소는 무료, 비공개 저장소도 넉넉한 무료 티어를 제공합니다. 간단한 린팅부터 복잡한 다중 환경 배포까지 처리할 만큼 강력합니다.

핵심 개념

워크플로 (Workflow)

워크플로는 .github/workflows/에 저장된 YAML 파일에 정의된 자동화 프로세스입니다. 저장소는 각각 다른 이벤트로 트리거되는 여러 워크플로를 가질 수 있습니다.

이벤트 (트리거)

이벤트는 워크플로가 실행될 시점을 정의합니다. 일반적인 트리거:

  • push — 브랜치에 코드가 push될 때
  • pull_request — PR이 열리거나 업데이트될 때
  • schedule — cron 일정에 따라
  • workflow_dispatch — GitHub UI에서 수동으로 트리거

잡 (Job)

워크플로는 하나 이상의 잡으로 구성됩니다. 잡은 기본적으로 병렬로 실행됩니다. 각 잡은 새로운 가상 머신(러너)에서 실행됩니다.

스텝 (Step)

각 잡은 순차적으로 실행되는 스텝들로 구성됩니다. 스텝은 셸 명령을 실행하거나 미리 빌드된 액션을 사용할 수 있습니다.

액션 (Action)

액션은 GitHub Marketplace에서 게시된 재사용 가능한 작업 단위입니다. 예를 들어, actions/checkout은 저장소를 체크아웃하고, actions/setup-node는 Node.js를 설치합니다.

첫 번째 워크플로: Node.js 테스트

저장소에 .github/workflows/test.yml을 생성하세요:

name: Test

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

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: 코드 체크아웃
        uses: actions/checkout@v4

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

      - name: 의존성 설치
        run: npm ci

      - name: 린터 실행
        run: npm run lint

      - name: 테스트 실행
        run: npm test

      - name: TypeScript 타입 검사
        run: npm run typecheck

이 워크플로는 main 또는 develop에 push할 때마다, 그리고 main에 대한 모든 풀 리퀘스트에서 실행됩니다. 코드를 체크아웃하고, Node.js 20을 설정하고(npm 캐싱으로 속도 향상), 의존성을 설치한 다음, lint, 테스트, 타입 검사를 순차적으로 실행합니다. 어느 단계에서든 실패하면 워크플로가 실패하고 GitHub가 PR 병합을 차단합니다.

Python 워크플로: 린트 및 테스트

name: Python CI

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

jobs:
  lint-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: 코드 체크아웃
        uses: actions/checkout@v4

      - name: Python 설정
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'

      - name: 의존성 설치
        run: |
          pip install --upgrade pip
          pip install -r requirements.txt
          pip install ruff pytest pytest-cov

      - name: Ruff로 린트
        run: ruff check .

      - name: 커버리지와 함께 테스트 실행
        run: pytest --cov=src --cov-report=xml

      - name: 커버리지 리포트 업로드
        uses: codecov/codecov-action@v4
        with:
          file: ./coverage.xml

매트릭스 빌드: 여러 버전에서 테스트

매트릭스 전략을 사용해 여러 버전의 Node.js나 Python에 대해 테스트를 동시에 실행하세요:

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: ['18', '20', '22']
        os: [ubuntu-latest, windows-latest]

    steps:
      - uses: actions/checkout@v4

      - name: Node.js ${{ matrix.node-version }} 사용
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - run: npm ci
      - run: npm test

이것은 각 조합에 대해 별도의 잡을 생성합니다: Node.js 버전 3개 × OS 2개 = 6개의 병렬 잡. 라이브러리가 Node 18, 20, 22를 지원해야 한다면, 이렇게 하면 호환성 문제가 자동으로 잡힙니다.

시크릿 관리

워크플로에 API 키나 비밀번호를 절대 하드코딩하지 마세요. GitHub Secrets를 사용하세요.

시크릿 설정:

  1. 저장소 → Settings → Secrets and variables → Actions로 이동
  2. "New repository secret" 클릭
  3. 이름(예: API_KEY)과 값 추가

워크플로에서 시크릿 사용:

steps:
  - name: 프로덕션 배포
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: |
      echo "API 키로 배포 중..."
      npm run deploy

시크릿은 로그에서 마스킹됩니다 — 코드가 실수로 $API_KEY를 출력해도 GitHub가 ***로 대체합니다.

Cloudflare Pages에 배포하기

Next.js 앱을 빌드하고 Cloudflare Pages에 배포하는 완전한 워크플로:

name: Cloudflare Pages 배포

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test

  deploy:
    runs-on: ubuntu-latest
    needs: test  # 테스트 통과 시에만 배포
    environment: production

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: 설치  빌드
        run: |
          npm ci
          npm run build

      - name: Cloudflare Pages 배포
        uses: cloudflare/pages-action@v1
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          projectName: my-project
          directory: .next
          gitHubToken: ${{ secrets.GITHUB_TOKEN }}

needs: test 지시문은 테스트 잡이 성공한 경우에만 배포 잡이 실행되도록 합니다. environment: production은 프로덕션 배포에 필수 검토자 승인 단계를 추가합니다.

빠른 워크플로를 위한 캐싱

느린 워크플로는 개발자들이 실행하지 않도록 만듭니다. 캐싱을 적극 활용하세요:

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

- name: pip 패키지 캐시
  uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-

캐시 키는 락 파일의 해시를 포함합니다. package-lock.json이나 requirements.txt가 변경될 때 캐시가 무효화되고 의존성이 재설치됩니다. 그렇지 않으면 캐시가 몇 초 안에 복원되어 워크플로 속도를 크게 높입니다.

조건부 스텝과 수동 승인

조건으로 스텝 실행 시점을 제어하세요:

- name: 스테이징 배포
  if: github.ref == 'refs/heads/develop'
  run: npm run deploy:staging

- name: 프로덕션 배포
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  run: npm run deploy:production

- name: PR에 댓글 달기
  if: github.event_name == 'pull_request'
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body: '모든 검사를 통과했습니다! 검토 준비가 되었습니다.'
      })

프로덕션 수준 워크플로를 위한 팁

  1. 액션 버전 고정actions/checkout@main이 아닌 actions/checkout@v4를 사용해 예기치 않은 호환성 문제를 방지하세요
  2. 워크플로를 빠르게 유지 — CI는 5분 이내를 목표로 하세요. 느린 파이프라인은 좌절한 개발자들에 의해 비활성화됩니다
  3. 경로 필터 사용 — 관련 파일이 변경될 때만 워크플로를 트리거하세요
  4. 타임아웃 제한 설정 — 잡에 timeout-minutes: 10을 추가해 오작동하는 빌드가 모든 분을 소모하지 않도록 하세요
  5. 워크플로 권한 검토 — 보안을 위해 permissions: read-all 또는 최소한 필요한 권한을 사용하세요

GitHub Actions는 현대 개발자에게 가장 강력한 도구 중 하나입니다. 잘 설계된 워크플로는 버그가 프로덕션에 도달하기 전에 잡아내고, 모든 환경에서 일관된 빌드를 보장하며, 배포의 수동 작업을 제거합니다. 오늘 간단한 테스트 워크플로부터 시작해 프로젝트가 성숙해지면 배포 자동화를 점진적으로 추가해 나가세요.

자주 묻는 질문

D

작성자

Daniel Park

서울에서 활동하는 시니어 프런트엔드 엔지니어. 국내 SaaS 회사들에서 7년간 웹 애플리케이션을 개발하며 개발자 도구, 웹 성능 최적화, 프라이버시 중심 설계에 집중해 왔습니다. JavaScript 생태계 오픈소스 기여자이자 ToolPal 창립자입니다.

더 알아보기

이 글 공유하기

XLinkedIn

관련 글