DevFinance
테크·7 min read

GitHub Actions CI/CD 완전 가이드 2026 — Next.js 자동 배포 파이프라인 구축

GitHub Actions로 Next.js 프로젝트의 CI/CD 파이프라인을 구축하는 실전 가이드. lint·타입체크·빌드 자동화, Vercel 배포, 캐싱 전략, 시크릿 관리, 비용 최적화까지 정리했습니다.

GitHub Actions로 인프라 걱정 없는 개발 환경 만들기

GitHub Actions는 push, PR, 스케줄 등 리포지토리 이벤트에 반응해 자동으로 워크플로우를 실행하는 CI/CD 플랫폼입니다. 별도 서버 없이 코드 검증, 빌드, 배포를 완전 자동화할 수 있습니다.


무료 한도 정리

항목퍼블릭 레포프라이빗 레포
실행 시간무제한2,000분/월
스토리지무제한500MB
동시 실행20개20개
캐시 용량10GB10GB

프라이빗 레포에서 Next.js CI 1회 평균 3분, 하루 20번 push = 월 1,800분. 한도에 근접하므로 캐싱 최적화가 중요합니다.


핵심 개념

워크플로우 구조

name: 워크플로우 이름           # GitHub Actions UI에서 표시됨

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

jobs:                          # 실행 단위 (병렬 또는 순차)
  job-name:
    runs-on: ubuntu-latest     # 실행 환경
    steps:                     # 순차 실행 단계
      - uses: actions/checkout@v4
      - run: npm ci

주요 트리거

on:
  push:
    branches: [main, develop]
    paths: ["src/**", "package.json"]  # 특정 경로 변경 시만
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]
  schedule:
    - cron: "0 9 * * 1"  # 매주 월요일 오전 9시 (UTC)
  workflow_dispatch:      # 수동 실행 버튼 추가

기본 CI 워크플로우

# .github/workflows/ci.yml
name: CI

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

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"   # npm 캐시 자동 활성화

      - run: npm ci
      - run: npm run lint
      - run: npx tsc --noEmit
      - run: npm run build

실전 워크플로우 (Next.js + TypeScript)

lint·타입체크·빌드를 병렬로 실행하고, 빌드 캐시까지 활용합니다.

# .github/workflows/ci.yml
name: CI/CD

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

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true  # 같은 브랜치 이전 실행 취소

jobs:
  lint:
    name: Lint
    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 run lint

  typecheck:
    name: TypeScript
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: "npm"
      - run: npm ci
      - run: npx tsc --noEmit

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, typecheck]  # lint, typecheck 성공 후 실행
    steps:
      - uses: actions/checkout@v4

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

      - run: npm ci

      # Next.js 빌드 캐시
      - uses: actions/cache@v4
        with:
          path: .next/cache
          key: nextjs-${{ runner.os }}-${{ hashFiles('package-lock.json') }}-${{ hashFiles('src/**') }}
          restore-keys: |
            nextjs-${{ runner.os }}-${{ hashFiles('package-lock.json') }}-
            nextjs-${{ runner.os }}-

      - run: npm run build
        env:
          NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
          NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}

Vercel 자동 배포 연동

방법 1: Vercel GitHub 앱 (권장)

가장 간단합니다. Vercel 대시보드에서 GitHub 레포를 연결하면:

  • main 브랜치 push → 자동 프로덕션 배포
  • PR 생성 → 자동 Preview URL 생성 (PR 댓글에 링크 첨부)

별도 워크플로우 불필요.

방법 2: GitHub Actions에서 Vercel CLI 배포

# .github/workflows/deploy.yml
name: Deploy to Vercel

on:
  push:
    branches: [main]

jobs:
  deploy:
    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 run build

      - name: Deploy to Vercel
        run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
        env:
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

유용한 패턴

PR 제목 Conventional Commits 검증

# .github/workflows/pr-title.yml
name: PR Title Check

on:
  pull_request:
    types: [opened, edited, synchronize]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: amannn/action-semantic-pull-request@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

스테일 이슈·PR 자동 닫기

# .github/workflows/stale.yml
name: Stale

on:
  schedule:
    - cron: "0 0 * * *"  # 매일 자정

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v9
        with:
          stale-issue-message: "30일 동안 활동이 없어 자동으로 스테일 처리됩니다."
          stale-pr-message: "30일 동안 활동이 없어 자동으로 스테일 처리됩니다."
          days-before-stale: 30
          days-before-close: 7

의존성 취약점 스캔

- name: Audit dependencies
  run: npm audit --audit-level=high

환경별 배포

jobs:
  deploy-staging:
    if: github.ref == 'refs/heads/develop'
    environment: staging
    steps:
      - run: npm run deploy:staging

  deploy-production:
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - run: npm run deploy:production

시크릿 관리

시크릿 등록 위치

GitHub Repository → Settings → Secrets and variables → Actions

워크플로우에서 사용

steps:
  - name: Build and deploy
    run: npm run deploy
    env:
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
      VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
      NEXT_PUBLIC_API_URL: ${{ vars.NEXT_PUBLIC_API_URL }}  # 비민감 변수

절대 하지 말 것

# 나쁜 예 — 로그에 시크릿 노출
- run: echo "Token is ${{ secrets.MY_TOKEN }}"

# 나쁜 예 — 코드에 하드코딩
- run: curl -H "Authorization: Bearer abc123" https://api.example.com

# 나쁜 예 — 워크플로우 파일에 시크릿 직접 기입
env:
  MY_SECRET: "actual-secret-value-here"

성능 최적화

npm 캐시 (필수)

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: "npm"  # package-lock.json 기반 자동 캐싱

Next.js 빌드 캐시

- uses: actions/cache@v4
  with:
    path: .next/cache
    key: nextjs-${{ hashFiles('package-lock.json') }}-${{ hashFiles('src/**/*.{ts,tsx}') }}
    restore-keys: |
      nextjs-${{ hashFiles('package-lock.json') }}-
      nextjs-

캐시 히트 전후 비교

단계캐시 없음캐시 있음
npm ci60~90초10~20초
next build60~120초20~40초
전체 CI4~6분1~2분

실전 체크리스트

CI 워크플로우 최적화:
□ concurrency 설정으로 중복 실행 방지
□ npm 캐시 활성화 (setup-node cache: 'npm')
□ Next.js 빌드 캐시 설정
□ lint·typecheck 병렬 실행
□ 빌드는 lint/typecheck 성공 후 실행 (needs)

시크릿 보안:
□ 모든 민감 정보를 GitHub Secrets에 저장
□ 워크플로우에 하드코딩된 시크릿 없음
□ echo나 print로 시크릿 출력하지 않음

배포:
□ main 브랜치 배포 전 CI 성공 조건 설정
□ 환경별(staging/production) 배포 분리
□ 배포 실패 시 Slack/이메일 알림 설정

관련 글: Docker 입문 완전 가이드 · Vercel 무료 배포 완전 가이드 · Playwright E2E 테스트

DF

DevFinance 편집팀

현직 소프트웨어 엔지니어가 운영합니다. IT 업계 종사자에게 필요한 재테크·기술 정보를 공식 데이터와 실무 경험을 바탕으로 정리합니다.

더 알아보기