GitHub Actions CI/CD 입문 가이드: 커밋 시 자동 배포 구현하기

GitHub Actions를 처음 접하고 .github/workflows 디렉토리에 YAML 파일을 추가했지만, 워크플로우가 제대로 트리거되지 않거나 Job과 Step의 차이를 이해하지 못해 혼란스러운 경험이 있을 것입니다. 이 글은 GitHub Actions의 핵심 개념과 실무 CI/CD 파이프라인 구축 방법을 실습 중심으로 정리하여, 커밋 시 자동 배포까지 구현할 수 있는 구체적인 가이드를 제공합니다. 불필요한 시행착오를 줄이고 당장 실무에 적용 가능한 Action Item을 확보하십시오.


GitHubActionsvsJenkins비교와자동배포실전구성법




1. GitHub Actions 핵심 개념: Workflow, Job, Step의 관계

GitHub Actions는 이벤트 기반 자동화 시스템입니다. 핵심 구성 요소는 다음과 같습니다.

  • Workflow: .github/workflows/*.yml 파일로 정의되는 자동화 프로세스. 하나 이상의 Job으로 구성됩니다.
  • Event: Workflow를 트리거하는 조건. on: push, on: pull_request, on: schedule(cron), workflow_dispatch(수동 실행) 등이 있습니다.
  • Job: 병렬 또는 순차 실행 가능한 작업 단위. runs-on으로 실행 환경(ubuntu-latest, macos-latest 등)을 지정합니다.
  • Step: Job 내에서 순차 실행되는 명령 또는 액션. run(셸 명령)과 uses(재사용 가능한 액션) 두 가지 형태로 구성됩니다.
  • Runner: Workflow를 실행하는 서버. GitHub-hosted(무료 제공, 사용량 제한 있음)와 self-hosted(자체 관리) 중 선택 가능합니다.

실무 팁: 처음 학습 시 워크플로우와 Job의 차이를 헷갈리는 경우가 많습니다. 워크플로우는 "전체 자동화 시나리오"이고, Job은 "병렬 실행 가능한 작업 묶음"입니다. 예를 들어 빌드·테스트·배포를 각각 별도 Job으로 분리하면, 빌드 실패 시 테스트와 배포가 실행되지 않도록 needs 키워드로 의존성을 설정할 수 있습니다.

2. 최소 구성 Workflow 작성 및 트리거 확인

실습을 통해 개념을 빠르게 이해할 수 있습니다. 아래는 push와 PR 시 트리거되는 최소 구성 예시입니다.

name: CI
on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
  workflow_dispatch: {}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Hello World
        run: echo "Hello, GitHub Actions!"

위 YAML 파일을 .github/workflows/test.yml로 저장하고 커밋·푸시하면, Actions 탭에서 워크플로우 실행 로그를 확인할 수 있습니다. 반드시 actions/checkout@v3를 첫 Step으로 사용하십시오. 이 액션은 러너에 레포지토리 코드를 체크아웃하는 역할을 하며, 생략 시 이후 Step에서 코드에 접근할 수 없습니다.

주의사항: 전체 Git 히스토리가 필요한 경우(예: 커밋 메시지 분석, 태그 기반 버전 관리) with: fetch-depth: 0을 반드시 지정하십시오. 기본값은 최신 커밋 1개만 가져오므로, 이전 커밋 정보가 필요한 작업에서 오류가 발생합니다.

3. 실무 CI/CD 파이프라인 구현: Docker 빌드·배포 자동화

단순 Hello World를 넘어 실무에서 사용할 수 있는 파이프라인을 구성해야 합니다. 다음은 Docker 이미지 빌드 후 배포 서버에 자동 배포하는 흐름입니다.

3.1. 브랜치 전략 및 트리거 설정

  • main: 안정 버전, 프로덕션 배포용
  • develop: 개발 통합 브랜치, 개발 서버 자동 배포 트리거
  • feat/fix/#이슈번호: 기능 개발 브랜치

develop 브랜치에 push 시 cd-dev 워크플로우가 실행되도록 설정합니다.

on:
  push:
    branches: ["develop"]

3.2. Docker 이미지 빌드 및 태깅

이미지 태그로 ${{ github.sha }}를 사용하면 재현 가능하고 충돌이 적습니다. 날짜 기반 태그(예: 20250101-1, 20250101-2)는 동일 날짜 내 여러 배포 시 관리가 복잡해집니다.

- name: Build and Push Docker Image
  run: |
    docker build -t myrepo/myapp:${{ github.sha }} .
    docker push myrepo/myapp:${{ github.sha }}

3.3. 배포 서버에서 이미지 Pull 및 재시작

self-hosted 러너를 배포 서버에 설치하거나, SSH를 통해 원격 명령을 실행합니다. self-hosted 러너 사용 시 비용 절감 효과가 크지만, 러너의 보안 업데이트와 모니터링 정책을 반드시 수립하십시오.

- name: Deploy to Server
  run: |
    docker pull myrepo/myapp:${{ github.sha }}
    docker-compose down
    docker-compose up -d

3.4. 민감정보 관리: Secrets와 Variables

Docker Hub 인증 정보, SSH 키 등은 Settings > Secrets and variables > Actions에 등록하고, 워크플로우에서 ${{ secrets.DOCKER_PASSWORD }} 형태로 참조합니다. 절대 하드코딩하지 마십시오.

4. 고급 설정: Matrix 전략, Job 의존성, Environment

4.1. Matrix 전략으로 병렬 테스트

여러 Node.js 버전에서 동시에 테스트를 실행하려면 strategy.matrix를 사용합니다.

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14, 16, 18]
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

4.2. Job 의존성 설정: needs 키워드

빌드 성공 후에만 배포가 실행되도록 순차 제어합니다.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building..."
  
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying..."

4.3. Environment로 배포 승인 절차 추가

Settings > Environments에서 Production 환경을 생성하고, Required reviewers(승인자 지정)와 Wait timer(대기 시간)를 설정합니다. 워크플로우에서 environment: production으로 참조하면, 배포 전 수동 승인 단계가 추가됩니다.

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: echo "Production deployment"

실무 권장: 프로덕션 배포는 반드시 승인 절차를 추가하십시오. 자동화로 인한 장애 확산을 방지할 수 있습니다.

5. 모니터링 및 트러블슈팅

  • Actions 탭: 워크플로우·Job·Step별 실행 로그를 확인할 수 있습니다. 실패 시 해당 Step의 로그를 펼쳐 오류 메시지를 확인하십시오.
  • Artifact 보존 기간: Settings > Actions > General에서 로그 및 아티팩트 보존 기간을 조정할 수 있습니다. 기본값은 90일입니다.
  • Verbose 로그: 디버깅이 필요한 경우, 워크플로우 재실행 시 "Enable debug logging" 옵션을 활성화하면 상세 로그를 확인할 수 있습니다.

트러블슈팅 팁: self-hosted 러너 사용 시 "Runner is offline" 오류가 자주 발생합니다. 러너 프로세스가 정상 실행 중인지, 네트워크 방화벽이 GitHub API 접근을 차단하지 않는지 확인하십시오.

6. AWS 환경에서의 배포 자동화: CodePipeline 구성

GitHub Actions 외에도 AWS 네이티브 도구를 사용할 수 있습니다. CodePipeline은 Source(GitHub/CodeCommit) → Build(CodeBuild) → Deploy(CodeDeploy) 단계를 시각적으로 구성할 수 있습니다.

6.1. CodeBuild 설정

buildspec.yml 파일로 빌드 명령을 정의합니다.

version: 0.2
phases:
  build:
    commands:
      - echo "Building JAR..."
      - ./gradlew bootJar
artifacts:
  files:
    - build/libs/*.jar

6.2. CodeDeploy 배포 그룹 설정

EC2 인스턴스에 태그(예: Environment=Dev)를 추가하고, CodeDeploy 애플리케이션에서 배포 그룹을 생성할 때 해당 태그를 기준으로 인스턴스를 선택합니다. 서비스 역할(IAM Role)을 반드시 지정하십시오.

6.3. EC2 사전 준비

  • Java 버전 확인 및 설치 (java -version)
  • AWS CLI 설치 및 CodeDeploy Agent 실행
  • 배포 스크립트 디렉토리 생성 (/home/ec2-user/scripts)

주의사항: CodeDeploy는 배포 후 프로세스를 자동으로 종료하지 않습니다. 기존 Java 프로세스의 PID를 확인하고 kill 명령으로 종료한 뒤, nohup java -jar app.jar &로 재시작하는 스크립트를 작성하십시오.

7. Jenkins vs GitHub Actions: 선택 기준

항목 GitHub Actions Jenkins
설치·관리 불필요 (SaaS) 필요 (서버 구축·유지보수)
비용 Public 레포: 무료, Private: 사용량 제한 서버 비용만 발생
YAML 기반 설정 O Jenkinsfile (Groovy)
플러그인 생태계 Marketplace (제한적) 방대한 플러그인
권장 사용처 GitHub 중심 워크플로우, 빠른 구축 복잡한 파이프라인, 레거시 통합

실무 판단 기준: GitHub 레포지토리를 사용하고 있고, 파이프라인이 비교적 단순하다면 GitHub Actions를 권장합니다. 반면 사내 GitLab, Bitbucket 등을 사용하거나, 복잡한 승인 프로세스와 레거시 시스템 통합이 필요하다면 Jenkins가 적합합니다.

결론 및 Action Item

GitHub Actions는 .github/workflows/*.yml 파일로 정의되며, Event → Job → Step 구조로 자동화 파이프라인을 구성합니다. 실무 적용 시 actions/checkout@v3 사용, 이미지 태깅에 github.sha 활용, Secrets로 민감정보 관리를 기본 원칙으로 삼으십시오. self-hosted 러너는 비용 절감 효과가 크지만, 보안 업데이트와 모니터링 정책을 반드시 수립해야 합니다.

당장 실행할 Action Item: 현재 진행 중인 프로젝트의 develop 브랜치에 최소 구성 워크플로우(checkout + echo)를 추가하고, push 시 Actions 탭에서 로그를 확인하십시오. 이후 Docker 빌드·배포 단계를 순차적으로 추가하면서 파이프라인을 확장하면, 시행착오를 최소화하고 안정적인 CI/CD 환경을 구축할 수 있습니다.


#함께 읽으면 좋은 글

GitHub 다중 계정 관리 완벽 가이드 SSH Config로 회사와 개인 계정 분리하기 : 바로보기

댓글