Vercel의 Build Output API를 활용해 React 기반 웹 프레임워크를 처음부터 구현하는 과정을 단계별 코드로 설명한다. 정적 렌더링(Static), ISR(Incremental Static Regeneration), 서버 사이드 렌더링(SSR), Edge 렌더링, 이미지 최적화까지 모던 프레임워크가 제공하는 핵심 기능을 직접 구현함으로써, Next.js 같은 프레임워크 내부 동작 원리를 깊이 이해할 수 있다. 모든 렌더링 패턴은 `.vercel/output/` 폴더 구조를 생성하는 방식으로 Vercel 인프라와 연결된다.
핵심 포인트- Vercel Build Output API는 `.vercel/output/` 폴더 구조를 인프라 프리미티브로 변환 — 프레임워크 무관 표준 배포 인터페이스
- 정적 렌더링: `ReactDOM.renderToString(Component)` 으로 빌드 타임 HTML 생성 + hydration 번들을 deferred script로 주입
- ISR = Serverless Function(재생성 핸들러) + `prerender-config.json`(만료 시간) + fallback HTML 3종 세트
- Edge 렌더링: `.vc-config.json`에 `runtime: "edge"` 설정. Node.js 없이 `Response` 객체로 HTML 반환
- ISR은 캐시 만료 시에만 Lambda 호출. SSR은 매 요청마다 함수 호출 — 캐싱 동작의 핵심 차이
- `/_vercel/image?url=&w=&q=` 경로 + `vercel.config.js` 설정으로 자동 이미지 최적화(WebP/AVIF) 적용
상세 정리- **Build Output API 폴더 구조**: `.vercel/output/static/` (정적 파일), `.vercel/output/functions/<name>.func/` (서버리스/엣지 함수), `.vercel/output/config.json` (라우팅/이미지 설정)
- **정적 렌더링 구현**: `ReactDOM.renderToString()` 으로 HTML 생성 → `.vercel/output/static/` 에 저장. esbuild로 클라이언트 번들 생성 후 HTML에 deferred script로 주입해 hydration 처리
- **ISR 4종 파일**: `products.func/index.js`(재생성 핸들러), `products.func/.vc-config.json`(Node.js 16.x + launcherType: Nodejs), `products.prerender-config.json`(expiration + fallback 경로), `products.prerender-fallback.html`(캐시 없을 때 표시할 정적 fallback)
- **Serverless Function 구현**: `createServerlessFunction()` 이 `generateClientBundle`(클라이언트 번들)과 `generateLambdaBundle`(Lambda 번들)을 `Promise.allSettled` 로 병렬 생성. 핸들러는 `res.setHeader('Content-type', 'text/html')` + `res.end(html)` 방식
- **Edge Function vs Serverless Function**: Edge는 `.vc-config.json`에 `runtime: "edge"`, `entrypoint: "index.js"`. React가 Node.js 없이 동작하는 isomorphic 특성 활용, 핸들러가 Web API `Response` 객체 반환
- **ISR vs SSR 캐싱 차이**: ISR은 `prerender-config.json`의 `expiration` 값 기준으로 캐시 만료 시에만 Lambda 호출 (Stale-While-Revalidate). SSR은 매 요청마다 함수 호출, Vercel이 자동 캐시하지 않음
- **이미지 최적화 구현**: 커스텀 `Image` 컴포넌트가 src를 `/_vercel/image?url=encodeURIComponent(src)&w=width&q=75` 로 자동 변환. `vercel.config.js`에서 domains, sizes, minimumCacheTTL, formats(webp/avif) 설정
- **빌드 오케스트레이션**: `buildVercelOutput()` 이 `pages/` 디렉토리를 순회해 `pageConfig.strategy` ('static'|'prerender'|'ssr'|'edge') 에 따라 적절한 생성 함수 디스패치
- **라우팅 통합**: `getTransformedRoutes({ cleanUrls: true })` 로 클린 URL + 라우트 설정 자동 생성, `config.json`에 포함
왜 읽나Next.js 같은 프레임워크가 내부에서 정적 렌더링·ISR·Edge·SSR을 어떻게 구현하는지 직접 코드로 확인할 수 있어, 프레임워크 추상화 뒤의 실질적 인프라 원리를 이해하는 가장 직관적인 방법이다.