173 lines
3.9 KiB
Markdown
173 lines
3.9 KiB
Markdown
# 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 절감
|