Next.js를 Cloudflare Pages에 배포하면서 겪은 일들
2026.04.05
Vercel 대신 Cloudflare Pages를 선택한 이유
Next.js를 배포하려면 가장 먼저 떠오르는 건 Vercel이다. Next.js를 만든 회사니까 호환성이 완벽하다. 하지만 한 가지 제약이 있었다.
Vercel Hobby 플랜은 상업적 용도로 사용할 수 없다.
블로그에 광고를 붙여서 수익화하려면 Pro 플랜(월 $20)이 필요하다. 아직 수익이 0원인 상태에서 매달 호스팅비를 내고 싶지 않았다.
Cloudflare Pages는 무료 플랜에서도 상업적 사용이 가능하고, 대역폭도 무제한이다.
@cloudflare/next-on-pages
Cloudflare Pages에 Next.js를 배포하려면 @cloudflare/next-on-pages 패키지가 필요하다. 이 패키지가 Next.js의 빌드 출력을 Cloudflare Pages가 이해할 수 있는 형태로 변환해준다.
npm install -D @cloudflare/next-on-pagespackage.json에 빌드 스크립트를 추가한다.
{
"scripts": {
"pages:build": "npx @cloudflare/next-on-pages"
}
}Cloudflare 대시보드에서 Build command를 npm run pages:build로 설정하면 된다.
트러블슈팅: nodejs_compat 에러
배포 후 첫 번째로 만난 에러가 이것이었다.
Node.JS Compatibility Error
no nodejs_compat compatibility flag set
Next.js는 내부적으로 Node.js API를 사용하는데, Cloudflare Workers는 기본적으로 Node.js 호환 모드가 꺼져 있다.
시도 1: wrangler.toml 추가
name = "joowonkoh-dev"
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat"]프로젝트 루트에 wrangler.toml을 추가하고 push했지만, 적용되지 않았다. Cloudflare Pages는 wrangler.toml의 모든 설정을 읽지 않는 경우가 있다.
시도 2: 대시보드에서 직접 설정 (해결)
결국 Cloudflare 대시보드에서 직접 설정했다.
- Workers & Pages → 프로젝트 선택
- Settings → Runtime
- Compatibility flags에
nodejs_compat추가 - Compatibility date를
2024-09-23으로 설정 - 재배포
이렇게 하니 정상적으로 배포가 되었다.
교훈: Cloudflare Pages의 일부 설정은 대시보드에서 직접 해야 한다. 코드로 관리하고 싶은 마음은 이해하지만, 플랫폼이 아직 모든 설정의 코드 기반 관리를 지원하지는 않는다.
next.config.ts 설정
Cloudflare Pages와 호환되려면 두 가지 설정이 필요하다.
const nextConfig = {
output: "standalone", // 독립 실행 가능한 빌드
images: {
unoptimized: true, // Cloudflare는 Next.js Image Optimization 미지원
},
};images.unoptimized를 true로 안 하면 이미지 최적화 API 관련 에러가 난다. Cloudflare에서는 자체 CDN이 이미지를 캐싱하고 최적화하니까, Next.js의 이미지 최적화는 끄는 게 맞다.
SSG vs SSR
Cloudflare Pages에서 정적 페이지(SSG)는 아무 문제 없이 동작한다. SSR이 필요한 페이지는 Cloudflare Workers가 처리한다. @cloudflare/next-on-pages가 빌드 시 자동으로 분리해준다.
이 블로그는 대부분 SSG로 충분하다. 블로그 글, 프로젝트 목록, 소개 페이지 모두 빌드 타임에 생성된다. 나중에 플레이그라운드에 인터랙티브한 기능을 넣으면 그때 SSR을 부분적으로 사용할 계획이다.
직접 겪은 일: 빌드 산출물 경로에서 한참 멈췄다
제일 오래 붙잡힌 건 에러가 아니라 경로였다.
package.json의 배포 스크립트는 이렇게 생겼다.
npx @cloudflare/next-on-pages
npx wrangler pages dev .vercel/output/staticCloudflare에 올리는데 폴더 이름이 .vercel이다. 처음 봤을 때 설정을 잘못한 줄 알고 한참 뒤졌다. 알고 보니 next-on-pages가 Vercel의 빌드 출력 규격을 중간 형식으로 쓰기 때문이다. 잘못된 게 아니라 원래 그렇다.
next.config.ts에는 output: "standalone"이 들어 있다. 이것도 Cloudflare용이라기보다 «Node 서버 하나로 묶어라»에 가까운 설정이라 이름만 봐서는 연결이 안 된다.
배포 문서를 읽을 때 제일 헷갈렸던 게 이런 것들이었다. 에러는 검색하면 답이 나오는데, «이 이름이 왜 여기 나오는가»는 검색어를 만들기가 어렵다. 결국 도구가 무엇을 중간 형식으로 쓰는지를 알아야 풀린다.
배포 플로우
최종적으로 배포 과정은 이렇게 된다.
- 코드 수정 또는 새 글 작성
git push- Cloudflare Pages가 자동 감지 → 빌드 시작
npm run pages:build실행- 빌드 결과물 배포
- 커스텀 도메인(joowonkoh.dev)으로 접근 가능
PR을 올리면 프리뷰 URL도 자동으로 생성된다. 글을 올리기 전에 미리 확인할 수 있어서 편하다.
같이 읽으면 좋은 글
주니어에서 미들 개발자로 가며 바뀐 도구들
주니어 시절에는 IDE 하나면 충분하다고 생각했다. 미들로 오면서 도구가 늘었고, 줄어들기도 했다. 매일 쓰는 도구를 카테고리별로 비교하며 무엇이 변했는지 정리한다.
회고도구2026.04.26mise(구 rtx)로 Node·Python·Go 버전 관리 통합하기
nvm, pyenv, gvm을 따로 깔지 않고 mise 하나로 합치는 법. .tool-versions로 프로젝트별 자동 버전 전환, asdf와의 차이, .env 자동 로딩, 그리고 좋은 걸 알면서 아직 안 옮긴 이유까지 정리한다.
개발환경도구2026.04.18