GitHub Actions로 Next.js 프로젝트 자동 배포 파이프라인 구축하기 (feat. Vercel + Slack 알림)
PR 올릴 때마다 수동으로 빌드하고 배포하는 거 지치셨나요? 이 글에서는 GitHub Actions를 이용해서 main 브랜치에 머지되는 순간 자동으로 빌드 → 테스트 → 배포 → Slack 알림까지 이어지는 파이프라인을 구성하는 방법을 다룹니다.
전체 파이프라인 구조
구성하려는 파이프라인의 흐름은 다음과 같습니다.
- PR 생성 시 → lint + type-check + 테스트 자동 실행
- main 머지 시 → Vercel 프로덕션 배포 트리거
- 배포 완료 후 → Slack 채널에 결과 알림 전송
1 디렉토리 구조
프로젝트 루트에 .github/workflows/ 폴더를 만들고 두 개의 워크플로우 파일을 생성합니다.
├── .github/
│ └── workflows/
│ ├── ci.yml # PR 생성 시 lint + test
│ └── deploy.yml # main 머지 시 배포 + 알림
├── src/
├── package.json
└── pnpm-lock.yaml
2 CI 워크플로우 (PR 검증)
PR이 열리거나 업데이트될 때마다 lint, 타입 체크, 테스트를 자동으로 실행합니다. pnpm 캐시를 활용해서 의존성 설치 시간을 줄이는 게 포인트입니다.
name: CI
on:
pull_request:
branches: [main, develop]
jobs:
ci:
name: Lint & Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run ESLint
run: pnpm lint
- name: Run type check
run: pnpm tsc --noEmit
- name: Run tests
run: pnpm test --passWithNoTests
- name: Build check
run: pnpm build
env:
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
--frozen-lockfile 옵션은 lockfile이 package.json과 맞지 않으면 에러를 냅니다. 의존성 추가 후 lockfile 커밋을 빠뜨리면 CI가 깨지므로 주의하세요.3 배포 워크플로우 (main 머지 시)
main 브랜치에 push가 발생하면 Vercel CLI를 통해 프로덕션 배포를 수행하고, 성공/실패 여부를 Slack으로 알립니다.
name: Deploy to Production
on:
push:
branches: [main]
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
outputs:
deploy_url: ${{ steps.deploy.outputs.url }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Vercel CLI
run: pnpm add -g vercel@latest
- name: Pull Vercel environment
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build project
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel
id: deploy
run: |
url=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
echo "url=$url" >> $GITHUB_OUTPUT
notify:
name: Slack Notify
runs-on: ubuntu-latest
needs: deploy
if: always()
steps:
- name: Notify success
if: needs.deploy.result == 'success'
uses: slackapi/slack-github-action@v1.26.0
with:
payload: |
{
"text": ":white_check_mark: *프로덕션 배포 성공*",
"attachments": [{
"color": "good",
"fields": [
{ "title": "배포 URL", "value": "${{ needs.deploy.outputs.deploy_url }}", "short": false },
{ "title": "커밋", "value": "${{ github.event.head_commit.message }}", "short": false },
{ "title": "배포자", "value": "${{ github.actor }}", "short": true }
]
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
- name: Notify failure
if: needs.deploy.result == 'failure'
uses: slackapi/slack-github-action@v1.26.0
with:
payload: |
{
"text": ":x: *프로덕션 배포 실패*",
"attachments": [{
"color": "danger",
"fields": [
{ "title": "커밋", "value": "${{ github.event.head_commit.message }}", "short": false },
{ "title": "배포자", "value": "${{ github.actor }}", "short": true },
{ "title": "Actions 로그", "value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "short": false }
]
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
4 GitHub Secrets 등록
Settings → Secrets and variables → Actions 에서 아래 시크릿을 등록해야 합니다.
VERCEL_TOKEN # Vercel → Account Settings → Tokens
VERCEL_ORG_ID # vercel link 실행 후 .vercel/project.json 에서 확인
VERCEL_PROJECT_ID # 동일 파일에서 확인
SLACK_WEBHOOK_URL # Slack → 앱 → Incoming Webhooks → Add
NEXT_PUBLIC_API_URL # 프로젝트에서 사용하는 환경변수들
Vercel 토큰 & ID 빠르게 얻는 법
# Vercel CLI 설치 (이미 있으면 skip)
npm i -g vercel
# 프로젝트 루트에서 실행
vercel link
# .vercel/project.json 생성됨 → orgId, projectId 복사
cat .vercel/project.json
5 package.json 스크립트 확인
워크플로우에서 사용하는 pnpm lint, pnpm test 스크립트가 정의되어 있어야 합니다.
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint && eslint . --ext .ts,.tsx",
"test": "jest --ci",
"type-check": "tsc --noEmit"
}
}
6 선택: PR에 배포 URL 자동 코멘트
PR마다 preview 배포 URL을 자동으로 댓글로 달아주면 리뷰어가 바로 확인할 수 있어서 편합니다.
- name: Deploy preview to Vercel
id: preview
run: |
vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
vercel build --token=${{ secrets.VERCEL_TOKEN }}
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
echo "url=$url" >> $GITHUB_OUTPUT
- name: Comment PR with preview URL
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: `🚀 **Preview 배포 완료**\n\n${process.env.PREVIEW_URL}\n\n> 커밋: ${context.sha.substring(0, 7)}`
})
env:
PREVIEW_URL: ${{ steps.preview.outputs.url }}
마무리
이 파이프라인을 적용하면 개발 흐름이 이렇게 됩니다.
- 기능 브랜치에서 작업 후 PR 오픈 → CI 자동 실행 + Preview URL 댓글
- 코드 리뷰 후 main 머지 → 프로덕션 자동 배포
- 배포 결과 Slack 알림 → 팀 전체가 인지
수동 배포에서 오는 실수와 스트레스를 없애고 싶은 분들께 도움이 됐으면 합니다. 질문은 댓글로!
