devops2025-03-25·9 min·139/348

Vercel에서 환경별 설정 분리

Vercel에서 개발, 스테이징, 프로덕션 환경을 분리하여 설정하는 방법을 알아봅니다.

Vercel에서 환경별 설정 분리

Introduction

개발, 스테이징, 프로덕션 환경을 효과적으로 분리하면 배포 안정性和 개발 효율성을 높일 수 있습니다. 이 글에서는 Vercel에서 환경별 설정을 분리하는 방법을 알아보겠습니다.

Environment

  • Vercel 프로젝트 (Next.js 14+)
  • GitHub/GitLab
  • 환경 변수 관리
  • 브랜치 전략

Problem

환경 변수가 혼재되어 있을 때 발생하는 문제:

// .env.local (로컬 개발)
DATABASE_URL=postgresql://localhost:5432/dev
API_KEY=dev-key-12345

// Vercel 프로덕션
DATABASE_URL=postgresql://prod-host:5432/prod
API_KEY=prod-key-67890

// 실수로 개발 키가 프로덕션에 배포되는 경우 발생

Analysis

Vercel 환경 분리 구조:

  1. Development: 로컬 개발 환경
  2. Preview: PR 시 자동 생성되는 프리뷰 환경
  3. Production: 메인 브랜치 배포

Solution

1. Vercel 대시보드에서 환경 변수 설정

# 환경 변수 추가
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add DATABASE_URL development

# 환경 변수 목록 확인
vercel env ls

2. vercel.json 환경 설정

{
  "env": {
    "DATABASE_URL": "@database-url",
    "API_KEY": "@api-key"
  },
  "build": {
    "env": {
      "NEXT_PUBLIC_API_URL": "@api-url"
    }
  }
}

3. 환경별 설정 파일

// config/environments.js
const environments = {
  development: {
    apiUrl: 'http://localhost:3000',
    databaseUrl: process.env.DATABASE_URL,
    debug: true,
  },
  preview: {
    apiUrl: `https://${process.env.VERCEL_URL}`,
    databaseUrl: process.env.DATABASE_URL,
    debug: true,
  },
  production: {
    apiUrl: 'https://your-app.vercel.app',
    databaseUrl: process.env.DATABASE_URL,
    debug: false,
  },
};

export function getConfig() {
  const env = process.env.VERCEL_ENV || 'development';
  return environments[env] || environments.development;
}

4. 브랜치 전략에 따른 배포

# .github/workflows/vercel-deploy.yml
name: Deploy to Vercel
on:
  push:
    branches: [main, develop, 'feature/*']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: ${{ github.ref == 'refs/heads/main' && '--prod' || '' }}

5. 환경 변수 검증

// lib/env-validation.js
const requiredEnvVars = [
  'DATABASE_URL',
  'API_KEY',
  'NEXTAUTH_SECRET',
];

export function validateEnvironment() {
  const missing = requiredEnvVars.filter(
    (envVar) => !process.env[envVar]
  );
  
  if (missing.length > 0) {
    console.error('Missing environment variables:', missing);
    throw new Error(`Missing required env vars: ${missing.join(', ')}`);
  }
  
  // 환경별 검증
  const env = process.env.VERCEL_ENV || 'development';
  
  if (env === 'production') {
    if (process.env.DEBUG === 'true') {
      console.warn('DEBUG mode is enabled in production');
    }
  }
  
  return true;
}

6. 프리뷰 환경 설정

// app/api/preview-info/route.js
import { NextResponse } from 'next/server';

export async function GET() {
  return NextResponse.json({
    environment: process.env.VERCEL_ENV,
    url: process.env.VERCEL_URL,
    gitBranch: process.env.VERCEL_GIT_COMMIT_REF,
    gitCommit: process.env.VERCEL_GIT_COMMIT_SHA,
  });
}

7. 환경별 데이터베이스 연결

// lib/database.js
import { PrismaClient } from '@prisma/client';

const databaseConfigs = {
  development: {
    log: ['query'],
    datasources: {
      db: {
        url: process.env.DATABASE_URL,
      },
    },
  },
  preview: {
    log: ['error'],
    datasources: {
      db: {
        url: process.env.DATABASE_URL,
      },
    },
  },
  production: {
    log: ['error'],
    datasources: {
      db: {
        url: process.env.DATABASE_URL,
      },
    },
  },
};

const env = process.env.VERCEL_ENV || 'development';

export const prisma = new PrismaClient(databaseConfigs[env]);

8. CI/CD 환경 분리

# .github/workflows/ci.yml
name: CI
on:
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Run tests
        run: npm test
        env:
          DATABASE_URL: postgresql://localhost:5432/test
          
      - name: Run lint
        run: npm run lint

Lessons Learned

  1. 일관된 명명 규칙: 환경 변수명을 일관되게 유지하면 관리가 용이합니다.
  2. 보안 고려: 프로덕션 키가 개발 환경에 노출되지 않도록 주의해야 합니다.
  3. 자동화: CI/CD 파이프라인에서 환경 변수를 자동으로 설정하면 실수를 줄일 수 있습니다.
  4. 문서화: 환경 변수 목록과 용도를 문서화하면 팀원들의 이해를 돕습니다.
  5. 모니터링: 환경별 설정이 올바르게 적용되는지 주기적으로 확인해야 합니다.

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.