Vercel의 무료 사용량 제한으로 블로그 호스팅을 Vercel에서 Netlify로 이전했던 일이 있었습니다.

https://blog.huns.site/posts/dev/blog/v2/nextjs-hosting-migration-from-vercel-to-netlify

옮긴 지 얼마 안 됐는데, 또다시 플랫폼을 옮겨야 하는 상황이 되었습니다. 있는 줄도 몰랐던 Netlify Free 플랜의 빌드 크레딧 한도 때문이었어요. 이게 생각보다 빠르게 소진되더라고요.

Netlify Free 플랜 한도 초과돈 더 내라

이제는 피곤해졌습니다. 돈을 내더라도 내가 통제할 수 있는 환경에서 호스팅을 하고 싶어요. 최근 인프라 관련으로 관심이 많던 AWS를 일부러 선택했고, Web Framework를 지원하는 Amplify로 이전하기로 결정했습니다. 종량제 과금 방식이라 한도 초과 걱정 없이 사용할 수 있습니다.

Netlify Free 플랜은 월 300 크레딧을 제공해요. 문제는 배포 한 번에 15 크레딧이 소비된다는 점이죠. (출처: Netlify Credit-based pricing)

text
300 크레딧 ÷ 15 크레딧/배포 = 20회 배포

한 달에 20번만 배포할 수 있다는 의미예요. 블로그 포스트를 자주 수정하거나 여러 번 배포하다 보면 금방 한도에 도달합니다.

이전에 Vercel에서 Netlify로 이전한 이유는 Fast Origin Transfer 10GB 한도 문제였습니다. 플랫폼마다 무료 플랜의 제약이 다릅니다.

여러 플랫폼을 비교해봤어요.

플랫폼문제점비고
Vercel HobbyFast Origin Transfer 10GB 한도, 배포마다 전체 캐시 무효화Vercel Hobby Plan
Netlify Free300 크레딧 한도, 배포당 15 크레딧 소비Netlify Credit-based pricing
Cloudflare PagesEdge Runtime 제약, Node.js 풀 지원 안 됨Cloudflare Workers Node.js
AWS Amplify종량제, 한도 걱정 없음AWS Amplify Pricing

쓴 만큼만 내면 됩니다. 예상 비용은 월 $1~2 수준이에요. (AWS Amplify Pricing)

text
빌드: 월 100분 (20회 × 5분) → $1.00 Bandwidth: 월 ~5GB → $0.75 저장: ~500MB → $0.01 총: ~$1.76/월

https://aws.amazon.com/free/

저는 해당되지 않지만, 새 AWS 계정이라면 12개월 동안 무료 티어를 사용할 수 있어요.

  • 빌드 1,000분
  • 저장 5GB
  • 전송 15GB

https://developers.cloudflare.com/workers/runtime-apis/nodejs/

Cloudflare Pages와 달리 Node.js 환경을 완전히 지원합니다. API Route가 복잡해져도 문제없어요.

https://docs.aws.amazon.com/amplify/latest/userguide/ssr-amplify-support.html

Next.js 15까지 네이티브로 지원해요. 별도 어댑터 없이 바로 배포할 수 있습니다.

Amplify 사용 시 아래 내용에 유의해야 합니다.

  • On-Demand ISR 미지원: revalidatePath(), revalidateTag() 같은 On-Demand ISR 기능은 동작하지 않습니다. (Amplify SSR supported features) 대신 시간 기반 ISR(revalidate: 3600)은 정상 지원됩니다.
  • Next.js 12-15만 공식 지원 (16은 Webpack 모드로 우회 필요) (Amplify support for Next.js)
  • Edge API Routes 미지원
  • Cold Start 발생 가능 (Lambda 기반)

블로그 특성상 시간 기반 ISR로 충분하고, Edge 기능도 필요 없어서 문제없어요. Next.js 16은 Webpack 모드로 빌드하면 정상 배포가 가능합니다.

text
huns-log (Next.js 16 + MDX) ├── 약 450개 페이지 (포스트 + 카테고리) ├── ISR 사용 중 (revalidate: 3600) ├── 이미지: AWS S3 + CloudFront CDN └── 도메인: blog.huns.site

마이그레이션을 5단계로 나눴어요.

단계내용
Phase 1Netlify 백업, AWS 계정 준비
Phase 2Amplify 앱 생성, 환경변수 이전
Phase 3amplify.yml 생성, 코드 호환성 확인
Phase 4DNS 변경, SSL 설정
Phase 5전체 기능 검증

pnpm을 사용하는 프로젝트의 amplify.yml 설정입니다.

amplify.yml
version: 1 frontend: phases: preBuild: commands: - corepack enable - corepack prepare pnpm@latest --activate - pnpm install build: commands: - pnpm build artifacts: baseDirectory: .next files: - '**/*' cache: paths: - node_modules/**/* - .next/cache/**/* - .mdx-cache/**/*

Next.js 16은 Turbopack이 기본이지만, Amplify와 호환되지 않습니다. 반드시 --webpack 플래그를 사용해야 해요. (아래 트러블슈팅 참고)

Amplify 배포 전에 확인해야 할 사항들이에요.

terminal
# Edge Runtime 사용 여부 확인 grep -r "runtime.*edge" src/app/api/

있다면 제거해야 합니다. Amplify는 Edge API Routes를 지원하지 않거든요.

terminal
# On-Demand ISR 사용 여부 확인 grep -r "revalidatePath\|revalidateTag" src/

사용 중이라면 시간 기반 ISR로 대체해야 해요.

호스팅 구조를 바꾸는 건 꽤나 도전적인 미션입니다. 그리 대단한 블로그는 아니지만, 제 자존심인만큼 공백이 발생하는 걸 두고 볼 수 없습니다. 문제가 생기면 Netlify로 바로 복구할 수 있어야 해요.

  1. DNS를 Netlify로 다시 변경 (5분)
  2. Netlify 프로젝트는 삭제하지 않고 유지

지금부터는 마이그레이션 과정에서 겪은 문제들과 해결 방법을 정리해봤어요.

빌드 실패와 함께 위와 같은 Log가 발생했습니다.

Next.js의 segment config(revalidate, dynamic 등)는 빌드 시점에 정적으로 분석 가능해야 합니다. 조건부 표현식은 허용되지 않아요. (출처: Next.js Route Segment Config)

segment-config.ts
// ❌ 에러 발생 export const revalidate = process.env.NODE_ENV === 'development' ? 0 : 31536000; // ✅ 정적 값 사용 export const revalidate = 31536000; // 1년

위와 같이 조건부 표현식을 제거하고 정적 값으로 변경하여 해결했습니다.

text
CustomerError: Can't find required-server-files.json in build output directory CustomerError: The size of the build output exceeds the max allowed size

AWS Amplify는 공식적으로 Next.js 12-15만 지원합니다. Next.js 16은 아직 공식 지원 대상이 아닙니다.

Next.js 16은 Turbopack이 기본 번들러예요. (Next.js 16 Release) 하지만 Turbopack은 .next/node_modules/에 symlinks를 생성하는데, Amplify 번들러가 이를 처리하지 못합니다.

https://github.com/aws-amplify/amplify-hosting/issues/4074

또한 output: 'standalone' 설정은 Amplify의 표준 배포 방식과 맞지 않아 추가 문제를 일으켜요.

https://docs.aws.amazon.com/amplify/latest/userguide/deploy-nextjs-app.html

  1. Webpack 사용: package.json의 build 스크립트에 --webpack 플래그를 추가합니다.
package.json
{ "scripts": { "build": "next build --webpack" } }
  1. standalone 모드 제거: next.config.mjs에서 output: 'standalone' 설정을 제거해요.

  2. 표준 amplify.yml 사용: baseDirectory를 .next로 설정합니다.

amplify.yml
artifacts: baseDirectory: .next files: - '**/*'

Turbopack 대신 Webpack을 사용하면 symlinks 문제가 발생하지 않고, 표준 Next.js 출력 구조가 생성되어 Amplify가 정상적으로 처리할 수 있어요.

위 설정으로 Amplify 빌드에 성공했습니다.

Amplify 빌드 성공Netlify는 딸깍이었는데 AWS는 역시 만만치 않다

최종 설정 요약이에요.

항목설정
Next.js 버전16.1.1
번들러Webpack (--webpack 플래그)
amplify.yml표준 설정 (baseDirectory: .next)
output 모드기본 (standalone 아님)

Amplify Console에서 커스텀 도메인 blog.huns.site를 추가하고, DNS 레코드를 설정했어요.

text
Type: CNAME Name: blog Value: [Amplify CloudFront 도메인]

AWS Certificate Manager(ACM)를 통해 SSL 인증서가 자동으로 발급됩니다. (Amplify SSL/TLS certificates) HTTPS 접속이 정상 동작해요.

무료 호스팅 플랫폼들은 각자 다른 제약이 있고, 저는 제각각의 이유로 부딪혀 떠나게 되었습니다. Vercel은 Origin Transfer, Netlify는 빌드 크레딧의 부족이었죠.

결국 활발하게 개발을 이어가는 현재, 완전 무료를 유지하기는 어렵다는 결론에 이르렀습니다.

Vercel, Netlify는 Free Plan 이후 바로 $20 수준의 유료 플랜으로 시작하기 때문에, 사용한만큼 지불하는 AWS Amplify의 종량제 모델이 가장 합리적인 선택으로 보였습니다. 마이그레이션을 잘 마쳤습니다.

그런데 말입니다...

비용이 예상 밖입니다. 10일동안 $3 정도의 비용이 발생했어요.

Amplify 비용2달러 안 나온다면서요

아무래도 너어무 활발하게 개발을 했나 봅니다. Amplify도 빌드 시간에 따라 비용이 발생하는데, 빌드 시간이 상당해서 DX 저하, 비용 걱정이 됐습니다. 그래서 관련 트러블슈팅과 배포를 꽤나 자주 했거든요.

저는 다음 단계를 슬슬 마음 속에 품게 되었습니다. 바로 모든 페이지를 SSG로 전환하고, S3+CloudFront로 정적 배포하는 것입니다. 정적인 블로그를 더욱 블로그스럽게. 그리고 더 저렴하게. 그 과정을 다음 포스트에서 다뤄보겠습니다.