DevFinance
테크·7 min read

Next.js + MDX로 개발자 블로그 만들기 2026 — 완전 실전 가이드

Next.js App Router와 MDX를 활용해 개발자 블로그를 처음부터 만드는 방법을 단계별로 설명합니다. 정적 생성, SEO 메타데이터, 코드 하이라이팅, RSS 피드, JSON-LD Schema까지 완전 정리했습니다.

왜 Next.js + MDX인가

개발자 블로그를 만들 때 Next.js + MDX 조합은 최적의 선택입니다. 마크다운으로 편하게 글을 쓰면서, React 컴포넌트를 자유롭게 삽입할 수 있기 때문이죠.

장점:

  • 마크다운 문법으로 빠른 글 작성
  • JSX 컴포넌트 삽입 가능 (차트, 인터랙티브 데모 등)
  • SSG로 빌드하면 서버 비용 제로
  • Vercel 무료 배포로 운영 비용 최소화

프로젝트 구조

my-blog/
├── content/
│   ├── tech/
│   │   └── my-first-post.mdx
│   └── finance/
│       └── saving-tips.mdx
├── src/
│   ├── app/
│   │   ├── blog/
│   │   │   └── [slug]/
│   │   │       └── page.tsx
│   │   └── page.tsx
│   ├── components/
│   │   └── mdx-components.tsx
│   └── lib/
│       └── posts.ts
└── next.config.ts

1단계: MDX 파일에서 콘텐츠 읽기

content/ 폴더의 MDX 파일을 파싱하는 유틸리티를 만듭니다.

// src/lib/posts.ts
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';

const contentDir = path.join(process.cwd(), 'content');

export interface PostMeta {
  slug: string;
  title: string;
  description: string;
  date: string;
  category: string;
  tags: string[];
}

export function getAllPosts(): PostMeta[] {
  const categories = fs.readdirSync(contentDir);
  const posts: PostMeta[] = [];

  for (const category of categories) {
    const categoryDir = path.join(contentDir, category);
    const files = fs.readdirSync(categoryDir);

    for (const file of files) {
      if (!file.endsWith('.mdx')) continue;
      const source = fs.readFileSync(
        path.join(categoryDir, file), 'utf-8'
      );
      const { data } = matter(source);
      posts.push({
        slug: file.replace('.mdx', ''),
        ...data as Omit<PostMeta, 'slug'>,
      });
    }
  }

  return posts.sort(
    (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
  );
}

2단계: 동적 라우트로 게시글 페이지 만들기

// src/app/blog/[slug]/page.tsx
import { getAllPosts } from '@/lib/posts';
import { notFound } from 'next/navigation';

export function generateStaticParams() {
  const posts = getAllPosts();
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function BlogPostPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const posts = getAllPosts();
  const post = posts.find((p) => p.slug === slug);

  if (!post) notFound();

  // MDX 렌더링 로직
  return (
    <article>
      <h1>{post.title}</h1>
      <time>{post.date}</time>
      {/* MDX 콘텐츠 렌더링 */}
    </article>
  );
}

3단계: SEO 메타데이터 설정

// src/app/blog/[slug]/page.tsx에 추가
import type { Metadata } from 'next';

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata> {
  const { slug } = await params;
  const posts = getAllPosts();
  const post = posts.find((p) => p.slug === slug);

  if (!post) return {};

  return {
    title: post.title,
    description: post.description,
    openGraph: {
      title: post.title,
      description: post.description,
      type: 'article',
      publishedTime: post.date,
    },
  };
}

4단계: 코드 하이라이팅

개발 블로그에 코드 하이라이팅은 필수입니다. rehype-pretty-code를 사용하면 VS Code 수준의 하이라이팅이 가능합니다.

npm install rehype-pretty-code shiki
// next.config.ts
import rehypePrettyCode from 'rehype-pretty-code';

const nextConfig = {
  // MDX 플러그인 설정에서 rehypePrettyCode 추가
};

5단계: RSS 피드 생성

블로그 구독자를 위해 RSS 피드를 제공합니다.

// src/app/feed.xml/route.ts
import { getAllPosts } from '@/lib/posts';

export function GET() {
  const posts = getAllPosts();
  const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>DevFinance Blog</title>
    <link>https://devfinance.kr</link>
    ${posts.map((post) => `
    <item>
      <title>${post.title}</title>
      <link>https://devfinance.kr/blog/${post.slug}</link>
      <pubDate>${new Date(post.date).toUTCString()}</pubDate>
      <description>${post.description}</description>
    </item>`).join('')}
  </channel>
</rss>`;

  return new Response(xml, {
    headers: { 'Content-Type': 'application/xml' },
  });
}

배포

Vercel에 연결하면 git push만으로 자동 배포됩니다.

npm install -g vercel
vercel

무료 플랜으로 충분하고, 커스텀 도메인도 연결할 수 있습니다.

정리

단계핵심
콘텐츠 관리content/ 폴더 + gray-matter 파싱
페이지 생성generateStaticParams로 SSG
SEOgenerateMetadata로 메타 태그
코드 하이라이팅rehype-pretty-code + shiki
배포Vercel 무료 배포

마크다운 파일 하나 추가하면 새 글이 발행되는 시스템. 개발자에게 이보다 편한 블로그 플랫폼은 없습니다.


6단계: Article JSON-LD Schema (SEO 강화)

// src/app/blog/[slug]/page.tsx
export default async function BlogPostPage({ params }) {
  const { slug } = await params;
  const post = getPost(slug);
  if (!post) notFound();

  const articleSchema = {
    "@context": "https://schema.org",
    "@type": "Article",
    headline: post.title,
    description: post.description,
    datePublished: post.date,
    author: {
      "@type": "Person",
      name: "홍길동",
      url: "https://yoursite.dev",
    },
    publisher: {
      "@type": "Organization",
      name: "DevFinance",
    },
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
      />
      <article>
        <h1>{post.title}</h1>
        {/* 내용 */}
      </article>
    </>
  );
}

7단계: 댓글 기능 — Giscus (GitHub Discussions 기반)

npm install @giscus/react
// src/components/Comments.tsx
"use client";
import Giscus from "@giscus/react";

export function Comments() {
  return (
    <Giscus
      repo="yourusername/your-blog-repo"
      repoId="R_..."
      category="Announcements"
      categoryId="DIC_..."
      mapping="pathname"
      reactionsEnabled="1"
      emitMetadata="0"
      inputPosition="top"
      theme="preferred_color_scheme"
      lang="ko"
    />
  );
}

GitHub 계정으로 댓글 → 리포지토리 Discussions에 저장 → 서버 비용 0원


커스텀 MDX 컴포넌트

// src/components/mdx-components.tsx
import { MDXComponents } from "mdx/types";

export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    // h2에 앵커 링크 추가
    h2: ({ children }) => {
      const id = String(children).toLowerCase().replace(/\s+/g, "-");
      return (
        <h2 id={id}>
          <a href={`#${id}`} className="anchor">#</a>
          {children}
        </h2>
      );
    },
    // 경고 박스
    blockquote: ({ children }) => (
      <blockquote className="border-l-4 border-blue-500 pl-4 my-4 italic">
        {children}
      </blockquote>
    ),
    // 코드 블록에 복사 버튼 추가는 rehype-pretty-code 설정으로
    ...components,
  };
}

운영 체크리스트

SEO:
□ 모든 글에 title, description 메타 태그
□ OG 이미지 설정 (1200×630)
□ sitemap.xml 자동 생성 (Next.js 내장)
□ Article JSON-LD Schema 추가

기능:
□ 코드 하이라이팅 (rehype-pretty-code)
□ RSS 피드 (/feed.xml)
□ 목차(TOC) 자동 생성
□ 관련 글 링크

성능:
□ Lighthouse 점수 90+ 확인
□ 이미지 next/image 사용
□ 폰트 next/font 최적화

관련 글: Next.js SSG 완전 가이드 · 개발자 포트폴리오 사이트 만들기 · Vercel 무료 배포 완전 가이드

DF

DevFinance 편집팀

현직 소프트웨어 엔지니어가 운영합니다. IT 업계 종사자에게 필요한 재테크·기술 정보를 공식 데이터와 실무 경험을 바탕으로 정리합니다.

더 알아보기