앞선 포스트에서 Netlify에서 AWS Amplify로 블로그 호스팅을 이전한 이야기를 소개했습니다.
https://blog.huns.site/posts/dev/blog/v2/nextjs-hosting-migration-from-netlify-to-amplify빌드 크레딧 한도 문제에서 벗어나 종량제 과금의 자유를 얻었는데, 이번엔 다른 문제가 생겼습니다. 이전 포스트의 말미에 적었듯이, 기능 개발을 할 때마다 빌드가 돌아가면서 비용이 꽤 나온 겁니다.
Amplify는 GitHub 브랜치에 push할 때마다 자동으로 빌드를 트리거합니다. 개발 중 잦은 커밋이 쌓이면 빌드 비용도 덩달아 올라가죠. 엄청나게 많은 비용은 아니지만, 월 $10 정도 지출이 예상되었습니다. 이미 디지털 월세를 많이 내고 있어요. 그리고 앞으로 더더욱 활발한 개발을 이어나갈 계획이죠. 아, 개선이 필요했습니다.
그러다 문득, S3 + CloudFront 같은 더 저렴한 배포 방식을 시도해보기로 했습니다.
Amplify의 과금은 크게 세 가지로 나뉩니다. (출처: Amplify Pricing)
| 항목 | 단가 | 무료 티어 (12개월) |
|---|---|---|
| 빌드 | $0.01/분 | 1,000분/월 |
| 전송 | $0.15/GB | 15GB/월 |
| 저장 | $0.023/GB | 5GB/월 |
문제는 빌드 비용이에요. push 한 번에 빌드가 트리거되고, Next.js + MDX 컴파일을 포함하면 빌드 한 번에 5분 이상 걸립니다.
하루 3번 push × 30일 = 90회 빌드 90회 × 5분 = 450분 450분 × $0.01 = $4.50/월 (빌드만)
여기에 전송 비용까지 더하면 개인 블로그 치고 부담스러운 금액입니다. 게다가 Amplify의 전송 비용($0.15/GB)은 CloudFront 직접 사용 시($0.085/GB)보다 76% 더 비싸요. (출처: CloudFront Pricing)
비용 절감 방법을 찾기 전에, 현재 어떤 기능을 쓰고 있는지 정리해봤습니다.
huns-log (Next.js 16 + MDX + pnpm) ├── 약 430개 포스트 ├── SSG: ssg: true 마킹된 인기 포스트 + 카테고리만 ├── ISR: 나머지 포스트 (revalidate: 1년) ├── API Routes │ ├── /api/open-graph (링크 프리뷰 fetch) │ └── /api/hmr-timestamp (개발 전용) ├── /feed.xml (RSS 피드 생성) ├── Client Components (테마, nuqs 등) └── 이미지: S3 + CloudFront CDN (별도 운영)
핵심 질문은 이거예요. 이 기능들을 유지하면서 비용을 줄일 수 있는가?
크게 세 가지 방향을 검토했습니다.
Next.js의 output: 'export' 옵션으로 완전 정적 사이트를 생성하고, S3에 올려 CloudFront로 서빙하는 방식입니다.
예상 비용 (월 50K PV 기준)
| 항목 | 비용 |
|---|---|
| CloudFront 전송 (2GB) | ~$0.17 |
| S3 저장 (10GB) | ~$0.23 |
| Route 53 | ~$0.50 |
| 합계 | ~$0.90/월 |
빌드는 GitHub Actions 무료 티어로 처리하면 $0입니다.
대신 포기해야 하는 것들이 있어요.
- API Routes 사용 불가
- ISR 사용 불가 (모든 페이지를 빌드 타임에 생성해야 함)
- Image Optimization 사용 불가
- Middleware 사용 불가
SST는 OpenNext를 통해 Next.js를 AWS Lambda + S3 + CloudFront로 분해 배포합니다. 모든 Next.js 기능을 유지하면서 서버리스로 운영할 수 있어요. (https://opennext.js.org/aws/inner_workings/architecture)
CloudFront (CDN) ├── 정적 자산 → S3 ├── 페이지 (SSR/ISR) → Lambda ├── API Routes → Lambda └── Image Optimization → Lambda
예상 비용
Lambda 호출과 S3 저장 비용을 합쳐 월 $3~5 수준입니다. 트래픽이 적은 개인 블로그라면 Lambda 무료 티어(100만 요청/월)로 대부분 커버돼요.
장점은 Next.js 기능을 하나도 포기하지 않아도 된다는 것이고, 단점은 설정 복잡도가 올라간다는 거예요.
https://developers.cloudflare.com/workers/framework-guides/web-apps/nextjs/Cloudflare의 가장 큰 장점은 무제한 대역폭입니다. 무료 플랜에서 월 500회 빌드, 무제한 전송을 제공하죠. (출처: Cloudflare Limits)
| 항목 | Free 플랜 |
|---|---|
| 빌드 | 500회/월 |
| 대역폭 | 무제한 |
| Workers 요청 | 10만/일 |
@opennextjs/cloudflare 어댑터를 통해 Next.js를 Cloudflare Workers에 배포할 수 있습니다. (출처: OpenNext Cloudflare)
단점은 Workers 런타임이 Node.js와 다르다는 점이에요. link-preview-js 같은 Node.js 네이티브 라이브러리가 동작하지 않을 수 있습니다. 이전에 Cloudflare Pages를 검토했을 때도 Edge Runtime 제약이 문제였어요.
여기서 중요한 건 현재 블로그에서 실제로 필요한 기능이 뭔지입니다.
/api/open-graph: OG 데이터를 런타임에 fetch하는 API인데, 사실compile-mdx.mjs스크립트에서 이미 빌드 타임에 모든 OG 데이터를 프리페치하고 있습니다. 이 API는 빌드 타임에 캐시되지 않은 새 URL이 추가될 때만 의미가 있어요./api/hmr-timestamp: 개발 전용이에요. 프로덕션에서는 0을 반환합니다. 없어도 됩니다.
/feed.xml은 Route Handler로 구현되어 있지만, 포스트 목록은 빌드 타임에 이미 결정돼요. 빌드 스크립트로 전환하면 정적 파일로 생성 가능합니다.
현재 ssg: true인 포스트만 빌드 타임에 생성하고, 나머지는 ISR(1년 캐시)로 처리하고 있습니다. 이유는 전체 SSG 시 메모리를 너무 많이 써서였어요. 하지만 빌드 환경(GitHub Actions)에서 메모리를 충분히 확보하거나 배치 처리를 적용하면 전체 SSG도 가능할 수 있습니다. 이전의 OOM 문제로부터 자유로워질 수 있는, 오히려 좋은 상황입니다.
정리하면, 현재 블로그는 사실상 SSG-only로 전환 가능한 구조입니다.
API Routes와 ISR은 "없으면 안 되는" 기능이 아니라 "있으면 좋은" 기능이었어요. 빌드 타임 OG 프리페치가 이미 동작하고 있어서, 런타임 API가 꼭 필요하지 않습니다.
S3 + CloudFront를 선택하려면, 전체 430개 포스트와 카테고리 페이지를 빌드 타임에 생성해야 합니다. 이전에 Vercel과 Netlify에서 전체 SSG를 시도했을 때, OOM 문제로 빌드가 실패했던 경험이 있어서, 이게 진짜 가능한지 먼저 검증이 필요했어요.
OOM 문제로 이전 플랫폼에서 전체 SSG를 실패했던 경험이 많습니다. 애도 많이 먹었고요. 그래서 간단히 짚고 넘어가겠습니다.
Vercel과 Netlify의 빌드 환경은 메모리 제한이 있습니다.
- https://vercel.com/docs/functions/limitations
- https://vercel.com/kb/guide/troubleshooting-sigkill-out-of-memory-errors
- https://docs.github.com/en/actions/reference/runners/github-hosted-runners
Vercel에서 Next.js App Router 프로젝트가 OOM으로 실패하는 건 흔하게 보고되는 문제예요. 8 GB 한도 안에서 수백 개 페이지를 SSG하려면 빌드 프로세스 자체를 최적화해야 합니다.
- https://www.zhyd1997.dev/blog/resolve-nextjs-build-oom-on-vercel
- https://github.com/vercel/next.js/issues/76704
GitHub Actions의 표준 러너(ubuntu-latest)는 공개 저장소 기준 16 GB RAM입니다. 2023년 말 업그레이드로 기존 7 GB에서 대폭 늘어났어요. 비공개 저장소에서는 8 GB RAM이 제공됩니다. https://docs.github.com/en/actions/reference/runners/github-hosted-runners Vercel Hobby(8 GB)보다 오히려 넉넉하죠.
하지만 진짜 결정적인 차이는 메모리 총량이 아니에요.
Vercel/Netlify의 빌드 컨테이너는 빌드 외에도 플랫폼 자체 프로세스가 메모리를 점유합니다. 반면 GitHub Actions 러너는 빌드 작업에 거의 전체 메모리를 사용할 수 있어요. 그리고 NODE_OPTIONS으로 Node.js 힙 크기를 직접 조절할 수 있습니다.
env: NODE_OPTIONS: '--max-old-space-size=6144'
Next.js 15부터 빌드 메모리를 줄이는 공식 옵션들이 추가됐습니다. https://nextjs.org/docs/app/guides/memory-usage
const nextConfig = { experimental: { webpackMemoryOptimizations: true, // v15.0.0+ }, // 소스맵 비활성화로 메모리 절약 productionBrowserSourceMaps: false, };
webpackMemoryOptimizations는 Webpack의 메모리 사용 패턴을 변경해 피크 메모리를 줄여요. 빌드 시간이 약간 늘어날 수 있지만, OOM을 피하는 데 효과적입니다.
일반적인 Next.js 프로젝트와 달리, 이 블로그는 MDX 컴파일을 prebuild 단계에서 미리 처리합니다.
prebuild: compile-mdx.mjs → .mdx-cache/에 컴파일 결과 저장 build: next build → 캐시된 결과만 읽어서 페이지 생성
Next.js 빌드 시점에는 이미 컴파일된 MDX를 읽기만 하면 돼요. 430개 포스트를 처음부터 컴파일하는 것과 캐시를 읽는 것은 메모리 사용량이 크게 다릅니다.
SSG-only, 가능한가?
결론은 가능하다입니다. Vercel/Netlify에서 실패했던 건 플랫폼 빌드 컨테이너의 메모리 제한 때문이었고, GitHub Actions에서는 NODE_OPTIONS 조절 + Next.js 메모리 최적화 옵션 + prebuild MDX 캐시를 조합하면 430개 포스트 전체 SSG가 충분히 가능했습니다. (실제로 돌려본 결과)
검증 결과를 바탕으로 S3 + CloudFront 정적 배포를 선택했습니다. 마이그레이션에 필요한 작업을 정리하면 이렇습니다.
next.config.mjs에output: 'export'설정- API Routes 제거 및 대체
- RSS 피드를 빌드 스크립트로 전환
generateStaticParams에서 전체 포스트 SSG로 전환- GitHub Actions 배포 워크플로우 작성
- 빌드 테스트
next.config.mjs에 핵심 설정을 추가합니다.
const isProductionBuild = process.env.NODE_ENV === 'production'; const nextConfig = { ...(isProductionBuild && { output: 'export', trailingSlash: true }), images: { unoptimized: true, }, experimental: { webpackMemoryOptimizations: true, }, };
output: 'export'를 무조건 적용하면 next dev에서도 정적 내보내기 모드가 활성화되어,
generateStaticParams()에 없는 경로 접근 시 에러가 발생합니다.
NODE_ENV로 분기하여 프로덕션 빌드에서만 적용해야 해요.
2개의 API Routes는 모두 build 이후 사용하지 않는 API였습니다. 가벼운 마음으로 제거했습니다.
Route Handler 대신 빌드 스크립트에서 public/feed.xml을 직접 생성합니다.
import RSS from 'rss'; import fs from 'fs'; // posts-index.json에서 포스트 목록 로드 const postsIndex = JSON.parse( fs.readFileSync('.mdx-cache/posts-index.json', 'utf-8') ); const feed = new RSS({ title: 'Blog Title', site_url: 'https://blog.huns.site', feed_url: 'https://blog.huns.site/feed.xml', }); postsIndex .filter((post) => post.published !== false) .forEach((post) => { feed.item({ title: post.title, url: `https://blog.huns.site/posts${post.slug}`, date: new Date(post.modifiedAt || post.createdAt), }); }); fs.writeFileSync('public/feed.xml', feed.xml({ indent: true }));
prebuild 스크립트에 추가하여 빌드 전에 자동으로 RSS 피드를 생성하게 했습니다.
모든 포스트를 빌드 타임에 생성했습니다. (SSG-only) 이전에는 OOM 문제로 특정 포스트만 SSG로 생성했었는데 말이죠.
// src/app/blog/posts/[...slug]/page.tsx export const generateStaticParams = () => { const allPostParams = allPosts .filter((post) => post.ssg === true) .filter((post) => post.published !== false) .map((post) => ({ slug: post.slug.slice(1).split('/'), })); const categoryParams = getAllCategoryRoute(ROOT_CATEGORY).map((route) => ({ slug: route.split('/'), })); return [...allPostParams, ...categoryParams]; };
dynamicParams와 revalidate 설정도 정적 내보내기에서 사용되지 않으므로 제거했습니다.
export const dynamicParams = true; export const revalidate = 31536000;
# .github/workflows/deploy.yml name: Deploy to S3 + CloudFront on: push: branches: [master] workflow_dispatch: # 수동 트리거 (Actions 탭에서 브랜치 선택 후 실행) jobs: deploy: runs-on: ubuntu-latest env: NODE_OPTIONS: '--max-old-space-size=6144' steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 9.10.0 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - run: pnpm install --frozen-lockfile - run: pnpm build - uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-2 # 정적 자산은 긴 캐시, HTML은 짧은 캐시 - name: Sync static assets to S3 run: | aws s3 sync out/ s3://${{ secrets.S3_BUCKET }}/app/ \ --delete \ --cache-control "public,max-age=31536000,immutable" \ --exclude "*.html" --exclude "*.xml" - name: Sync HTML and XML to S3 run: | aws s3 sync out/ s3://${{ secrets.S3_BUCKET }}/app/ \ --exclude "*" --include "*.html" --include "*.xml" \ --cache-control "public,max-age=0,must-revalidate" - name: Invalidate CloudFront cache run: | aws cloudfront create-invalidation \ --distribution-id ${{ secrets.CF_DISTRIBUTION_ID }} \ --paths "/*"
빌드 비용은 $0입니다. GitHub Actions 무료 티어에서 월 2,000분을 사용할 수 있어요.
https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions빌드를 돌려보니, manifest.ts, robots.ts, sitemap.ts 같은 Metadata Route에서 에러가 발생했습니다.
Error: export const dynamic = "force-static"/export const revalidate not configured on route "/manifest.webmanifest" with "output: export"
output: 'export'에서는 Metadata Route도 명시적으로 정적임을 선언해야 해요.
// src/app/manifest.ts, robots.ts, sitemap.ts export const dynamic = 'force-static';
세 파일 모두에 export const dynamic = 'force-static'을 추가하면 됩니다.
모든 수정 사항을 적용하고 빌드를 실행했습니다.
NODE_OPTIONS='--max-old-space-size=6144' NEXT_PUBLIC_ENV=production pnpm build
▲ Next.js 16.1.1 (webpack) - Experiments (use with caution): ✓ webpackMemoryOptimizations ✓ Compiled successfully in 10.1s ✓ Generating static pages using 7 workers (481/481) in 28.4s
481개 정적 페이지가 전부 생성됐습니다. OOM 없이 성공이에요.
out/ 디렉토리에 feed.xml, sitemap.xml, robots.txt, manifest.webmanifest 모두 정상 포함됐습니다.
이전에 계속 실패했던 전체 SSG가 문제없이 성공했습니다. 전 행복한 개발자예요.
코드 변경은 완료됐고, 실제 배포를 위해 AWS 인프라 셋업이 필요합니다. AWS 콘솔에서 직접 진행하는 작업들이에요.
GitHub Actions에서 S3 업로드와 CloudFront 캐시 무효화를 수행할 IAM 사용자가 필요합니다.
- 프로그래밍 방식 액세스 키를 발급합니다. GitHub Actions에서 사용합니다.
- 필요한 권한은 S3 버킷 읽기/쓰기 + CloudFront 무효화 정도입니다.
- 최소 권한 원칙에 따라 JSON으로 인라인 정책을 직접 작성했습니다.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:DeleteObject", "s3:ListBucket", "s3:GetObject" ], "Resource": [ "arn:aws:s3:::BUCKET_NAME", "arn:aws:s3:::BUCKET_NAME/app/*" ] }, { "Effect": "Allow", "Action": "cloudfront:CreateInvalidation", "Resource": "arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID" } ] }
이미 이미지 CDN용으로 사용 중인 S3 버킷(huns-log)이 있습니다. 새 버킷을 만들지 않고, 기존 버킷에 app/ prefix를 추가해서 블로그 앱을 배포했습니다. 블로그를 위한 bucket은 하나면 돼요.
s3://huns-log/ ├── imgs/ ← 기존 이미지 CDN (blog-cdn.huns.site) └── app/ ← 블로그 앱 (blog.huns.site) ├── index.html ├── blog/ ├── feed.xml └── ...
- 버킷의 퍼블릭 액세스가 이미 차단되어 있어서 별도 설정은 필요 없었습니다.
- GitHub Actions에서
aws s3 sync out/ s3://huns-log/app/으로 세부 경로 prefix를 지정해서 배포할 수 있습니다.
CloudFront에 HTTPS를 적용하려면 ACM 인증서가 필요합니다.
반드시 us-east-1 (버지니아 북부) 리전에서 발급해야 합니다.
CloudFront는 글로벌 서비스이므로 us-east-1의 인증서만 연결할 수 있어요.
- 도메인:
blog.huns.site - 검증 방식: DNS 검증 (Route 53 사용 시 자동 CNAME 생성 가능)
Origin Path를 /app으로 설정하면 CloudFront의 /index.html 요청이 S3의 app/index.html로 매핑됩니다. 기존 이미지 CDN과 같은 버킷을 사용하면서도 경로가 충돌하지 않아요.
OAC를 생성하면 CloudFront가 S3 버킷 정책 업데이트를 안내합니다. 안내에 따라 S3 버킷 정책에 CloudFront 서비스 주체를 허용하면 돼요. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
blog.huns.site→ CloudFront Distribution의 도메인으로 **A 레코드(Alias)**를 생성합니다.- 기존 Amplify를 가리키던 레코드가 있다면 수정합니다.
GitHub 리포지토리 Settings → Secrets and variables → Actions에서 아래 시크릿을 추가합니다.
모든 설정이 완료되고 S3 + CloudFront 배포가 정상 동작하는 것을 확인한 후, Amplify 앱과의 연결을 종료했습니다. 로그를 남기기 위해 완전 삭제는 하지 않았죠.
이렇게 마이그레이션이 완료되었습니다.
배포 후 메인 페이지는 잘 나오는데, 포스트 상세 페이지에서 새로고침하면 S3에서 AccessDenied XML 에러가 발생했습니다.
<Error> <Code>AccessDenied</Code> <Message>Access Denied</Message> </Error>
trailingSlash: true 설정으로 Next.js가 모든 페이지를 경로/index.html 형태로 생성합니다. 예를 들어 /blog/posts/frontend/react/react-notion-x-introduction/ 경로는 S3에 app/blog/posts/frontend/react/react-notion-x-introduction/index.html로 저장돼요.
문제는 CloudFront의 Default root object(index.html)가 최상위 /에만 적용된다는 겁니다. (출처: Specify a default root object) 하위 디렉토리의 /index.html은 자동으로 찾아주지 않아요. 그래서 /blog/posts/.../ 경로로 직접 접근하면 S3에서 해당 "디렉토리"를 찾으려다가 권한 에러가 발생합니다.
클라이언트 사이드 라우팅(Next.js Link 컴포넌트)으로 이동할 때는 브라우저가 이미 로드된 JS 번들로 페이지를 렌더링하므로 문제가 없어요. 새로고침이나 URL 직접 접근 시에만 발생하는 이유입니다.
CloudFront Functions를 사용해 모든 요청의 URI를 리라이트하면 됩니다.
function handler(event) { var request = event.request; var uri = request.uri; // /path/ → /path/index.html if (uri.endsWith('/')) { request.uri += 'index.html'; } // /path (확장자 없음) → /path/index.html else if (!uri.includes('.')) { request.uri += '/index.html'; } return request; }
CloudFront 콘솔 → Functions → Create function → 코드 입력 → Publish → Distribution의 Viewer Request에 연결합니다.
이 함수가 하는 일은 간단해요.
/blog/posts/some-slug/→/blog/posts/some-slug/index.html/blog/posts/some-slug→/blog/posts/some-slug/index.html/styles/main.css→ 그대로 (확장자가 있으므로 변환하지 않음)
CloudFront Functions는 Viewer Request 이벤트에서 실행되므로 S3에 요청이 도달하기 전에 URI가 변환됩니다. 실행 비용은 100만 요청당 $0.10이고, 매월 200만 호출까지 무료입니다. (출처: CloudFront Pricing)
S3 + CloudFront로 정적 사이트를 배포할 때 trailingSlash: true를 사용한다면,
CloudFront Functions URI 리라이트는 선택이 아니라 필수입니다.
이 설정 없이는 메인 페이지 외의 모든 직접 접근이 실패해요.
나중에 API를 사용하고 싶으면 어떡하지?
S3 + CloudFront로 전환하면 API Routes를 사용할 수 없습니다. 완전 정적 배포 방식을 선택할 때 계속 마음에 걸렸던 단면입니다. 나중에 조회수 카운터 같은 동적 기능을 만들 수도 있잖아요.
그럴 땐 별도의 백엔드 서버 없이 Lambda Function URL + DynamoDB 서버리스 조합으로 해결할 수 있습니다.
Lambda Function URL은 API Gateway 없이 Lambda에 직접 HTTPS 엔드포인트를 부여하는 기능입니다. (출처: Lambda Function URL) Lambda 하나로 API를 만들 수 있어서 설정이 가장 간소해요. Function URL 자체에 추가 비용은 없고, 표준 Lambda 요금만 적용됩니다.
대안으로 API Gateway HTTP API + Lambda 구성도 있지만, 비용 차이가 미미하고 설정은 더 복잡합니다.
개인 블로그의 단순 API 정도라면 API Gateway의 인증/스로틀링이 과하다고 생각됩니다. Lambda Function URL이 설정이 간소하고 추가 비용도 없습니다.
정적 사이트에서 Lambda Function URL을 호출하는 구조는 SSG와 완전히 호환됩니다. 정적 HTML은 S3/CloudFront에서 서빙하고, 동적 데이터는 클라이언트 사이드에서 Lambda를 호출하면 돼요.
빌드 타임에 생성된 정적 페이지에 클라이언트 컴포넌트를 추가하고, useEffect에서 Lambda Function URL을 호출하는 방식이에요. output: 'export'와 충돌하는 부분이 전혀 없습니다.
조회수 카운팅 기능을 예로 들어서 비용을 계산해보는 시나리오를 AI에게 부탁했습니다.
포스트 진입 시 DynamoDB UpdateItem의 ADD 연산으로 원자적 +1과 새 값 반환을 1회 write로 처리할 수 있습니다. 별도의 read 요청이 필요 없어요.
건당 비용으로 산정하면 다음과 같습니다.
호스팅 비용(~$1/월)의 5%에 불과해요. 월 PV가 50만으로 10배 늘어도 ~$0.50 수준입니다.
SSG로 전환해도 동적 기능을 포기하는 것이 아니더라고요.
필요할 때 Lambda + DynamoDB를 붙이면 되고, 비용은 호스팅비의 5% 수준이에요.
공부가 많이 됐던 유목 생활이었습니다. 플랫폼마다의 문제와 비용을 정리했습니다.
Vercel → Netlify → Amplify → S3/CF를 거치며 짧은 기간 동안 호스팅 플랫폼을 세 번 바꿨습니다. 이런 결론을 얻었습니다.
- 무료로는 활발한 활동에 한계가 있다.
- 빌드 환경의 메모리 제한은 플랫폼마다 다르다. 같은 프로젝트도 어디서 빌드하느냐에 따라 성공/실패가 갈린다.
- 정적 사이트가 가장 저렴하다. "서버가 정말 필요한가?"를 먼저 질문해야 한다.
그리고 최종적으로 느낀 점은 인프라를 많이 알수록 시간과 비용을 절약할 수 있다는 거예요. 앞으로 개선하고 싶은 문제들이 많습니다. 더 적극적으로 부딪히고 해결하며 나아가볼 생각이에요.
포스팅할 소재가 끊이질 않네요. 도움되셨길 바랍니다. 감사합니다.
