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개 |
| 캐시 용량 | 10GB | 10GB |
프라이빗 레포에서 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 ci | 60~90초 | 10~20초 |
next build | 60~120초 | 20~40초 |
| 전체 CI | 4~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 테스트
관련 글
Vercel 무료 배포 실전 가이드 2026 — Hobby 플랜으로 사이드 프로젝트 운영하기
Vercel Hobby 플랜으로 Next.js 사이드 프로젝트를 무료 배포하는 방법을 단계별로 정리했습니다. 커스텀 도메인, 환경 변수, 성능 최적화, 무료 한도 관리까지 포함합니다.
Docker 입문 완전 가이드 2026 — 개발자 필수 컨테이너 기초
Docker의 핵심 개념, Dockerfile 작성, Docker Compose 멀티 서비스 구성, Next.js multi-stage 빌드, 보안 모범 사례까지 개발자가 알아야 할 Docker 기초를 완전 정리했습니다.
AWS 비용 최적화 완전 가이드 2026 — EC2, S3, RDS 비용 절감 실전
AWS 비용이 예상보다 많이 나오는 개발자를 위한 최적화 가이드. EC2 Reserved Instance vs Savings Plans, S3 스토리지 클래스, RDS 비용 절감, 무료 티어 한도, 비용 모니터링 설정까지 실전 방법을 정리했습니다.