GitHub Actions 완벽 가이드

Posted by Albert 3Day 9Hour 18Min 16Sec ago [2025-12-08]

GitHub Actions란?

GitHub Actions는 GitHub에서 제공하는 CI/CD(지속적 통합/배포) 플랫폼입니다. 코드 푸시, PR 생성 등의 이벤트에 자동으로 반응하여 빌드, 테스트, 배포 등의 작업을 수행할 수 있습니다.

주요 특징

  • GitHub 저장소에 통합되어 있어 별도 설정 불필요
  • 다양한 운영체제 지원 (Ubuntu, Windows, macOS)
  • 풍부한 마켓플레이스 액션
  • 무료 티어 제공 (public 저장소는 무제한)

기본 개념

핵심 용어

  • Workflow: 자동화된 프로세스 전체 (.github/workflows/ 폴더의 YAML 파일)
  • Event: Workflow를 트리거하는 이벤트 (push, pull_request 등)
  • Job: Workflow 내의 작업 단위
  • Step: Job 내의 개별 작업
  • Action: 재사용 가능한 작업 단위
  • Runner: Workflow를 실행하는 서버

기본 구조

name: Workflow 이름
on: [이벤트]
jobs:
  job-name:
    runs-on: 운영체제
    steps:
      - name: Step 이름
        run: 실행할 명령어

초보자 가이드

1. 첫 번째 Workflow 만들기

저장소에서 .github/workflows/hello.yml 파일을 생성합니다.

name: Hello World

' push 이벤트 발생 시 실행
on: [push]

jobs:
  hello-job:
    runs-on: ubuntu-latest
    
    steps:
      - name: 인사하기
        run: echo "Hello, GitHub Actions!"
      
      - name: 현재 시간 출력
        run: date

2. 코드 체크아웃하기

대부분의 Workflow는 저장소 코드가 필요합니다.

name: Checkout Example

on: [push]

jobs:
  checkout-job:
    runs-on: ubuntu-latest
    
    steps:
      ' 저장소 코드 가져오기
      - uses: actions/checkout@v4
      
      - name: 파일 목록 보기
        run: ls -la

3. 특정 브랜치에서만 실행

name: Main Branch Only

on:
  push:
    branches:
      - main  ' main 브랜치에서만 실행

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 배포 스크립트 실행
        run: echo "Deploying to production..."

4. Pull Request 검증

name: PR Check

on:
  pull_request:
    branches: [main]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: 코드 스타일 체크
        run: echo "Checking code style..."

중급 가이드

1. 여러 Job 사용하기

name: Multi-Job Workflow

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 빌드
        run: echo "Building..."
  
  test:
    runs-on: ubuntu-latest
    needs: build  ' build가 완료된 후 실행
    steps:
      - uses: actions/checkout@v4
      - name: 테스트
        run: echo "Testing..."
  
  deploy:
    runs-on: ubuntu-latest
    needs: [build, test]  ' 두 개 모두 완료 후 실행
    steps:
      - name: 배포
        run: echo "Deploying..."

2. 환경 변수 사용

name: Environment Variables

on: [push]

env:
  GLOBAL_VAR: "전역 변수"

jobs:
  demo:
    runs-on: ubuntu-latest
    env:
      JOB_VAR: "Job 레벨 변수"
    
    steps:
      - name: 환경 변수 출력
        env:
          STEP_VAR: "Step 레벨 변수"
        run: |
          echo "전역: $GLOBAL_VAR"
          echo "Job: $JOB_VAR"
          echo "Step: $STEP_VAR"

3. Secrets 사용하기

민감한 정보는 GitHub Secrets에 저장합니다. (Settings → Secrets and variables → Actions → New repository secret)

name: Using Secrets

on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: API 키 사용
        env:
          API_KEY: ${{ secrets.API_KEY }}
        run: |
          echo "API 키가 설정되었습니다"
          ' curl -H "Authorization: $API_KEY" https://api.example.com

4. Matrix 전략 (여러 버전 테스트)

name: Matrix Testing

on: [push]

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16, 18, 20]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Node.js 설정
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      
      - name: 테스트
        run: echo "Testing on ${{ matrix.os }} with Node ${{ matrix.node-version }}"

5. 조건부 실행

name: Conditional Execution

on: [push]

jobs:
  production:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: 프로덕션 배포
        run: echo "Deploying to production"
  
  staging:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'
    steps:
      - name: 스테이징 배포
        run: echo "Deploying to staging"

고급 가이드

1. 재사용 가능한 Workflow

.github/workflows/reusable-workflow.yml:

name: Reusable Workflow

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      token:
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 배포
        run: echo "Deploying to ${{ inputs.environment }}"

호출하는 Workflow:

name: Main Workflow

on: [push]

jobs:
  call-reusable:
    uses: ./.github/workflows/reusable-workflow.yml
    with:
      environment: production
    secrets:
      token: ${{ secrets.DEPLOY_TOKEN }}

2. Composite Action 만들기

.github/actions/setup-app/action.yml:

name: 'Setup Application'
description: '애플리케이션 설정을 위한 복합 액션'

inputs:
  node-version:
    description: 'Node.js 버전'
    required: true
    default: '18'

runs:
  using: "composite"
  steps:
    - name: Node.js 설정
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
      shell: bash
    
    - name: 의존성 설치
      run: npm ci
      shell: bash
    
    - name: 캐시 설정
      uses: actions/cache@v3
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
      shell: bash

사용 예:

name: Use Composite Action

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/setup-app
        with:
          node-version: '20'

3. 캐싱 전략

name: Advanced Caching

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      ' Node.js 의존성 캐싱
      - name: 캐시 확인
        uses: actions/cache@v3
        id: cache-npm
        with:
          path: |
            ~/.npm
            node_modules
          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-npm-
      
      - name: 의존성 설치
        if: steps.cache-npm.outputs.cache-hit != 'true'
        run: npm ci

4. Artifacts 저장 및 다운로드

name: Artifacts Example

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: 빌드
        run: |
          mkdir -p dist
          echo "Build output" > dist/app.js
      
      ' Artifact 업로드
      - name: Artifact 업로드
        uses: actions/upload-artifact@v4
        with:
          name: build-output
          path: dist/
          retention-days: 5
  
  test:
    runs-on: ubuntu-latest
    needs: build
    steps:
      ' Artifact 다운로드
      - name: Artifact 다운로드
        uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/
      
      - name: 테스트
        run: |
          ls -la dist/
          cat dist/app.js

5. 동적 매트릭스 생성

name: Dynamic Matrix

on: [push]

jobs:
  generate-matrix:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v4
      
      - name: 매트릭스 생성
        id: set-matrix
        run: |
          echo 'matrix={"include":[{"name":"test1","value":"a"},{"name":"test2","value":"b"}]}' >> $GITHUB_OUTPUT
  
  test:
    needs: generate-matrix
    runs-on: ubuntu-latest
    strategy:
      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
    steps:
      - name: 테스트 실행
        run: echo "Testing ${{ matrix.name }} with value ${{ matrix.value }}"

실전 예제

1. Node.js 애플리케이션 CI/CD

name: Node.js CI/CD

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18, 20]
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Node.js ${{ matrix.node-version }} 설정
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      
      - name: 의존성 설치
        run: npm ci
      
      - name: 린트 검사
        run: npm run lint
      
      - name: 테스트 실행
        run: npm test
      
      - name: 빌드
        run: npm run build
  
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Node.js 설정
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      - name: 의존성 설치
        run: npm ci
      
      - name: 빌드
        run: npm run build
      
      - name: 배포
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          echo "Deploying to production..."
          ' 실제 배포 명령어

2. Docker 이미지 빌드 및 배포

name: Docker Build and Push

on:
  push:
    branches: [main]
    tags:
      - 'v*'

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Docker 메타데이터 설정
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
      
      - name: Docker Buildx 설정
        uses: docker/setup-buildx-action@v3
      
      - name: 레지스트리 로그인
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: 빌드 및 푸시
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

3. 자동 릴리즈 생성

name: Create Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: 변경사항 생성
        id: changelog
        run: |
          echo "'' Changes in this Release" > CHANGELOG.md
          git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s" >> CHANGELOG.md
      
      - name: 빌드 아티팩트 생성
        run: |
          mkdir -p release
          zip -r release/app-${{ github.ref_name }}.zip src/
      
      - name: GitHub Release 생성
        uses: softprops/action-gh-release@v1
        with:
          body_path: CHANGELOG.md
          files: release/*
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4. 스케줄 기반 작업

name: Scheduled Task

on:
  schedule:
    ' 매일 오전 9시 (UTC)
    - cron: '0 9 * * *'
  workflow_dispatch:  ' 수동 실행 가능

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: 오래된 브랜치 정리
        run: |
          echo "Cleaning up old branches..."
          git fetch --prune
      
      - name: 리포트 생성
        run: |
          echo "Generating daily report..."
          date > report.txt
      
      - name: 알림 전송
        if: failure()
        run: echo "Task failed! Send notification..."

5. 모노레포 선택적 빌드

name: Monorepo Selective Build

on:
  push:
    branches: [main]

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      frontend: ${{ steps.filter.outputs.frontend }}
      backend: ${{ steps.filter.outputs.backend }}
    steps:
      - uses: actions/checkout@v4
      
      - uses: dorny/paths-filter@v2
        id: filter
        with:
          filters: |
            frontend:
              - 'frontend/**'
            backend:
              - 'backend/**'
  
  build-frontend:
    needs: changes
    if: needs.changes.outputs.frontend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Frontend 빌드
        run: |
          cd frontend
          npm ci
          npm run build
  
  build-backend:
    needs: changes
    if: needs.changes.outputs.backend == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Backend 빌드
        run: |
          cd backend
          npm ci
          npm test

유용한 팁

1. Workflow 디버깅

- name: 디버그 정보 출력
  run: |
    echo "Event: ${{ github.event_name }}"
    echo "Branch: ${{ github.ref }}"
    echo "Commit: ${{ github.sha }}"
    echo "Actor: ${{ github.actor }}"

2. 실행 시간 제한

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10  ' 10분 후 타임아웃

3. 병렬 실행 제어

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true  ' 새 실행 시 기존 실행 취소

4. 실패 시에도 계속 실행

steps:
  - name: 실패해도 괜찮은 작업
    run: exit 1
    continue-on-error: true

5. 단계 출력값 사용

steps:
  - name: 값 설정
    id: set-value
    run: echo "result=success" >> $GITHUB_OUTPUT
  
  - name: 값 사용
    run: echo "Result was ${{ steps.set-value.outputs.result }}"

추가 리소스





LIST

Copyright © 2014 visionboy.me All Right Reserved.