Next.js 15 블로그를 Cloudflare Pages에 배포하기
Next.js 15 App Router 기반 블로그를 MDX, Shadcn UI, Cloudflare Pages를 활용해 직접 구축하고 배포한 경험을 정리합니다.
왜 직접 만들었나?
블로그 플랫폼을 선택할 때 Velog, Notion, Tistory 등 여러 선택지가 있었지만, 결국 직접 만들기를 선택했습니다.
이유는 단순합니다:
- 원하는 기능을 마음대로 추가할 수 있다
- 배포 비용이 저렴하다 (Cloudflare 무료 티어)
- 직접 만들면서 배우는 것들이 있다
기술 스택
이 블로그는 다음 기술로 만들어졌습니다:
| 분류 | 기술 |
|---|---|
| 프레임워크 | Next.js 15 (App Router) |
| 언어 | TypeScript |
| 스타일링 | Tailwind CSS v4 |
| UI | Shadcn UI |
| 콘텐츠 | MDX |
| 배포 | Cloudflare Pages |
| 스토리지 | Cloudflare R2 |
MDX 설정하기
MDX는 Markdown에 JSX를 포함할 수 있어 기술 블로그에 적합합니다.
pnpm add next-mdx-remote gray-matter rehype-pretty-code rehype-slug remark-gfmfrontmatter를 파싱하는 유틸리티 함수를 작성합니다:
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
export function getPostBySlug(slug: string) {
const fullPath = path.join(process.cwd(), 'content/posts', `${slug}.mdx`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data, content } = matter(fileContents);
return { frontmatter: data, content };
}Cloudflare Pages 배포 시 주의사항
Cloudflare Pages는 Edge Runtime 환경입니다. 따라서:
fs모듈은 빌드 타임에만 사용해야 합니다. 런타임에서는 파일 시스템에 접근할 수 없습니다.
모든 MDX 파일을 빌드 시 정적으로 생성하려면 generateStaticParams를 사용합니다:
export async function generateStaticParams() {
const posts = getAllPosts(); // fs 모듈 사용 → 빌드 타임에만 실행
return posts.map((post) => ({ slug: post.slug }));
}마치며
직접 블로그를 구축하는 과정이 생각보다 재미있었습니다. 앞으로 더 많은 기능을 추가하면서 블로그도, 실력도 함께 성장시켜 나가겠습니다. 🚀