# 15. 배포 가이드 (Vercel)

> 대상: 프론트엔드 개발자, DevOps
> 최종 업데이트: 2026-03-20

---

## 목차

| 번호 | 항목 |
|------|------|
| 15.1 | [배포 환경](#151-배포-환경) |
| 15.2 | [환경 변수](#152-환경-변수) |
| 15.3 | [빌드 설정](#153-빌드-설정) |
| 15.4 | [Puppeteer 설정](#154-puppeteer-설정) |
| 15.5 | [배포 체크리스트](#155-배포-체크리스트) |
| 15.6 | [비용 관리](#156-비용-관리) |

---

## 15.1 배포 환경

| 환경 | 브랜치 | URL | 용도 |
|------|--------|-----|------|
| Development | `develop` | localhost:3000 | 로컬 개발 |
| Stage | `stage` | stage.xxx.com | QA/테스트 |
| Production | `main` | app.xxx.com | 실서비스 |

환경 구분은 `NEXT_PUBLIC_APP_ENV` 환경변수로 판별:

```typescript
const env = process.env.NEXT_PUBLIC_APP_ENV; // 'local' | 'development' | 'staging' | 'production'
```

---

## 15.2 환경 변수

### 필수 환경 변수

| 변수 | 설명 | 예시 |
|------|------|------|
| `NEXT_PUBLIC_API_URL` | 백엔드 API 주소 | `https://api.xxx.com` |
| `NEXT_PUBLIC_APP_ENV` | 실행 환경 | `production` |
| `JWT_SECRET` | JWT 토큰 시크릿 | (보안) |

### Vercel 설정 방법

1. Vercel Dashboard -> Settings -> Environment Variables
2. 환경별(Production/Preview/Development) 분리 설정
3. 민감 정보(JWT_SECRET 등)는 Encrypted로 저장

---

## 15.3 빌드 설정

### vercel.json

```json
{
  "functions": {
    "app/**/*.ts": {
      "memory": 1024,
      "maxDuration": 30
    }
  },
  "regions": ["icn1"]
}
```

| 설정 | 값 | 설명 |
|------|-----|------|
| memory | 1024MB | PDF 생성 등 무거운 작업 대응 |
| maxDuration | 30초 | 함수 실행 타임아웃 |
| regions | icn1 | 서울 리전 (한국 서비스) |

### TypeScript strict mode

Vercel 빌드 시 `tsc --noEmit`이 실행되므로 타입 에러가 있으면 배포 실패:

```bash
# 배포 전 로컬에서 확인
npx tsc --noEmit
```

---

## 15.4 Puppeteer 설정

PDF 생성(견적서, 거래명세서 등)을 위한 Puppeteer 환경별 분기:

```typescript
// 로컬: 시스템 Chrome 사용
// Vercel: puppeteer-core + @sparticuz/chromium (경량)

const browser = await (isVercel
  ? puppeteerCore.launch({
      args: chromium.args,
      executablePath: await chromium.executablePath(),
      headless: chromium.headless,
    })
  : puppeteer.launch({ headless: true })
);
```

### 패키지 구성

```json
{
  "dependencies": {
    "puppeteer-core": "^x.x.x",
    "@sparticuz/chromium": "^x.x.x"
  },
  "devDependencies": {
    "puppeteer": "^x.x.x"
  }
}
```

- `puppeteer`: 로컬 개발용 (devDependencies)
- `puppeteer-core` + `@sparticuz/chromium`: Vercel 배포용 (dependencies)

---

## 15.5 배포 체크리스트

### 배포 전

| # | 항목 |
|---|------|
| 1 | `npx tsc --noEmit` 에러 없음 |
| 2 | `npm run build` 성공 |
| 3 | 환경 변수 Vercel에 설정 완료 |
| 4 | 백엔드 CORS에 Vercel 도메인 추가 |
| 5 | API URL이 올바른 환경을 가리키는지 확인 |

### 배포 후

| # | 항목 |
|---|------|
| 1 | 로그인 정상 동작 (쿠키/토큰) |
| 2 | API 호출 정상 (CORS 에러 없음) |
| 3 | PDF 생성 정상 (Puppeteer) |
| 4 | 모바일 접속 확인 |

### 백엔드 CORS 설정

```php
// Laravel: config/cors.php
'allowed_origins' => [
    'https://your-app.vercel.app',
    'https://your-custom-domain.com',
],
```

---

## 15.6 비용 관리

### 예상 비용 (50개 회사 기준)

| 항목 | 월 비용 |
|------|--------|
| Serverless Functions | ~$15-20 |
| Bandwidth | ~$5-8 |
| 합계 | ~$22-28 |

### 비용 절감 전략

- **Edge Middleware**: 인증 체크 등 가벼운 로직을 Edge에서 처리 (Functions 비용 95% 절감 가능)
- **정적 페이지 최적화**: ISR(Incremental Static Regeneration) 적용 가능한 페이지 식별
- **이미지 최적화**: `next/image` 활용으로 Bandwidth 절감
