- executeServerAction 공통 유틸 도입으로 actions.ts 대폭 간소화 (50+개 파일) - sanitize 유틸 추가 (XSS 방지) - middleware CSP 헤더 추가 및 Open Redirect 방지 - 프록시 라우트 로깅 개발환경 한정으로 변경 - 프로덕션 불필요 console.log 제거 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
424 lines
19 KiB
Markdown
424 lines
19 KiB
Markdown
# Vercel 배포 프론트엔드 설정 내역
|
||
|
||
> 작성일: 2026-02-09
|
||
|
||
---
|
||
|
||
## 1. Puppeteer 패키지 교체
|
||
|
||
### 변경 내용
|
||
|
||
| 항목 | Before | After |
|
||
|------|--------|-------|
|
||
| 패키지 | `puppeteer` | `puppeteer-core` + `@sparticuz/chromium` |
|
||
|
||
### 왜 교체해야 하는가
|
||
|
||
`puppeteer`는 설치 시 **Chromium 브라우저 전체(~170MB)**를 함께 다운로드한다. 이는 로컬/Docker 환경에서는 문제없지만, Vercel 서버리스 함수는 **패키지 크기 제한(50MB 압축, 250MB 비압축)**이 있어 배포 자체가 불가능하다.
|
||
|
||
### 로컬 vs Vercel 차이
|
||
|
||
| 환경 | Chromium 제공 방식 | 설정 |
|
||
|------|-------------------|------|
|
||
| **로컬 (macOS)** | 사용자 PC에 설치된 Google Chrome 사용 | `PUPPETEER_EXECUTABLE_PATH` 환경변수로 경로 지정 |
|
||
| **Vercel (서버리스)** | `@sparticuz/chromium`이 AWS Lambda용 경량 Chromium 제공 | `chromium.executablePath()`로 자동 경로 획득 |
|
||
|
||
### 분기 처리 코드 (`src/app/api/pdf/generate/route.ts`)
|
||
|
||
```typescript
|
||
const isVercel = process.env.VERCEL === '1'; // Vercel이 자동 주입하는 환경변수
|
||
|
||
const browser = await puppeteer.launch({
|
||
args: isVercel ? chromium.args : ['--no-sandbox', ...],
|
||
executablePath: isVercel
|
||
? await chromium.executablePath() // Vercel: @sparticuz/chromium 경량 바이너리
|
||
: process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/google-chrome-stable', // 로컬: 시스템 Chrome
|
||
headless: true,
|
||
});
|
||
```
|
||
|
||
- `process.env.VERCEL === '1'`: Vercel 배포 환경에서 자동으로 설정되는 값
|
||
- `chromium.args`: 서버리스 환경에 최적화된 Chromium 실행 인자 (싱글 프로세스, SwiftShader 등)
|
||
|
||
### 로컬 환경변수 설정 (`.env.local`)
|
||
|
||
```
|
||
PUPPETEER_EXECUTABLE_PATH=/Applications/Google Chrome.app/Contents/MacOS/Google Chrome
|
||
```
|
||
|
||
기존 `puppeteer`는 Chromium을 자체 번들했으므로 경로 지정이 불필요했지만, `puppeteer-core`는 브라우저를 포함하지 않으므로 로컬에서도 Chrome 경로를 명시해야 한다.
|
||
|
||
---
|
||
|
||
## 2. next.config.ts 변경
|
||
|
||
### serverExternalPackages
|
||
|
||
| Before | After |
|
||
|--------|-------|
|
||
| `['puppeteer']` | `['puppeteer-core', '@sparticuz/chromium']` |
|
||
|
||
Webpack이 이 패키지들을 번들에 포함하지 않고 Node.js 런타임에서 직접 로드하도록 지정. `@sparticuz/chromium`은 바이너리 파일을 포함하고 있어 번들링하면 깨진다.
|
||
|
||
### TypeScript / ESLint 빌드 검사
|
||
|
||
| 항목 | Before | After | 이유 |
|
||
|------|--------|-------|------|
|
||
| `typescript.ignoreBuildErrors` | `true` | `false` | Vercel 배포 시 타입 에러가 런타임 버그로 이어질 수 있으므로 빌드 단계에서 차단 |
|
||
| `eslint.ignoreDuringBuilds` | `true` | `true` (유지) | 기존 미사용 import 에러 791개 존재, 점진적 해결 예정 |
|
||
|
||
---
|
||
|
||
## 3. vercel.json 생성
|
||
|
||
```json
|
||
{
|
||
"regions": ["icn1"],
|
||
"functions": {
|
||
"src/app/api/pdf/generate/route.ts": {
|
||
"memory": 1024,
|
||
"maxDuration": 30
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
| 설정 | 값 | 이유 |
|
||
|------|-----|------|
|
||
| `regions` | `icn1` (서울) | 사용자가 한국에 위치, 백엔드 API도 한국 서버 |
|
||
| `memory` | 1024MB | Chromium 브라우저 실행에 최소 512MB 이상 필요, PDF 렌더링 안정성 확보 |
|
||
| `maxDuration` | 30초 | 복잡한 문서의 PDF 변환 시 기본 10초로는 부족 |
|
||
|
||
---
|
||
|
||
## 4. 환경변수 가이드
|
||
|
||
Vercel Dashboard에 등록해야 할 환경변수 목록은 `claudedocs/vercel/vercel-env-setup-guide.md` 참조.
|
||
|
||
핵심 포인트:
|
||
- `API_KEY`: Sensitive 체크 필수, `NEXT_PUBLIC_` 접두사 절대 금지
|
||
- `PUPPETEER_EXECUTABLE_PATH`: Vercel에서는 설정 불필요 (`@sparticuz/chromium`이 처리)
|
||
- `VERCEL=1`: Vercel이 자동 주입, 별도 설정 불필요
|
||
|
||
---
|
||
|
||
## 5. TypeScript 에러 수정
|
||
|
||
`ignoreBuildErrors: false`로 변경하면서 기존에 숨겨져 있던 TS 에러 16개+ 수정.
|
||
|
||
| 에러 유형 | 파일 수 | 원인 |
|
||
|-----------|--------|------|
|
||
| `WorkOrderItem` 프로퍼티 누락 | 5개 파일 | `orderNodeId`, `orderNodeName` 필드 추가 후 목업 데이터 미갱신 |
|
||
| `WorkOrder` 프로퍼티 누락 | 3개 파일 | `shutterCount` 필드 추가 후 합성 객체 미갱신 |
|
||
| `unknown` → `ReactNode` | 1개 파일 | `Record<string, unknown>` 값을 JSX에 직접 사용 |
|
||
| `object` 프로퍼티 접근 | 2개 파일 | `Object.entries()` 후 타입 narrowing 부족 |
|
||
| 타입 미export | 1개 파일 | `BomCalculationResult` import만 하고 re-export 안 함 |
|
||
| implicit `any` | 1개 파일 | 콜백 파라미터 타입 어노테이션 누락 |
|
||
|
||
---
|
||
|
||
## 변경 파일 전체 목록
|
||
|
||
```
|
||
수정:
|
||
src/app/api/pdf/generate/route.ts # Puppeteer 교체
|
||
next.config.ts # 빌드 설정
|
||
package.json / package-lock.json # 패키지 교체
|
||
.env.local # Chrome 경로 추가
|
||
.env.example # Chrome 경로 가이드 추가
|
||
|
||
신규:
|
||
vercel.json # Vercel 배포 설정
|
||
claudedocs/vercel/vercel-env-setup-guide.md # 환경변수 가이드
|
||
claudedocs/vercel/vercel-deployment-setup.md # 이 문서
|
||
|
||
TS 에러 수정 (13개 파일):
|
||
src/app/[locale]/(protected)/quality/qms/components/InspectionModalV2.tsx
|
||
src/app/[locale]/(protected)/quality/qms/mockData.ts
|
||
src/components/material/ReceivingManagement/actions.ts
|
||
src/components/orders/OrderSalesDetailView.tsx
|
||
src/components/production/WorkerScreen/index.tsx
|
||
src/components/production/WorkerScreen/WorkLogModal.tsx
|
||
src/components/production/WorkOrders/documents/InspectionReportModal.tsx
|
||
src/components/production/WorkOrders/WorkOrderDetail.tsx
|
||
src/components/production/WorkOrders/WorkOrderEdit.tsx
|
||
src/components/quotes/LocationDetailPanel.tsx
|
||
src/components/quotes/QuoteSummaryPanel.tsx
|
||
src/components/quotes/QuotePreviewContent.tsx
|
||
src/components/quotes/actions.ts
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Vercel 비용 주의사항
|
||
|
||
### 비용 발생 구조
|
||
|
||
Vercel은 **서버리스 함수 호출 횟수 + 실행 시간 + 대역폭**으로 과금된다. 우리 프로젝트에서 비용이 튈 수 있는 요소를 분석한다.
|
||
|
||
### 6-1. API Proxy 패턴 (가장 큰 비용 요소)
|
||
|
||
현재 구조: `클라이언트 → /api/proxy/* (Vercel 서버리스) → PHP 백엔드`
|
||
|
||
| 문제 | 설명 |
|
||
|------|------|
|
||
| **이중 대역폭** | 모든 API 응답이 Vercel 서버리스를 거쳐 클라이언트로 전달 (대역폭 2배) |
|
||
| **함수 호출 폭발** | 모든 API 요청이 서버리스 함수 1회 호출 = 페이지 로드마다 수~수십 회 |
|
||
| **실행 시간 누적** | 각 함수가 백엔드 응답을 기다리는 시간만큼 과금 |
|
||
|
||
**왜 이 패턴을 쓰는가**: HttpOnly 쿠키에 저장된 `access_token`은 JavaScript로 읽을 수 없어서, 서버(서버리스 함수)에서 쿠키를 읽어 `Authorization` 헤더로 변환해야 한다.
|
||
|
||
**예상 영향**: 사용자 수가 늘어날수록 비용이 선형 증가. ERP 특성상 한 페이지에서 3-10개 API를 호출하므로, 동시 접속자 50명이면 분당 수백~수천 회 함수 호출 가능.
|
||
|
||
### 6-1-1. 30초 폴링 — 가장 심각한 비용 요소
|
||
|
||
프로젝트에 **30초 간격 폴링이 2개** 존재하며, 이것들이 서버리스 프록시를 통과한다.
|
||
|
||
| 폴링 | 파일 | 간격 | 호출 API |
|
||
|------|------|------|---------|
|
||
| **메뉴 폴링** | `src/hooks/useMenuPolling.ts` | 30초 | `refreshMenus()` → `/api/proxy/*` |
|
||
| **알림(Today Issue) 폴링** | `src/layouts/AuthenticatedLayout.tsx` | 30초 | `getUnreadTodayIssues()` → `/api/proxy/*` |
|
||
|
||
**폴링만의 서버리스 함수 호출 추정 (동시접속 50명, 8시간 근무 기준)**:
|
||
|
||
```
|
||
메뉴 폴링: 50명 × 2회/분 × 60분 × 8시간 = 48,000회/일
|
||
알림 폴링: 50명 × 2회/분 × 60분 × 8시간 = 48,000회/일
|
||
─────────────────────────────────────────────────────────
|
||
합계: 96,000회/일 (폴링만으로, 일반 API 호출 제외)
|
||
월간: 96,000 × 22일(근무일) = 약 2,112,000회/월
|
||
```
|
||
|
||
Vercel Pro 플랜 기준 서버리스 함수 포함 실행량 100만 회/월이므로, **폴링만으로 2배 초과**. 이 폴링 2개가 Edge Middleware로 전환 시 가장 큰 비용 절감 효과를 볼 수 있다.
|
||
|
||
> 참고: 두 폴링 모두 탭 비활성 시 일시정지하는 최적화가 적용되어 있지만, 활성 탭 기준으로는 위 수치가 그대로 적용된다.
|
||
|
||
### 6-2. PDF 생성 함수
|
||
|
||
| 항목 | 값 | 비용 영향 |
|
||
|------|-----|----------|
|
||
| 메모리 | 1024MB | 기본(128MB) 대비 8배 비용 |
|
||
| 최대 실행 시간 | 30초 | 긴 실행 = 높은 과금 |
|
||
| 빈도 | 낮음 (수동 PDF 변환) | 자동 배치가 아니므로 실제 비용 영향은 적음 |
|
||
|
||
PDF는 사용 빈도가 낮아 큰 문제는 아니지만, 메모리 1024MB로 설정했으므로 호출당 비용이 높다.
|
||
|
||
### 6-3. Server Actions (bodySizeLimit: 10MB)
|
||
|
||
`next.config.ts`에서 `serverActions.bodySizeLimit: '10mb'`로 설정. 이미지 업로드 시 큰 페이로드가 서버리스 함수를 통과하므로 대역폭 비용 발생. 단, 이미지 저장 자체는 PHP 백엔드가 처리하므로 Vercel 스토리지 비용은 없음.
|
||
|
||
### 6-4. 비용 안전 요소
|
||
|
||
| 항목 | 상태 | 이유 |
|
||
|------|------|------|
|
||
| 이미지/파일 저장 | 안전 | PHP 백엔드 서버에 저장, Vercel에 저장 안 함 |
|
||
| Vercel Image Optimization | 미사용 | `remotePatterns`에 `placehold.co`만 등록 (개발용) |
|
||
| ISR/SSG | 미사용 | 전체 Client Component, 정적 생성 없음 |
|
||
|
||
---
|
||
|
||
## 7. API Proxy 비용 절감 방안
|
||
|
||
### 현재 문제
|
||
|
||
```
|
||
클라이언트 → [Vercel 서버리스 함수] → PHP 백엔드
|
||
↑ 매 API 요청마다 호출
|
||
↑ Node.js Runtime (비쌈)
|
||
```
|
||
|
||
`/api/proxy/[...path]/route.ts`가 **모든 백엔드 API 호출을 중계**하므로 서버리스 함수 호출 횟수가 폭발적으로 증가한다.
|
||
|
||
### 방안 1: Edge Middleware Rewrite (프론트엔드 변경만으로 가능)
|
||
|
||
```
|
||
클라이언트 → [Edge Middleware] → PHP 백엔드 (직접)
|
||
↑ Edge Runtime (매우 저렴)
|
||
↑ 쿠키 읽기 가능
|
||
```
|
||
|
||
**원리**: 현재 `middleware.ts`는 이미 Edge Runtime에서 쿠키를 읽고 있다. 이를 확장하여 `/api/proxy/*` 요청을 Edge에서 백엔드로 직접 rewrite하면 서버리스 함수 호출을 제거할 수 있다.
|
||
|
||
**장점**:
|
||
- Edge 함수는 서버리스 대비 **10-100배 저렴** (실행 시간이 아닌 요청 수 기준)
|
||
- 프론트엔드만 변경하면 됨 (백엔드 수정 불필요)
|
||
- 응답 지연(latency)도 감소 (중간 서버리스 단계 제거)
|
||
|
||
**한계**:
|
||
- Edge Runtime은 Node.js API 일부를 사용 못함
|
||
- **토큰 자동 갱신(refresh)** 처리가 복잡해짐 — 현재 `authenticatedFetch`가 401 감지 → refresh → retry를 처리하는데, Edge Middleware의 rewrite에서는 이 패턴 구현이 어려움
|
||
- FormData/바이너리 응답 처리에 제약 가능
|
||
|
||
**적용 가능 범위**: 단순 GET/POST API 호출 (토큰 갱신 없이 정상 동작하는 요청)
|
||
|
||
### 방안 2: 백엔드 CORS 허용 + 직접 호출 (백엔드 변경 필요)
|
||
|
||
```
|
||
클라이언트 → PHP 백엔드 (직접)
|
||
↑ Vercel을 거치지 않음
|
||
↑ 서버리스 비용 0
|
||
```
|
||
|
||
**원리**: PHP 백엔드가 Vercel 도메인에서의 CORS를 허용하고, 쿠키를 직접 설정(`SameSite=None; Secure`)하면 프록시 자체가 불필요해진다.
|
||
|
||
**장점**:
|
||
- 서버리스 함수 호출 **완전 제거**
|
||
- 가장 큰 비용 절감 효과
|
||
- 응답 속도 최적 (중간 단계 없음)
|
||
|
||
**한계**:
|
||
- **백엔드 수정 필수**: CORS 헤더, 쿠키 SameSite 정책 변경
|
||
- **HttpOnly 쿠키 도메인 문제**: 프론트(Vercel)와 백엔드(PHP)가 다른 도메인이면 3rd-party 쿠키로 분류되어 브라우저 차단 가능
|
||
- 같은 도메인/서브도메인 구조가 아니면 추가 설정 필요 (`app.example.com` ↔ `api.example.com`)
|
||
|
||
### 방안 3: 하이브리드 (권장)
|
||
|
||
| 요청 유형 | 처리 방식 | 비용 |
|
||
|-----------|----------|------|
|
||
| 단순 데이터 조회 (GET) | Edge Middleware rewrite | 매우 저렴 |
|
||
| 데이터 변경 (POST/PUT/DELETE) | 기존 서버리스 프록시 유지 | 현행 유지 |
|
||
| 파일 업로드 (multipart) | 기존 서버리스 프록시 유지 | 현행 유지 |
|
||
| 토큰 갱신 필요 시 | 기존 서버리스 프록시 유지 | 현행 유지 |
|
||
|
||
GET 요청이 전체 API 호출의 60-80%를 차지하므로, 이것만 Edge로 옮겨도 비용을 절반 이상 줄일 수 있다.
|
||
|
||
### 방안 비교 요약
|
||
|
||
| 방안 | 비용 절감 | 프론트 변경 | 백엔드 변경 | 복잡도 | 권장 |
|
||
|------|----------|------------|------------|--------|------|
|
||
| **1. Edge Rewrite** | 중 (60-80%) | O | X | 중 | 단기 |
|
||
| **2. CORS 직접 호출** | 최대 (95%+) | O | O | 고 | 장기 |
|
||
| **3. 하이브리드** | 중상 (60-80%) | O | X | 중 | **현실적 1순위** |
|
||
|
||
### 다음 단계
|
||
|
||
1. Vercel 배포 후 실제 함수 호출 횟수/비용 모니터링
|
||
2. 비용이 예상보다 높으면 방안 3(하이브리드) 우선 적용
|
||
3. 장기적으로 백엔드팀과 협의하여 방안 2(CORS) 검토
|
||
|
||
---
|
||
|
||
## 8. 월간 비용 산정 (Vercel Pro, 서울 icn1 리전)
|
||
|
||
> 산정일: 2026-02-09 / 출처: [Vercel Pricing](https://vercel.com/pricing), [Fluid Compute Pricing](https://vercel.com/docs/functions/usage-and-pricing)
|
||
|
||
### 8-1. Vercel 요금 구조 (Pro 플랜)
|
||
|
||
| 항목 | Pro 포함량 | 초과 단가 |
|
||
|------|-----------|----------|
|
||
| **기본 요금** | $20/개발자 시트/월 | — |
|
||
| **사용 크레딧** | $20/월 포함 (사용량 차감) | — |
|
||
| **Invocations** (함수 호출) | 크레딧 차감 | $0.60 / 100만 회 |
|
||
| **Active CPU** (icn1) | 크레딧 차감 | $0.169 / 시간 |
|
||
| **Provisioned Memory** (icn1) | 크레딧 차감 | $0.014 / GB-시간 |
|
||
| **Edge Requests** | 1,000만 회/월 | ~$2 / 100만 회 |
|
||
| **Bandwidth** | 1TB/월 | 초과 시 GB당 과금 |
|
||
|
||
> Fluid Compute 모델: Active CPU는 **코드 실행 중에만** 과금 (I/O 대기 시 과금 안 됨). Provisioned Memory는 **인스턴스 활성 시간** 전체 과금.
|
||
|
||
### 8-2. 트래픽 추정 전제 (실제 사업 구조 반영)
|
||
|
||
| 전제 | 값 | 비고 |
|
||
|------|-----|------|
|
||
| 개발자 시트 | **2명** | 프론트엔드 2명 |
|
||
| 서비스 회사 수 | **50개 이하** (초기) | 점진적 확장 |
|
||
| 회사당 이용자 | **~5명** | ERP 실사용자 |
|
||
| 총 등록 사용자 | **~250명** | 50사 × 5명 |
|
||
| 동시접속률 | **30~40%** | ERP 특성 (전원 동시 사용 안 함) |
|
||
| **동시접속 사용자** | **~75~100명** | 250명 × 30~40% |
|
||
| 근무 시간 | 8시간/일 | |
|
||
| 월 근무일 | 22일 | |
|
||
| 메뉴 폴링 간격 | 30초 | `useMenuPolling.ts` |
|
||
| 알림 폴링 간격 | 30초 | `AuthenticatedLayout.tsx` |
|
||
| 페이지 이동 시 API 호출 | 평균 5개/페이지 | |
|
||
| 페이지 이동 횟수 | 평균 50회/사용자/일 | |
|
||
| PDF 생성 | 100건/월 | |
|
||
|
||
### 8-3. 월간 함수 호출 횟수 (동시접속 75명 기준)
|
||
|
||
```
|
||
① 메뉴 폴링: 75명 × 2회/분 × 480분 × 22일 = 1,584,000회
|
||
② 알림 폴링: 75명 × 2회/분 × 480분 × 22일 = 1,584,000회
|
||
③ 페이지 API: 75명 × 250회/일 × 22일 = 412,500회
|
||
④ PDF 생성: = 100회
|
||
──────────────────────────────────────────────────────────────
|
||
합계: 3,580,600회/월
|
||
```
|
||
|
||
### 8-4. 시나리오 A — 현재 구조 (전부 서버리스 프록시)
|
||
|
||
모든 API 호출이 `/api/proxy/[...path]` 서버리스 함수를 경유.
|
||
|
||
**API 프록시 1회당 비용 추정 (icn1)**:
|
||
- Active CPU: ~30ms (쿠키 읽기, 헤더 구성, 응답 파싱)
|
||
- Instance alive: ~300ms (백엔드 응답 대기 포함)
|
||
- Memory: 128MB (0.128 GB)
|
||
|
||
| 항목 | 계산 | 월 비용 |
|
||
|------|------|--------|
|
||
| **Invocations** | 3,580,000 × $0.60/1M | $2.15 |
|
||
| **Active CPU** | 3,580,000 × 0.03s = 107,400s = 29.8hr × $0.169 | $5.04 |
|
||
| **Provisioned Memory** | 3,580,000 × 0.128GB × 0.3s / 3600 = 38.2 GB-hr × $0.014 | $0.53 |
|
||
| **PDF CPU** | 100 × 5s / 3600 × $0.169 | $0.02 |
|
||
| **PDF Memory** | 100 × 1GB × 15s / 3600 × $0.014 | $0.01 |
|
||
| **함수 사용량 소계** | | **$7.75** |
|
||
| **기본 요금** | 개발자 2명 × $20 | **$40.00** |
|
||
| **사용 크레딧** | -$20 (포함) | **-$20.00** |
|
||
| **예상 월 합계** | | **~$28** |
|
||
|
||
> 함수 사용량 $7.75는 $20 크레딧 이내. 초과 과금 없음.
|
||
|
||
### 8-5. 시나리오 B — 하이브리드 (폴링 + GET을 Edge로)
|
||
|
||
폴링 2개 + 일반 GET을 Edge Middleware rewrite로 전환. POST/PUT/DELETE/파일업로드만 서버리스 유지.
|
||
|
||
```
|
||
Edge로 이동: 폴링 3,168,000 + GET ~300,000 = ~3,468,000 → Edge Requests (10M 포함 이내)
|
||
서버리스 유지: POST/PUT/DELETE ~112,500 + PDF 100 = ~112,600
|
||
```
|
||
|
||
| 항목 | 계산 | 월 비용 |
|
||
|------|------|--------|
|
||
| **Edge Requests** | 3,468,000회 (10M 포함 이내) | $0 |
|
||
| **Invocations** | 112,600회 × $0.60/1M | $0.07 |
|
||
| **Active CPU** | 112,600 × 0.05s / 3600 × $0.169 | $0.26 |
|
||
| **Provisioned Memory** | 112,600 × 0.128GB × 0.4s / 3600 × $0.014 | $0.02 |
|
||
| **PDF** | (위와 동일) | $0.03 |
|
||
| **함수 사용량 소계** | | **$0.38** |
|
||
| **기본 요금** | 개발자 2명 × $20 | **$40.00** |
|
||
| **사용 크레딧** | -$20 (포함) | **-$20.00** |
|
||
| **예상 월 합계** | | **~$20** |
|
||
|
||
### 8-6. 성장 단계별 비용 비교
|
||
|
||
| 단계 | 서비스 회사 | 총 사용자 | 동시접속 | 시나리오 A | 시나리오 B |
|
||
|------|-----------|----------|---------|-----------|-----------|
|
||
| **초기** | 10사 | 50명 | ~20명 | **~$22** (함수 $2) | **~$20** (함수 $0.1) |
|
||
| **안정기** | 50사 | 250명 | ~75명 | **~$28** (함수 $8) | **~$20** (함수 $0.4) |
|
||
| **성장기** | 100사 | 500명 | ~150명 | **~$35** (함수 $15) | **~$21** (함수 $0.8) |
|
||
| **확장기** | 200사 | 1,000명 | ~300명 | **~$50** (함수 $30) | **~$22** (함수 $1.5) |
|
||
|
||
> 모든 단계에서 고정 비용 = 개발자 2시트 $40 − 크레딧 $20 = **$20**. 함수 비용은 이 $20 크레딧에서 차감되며, 초기~안정기에는 크레딧 이내로 해결됨.
|
||
|
||
### 8-7. 결론
|
||
|
||
- **초기~안정기 (50사 이하)**: 월 **~$22~28**. 함수 비용 $8 이하로 **크레딧 $20 이내**. 최적화 불필요.
|
||
- **성장기 (100사)**: 함수 비용 $15. 아직 크레딧 이내이지만 여유 줄어듦. 하이브리드 전환 검토 시점.
|
||
- **확장기 (200사 이상)**: 함수 비용이 크레딧 초과 → 추가 과금 발생. 하이브리드 전환 필수.
|
||
- **핵심 비용은 개발자 시트**. 프론트 2명 기준 고정 $20/월. 함수 비용은 초기에 미미.
|
||
- 폴링 2개만 Edge로 전환해도 함수 비용 **95% 절감** 가능 (100사 기준 $15 → $0.8).
|
||
|
||
---
|
||
|
||
## 배포 전 체크리스트
|
||
|
||
- [x] `puppeteer-core` + `@sparticuz/chromium` 설치
|
||
- [x] PDF 라우트 로컬/Vercel 분기 처리
|
||
- [x] `next.config.ts` 설정 변경
|
||
- [x] `vercel.json` 생성
|
||
- [x] TypeScript 에러 0개 확인
|
||
- [x] 로컬 Chrome 경로 설정 (`.env.local`)
|
||
- [ ] 로컬 PDF 변환 테스트
|
||
- [ ] Vercel Dashboard 환경변수 등록
|
||
- [ ] Vercel 배포 및 PDF 변환 테스트
|