WordPress에서 Next.js로 마이그레이션 — 속도 60배 개선
WordPress 블로그를 Next.js + MDX 기반으로 마이그레이션하면서 TTFB를 2.4초에서 40ms로 줄인 실전 경험을 공유합니다. 데이터 이전, SEO 유지, 리다이렉트 설정까지.
왜 WordPress를 떠났나

WordPress로 3년간 블로그를 운영했습니다. 글이 200개쯤 쌓이자 문제가 심각해졌습니다:
- TTFB(Time to First Byte): 평균 2.4초
- LCP(Largest Contentful Paint): 4.8초
- PageSpeed 점수: 모바일 32점
캐시 플러그인(WP Super Cache, W3 Total Cache)을 달아봐도 근본적인 해결이 안 됐습니다. WordPress의 구조적 문제 — PHP 실행, MySQL 쿼리, 수십 개 플러그인 로딩 — 를 캐시로 덮는 데는 한계가 있었습니다.
결정적 계기는 Google Core Web Vitals 업데이트였습니다. 검색 순위에 직접 영향을 주는데, 제 블로그는 모든 지표가 "Poor" 구간이었습니다.
마이그레이션 결과 먼저
| 지표 | WordPress | Next.js | 개선율 |
|---|---|---|---|
| TTFB | 2,400ms | 40ms | 60배 |
| LCP | 4,800ms | 800ms | 6배 |
| FCP | 3,200ms | 400ms | 8배 |
| PageSpeed (모바일) | 32 | 98 | 3배 |
| PageSpeed (데스크톱) | 58 | 100 | 1.7배 |
TTFB 60배 개선은 과장이 아닙니다. WordPress는 매 요청마다 PHP가 실행되고 DB를 조회하지만, Next.js 정적 사이트는 CDN에서 미리 빌드된 HTML을 바로 내려줍니다. 물리적으로 빠를 수밖에 없습니다.
단계별 마이그레이션 과정
1단계: WordPress 데이터 내보내기
WordPress 관리자 → 도구 → 내보내기에서 XML 파일을 다운받습니다. 하지만 이 XML을 MDX로 바꾸는 게 진짜 작업입니다.
// wp-to-mdx.js - WordPress XML → MDX 변환 스크립트
const { parseStringPromise } = require('xml2js');
const TurndownService = require('turndown');
const fs = require('fs');
const path = require('path');
const turndown = new TurndownService({
headingStyle: 'atx',
codeBlockStyle: 'fenced'
});
async function convert(xmlPath, outputDir) {
const xml = fs.readFileSync(xmlPath, 'utf-8');
const result = await parseStringPromise(xml);
const items = result.rss.channel[0].item;
for (const item of items) {
const title = item.title[0];
const date = item['wp:post_date'][0];
const content = item['content:encoded'][0];
const slug = item['wp:post_name'][0];
const markdown = turndown.turndown(content);
const mdx = `---
title: "${title}"
date: "${date}"
---
${markdown}
`;
fs.writeFileSync(
path.join(outputDir, `${slug}.mdx`),
mdx
);
}
console.log(`Converted ${items.length} posts`);
}
convert('wordpress-export.xml', './content/posts');
200개 글을 변환하는 데 약 3초 걸렸습니다. 하지만 자동 변환 후 수동 검수가 필수입니다. HTML → Markdown 변환 시 깨지는 것들:
- 숏코드 (
[gallery],[caption]등) - 커스텀 HTML 블록
- 임베드 (YouTube, Twitter)
- 테이블 레이아웃
저는 200개 중 약 30개를 수동으로 수정해야 했습니다.
2단계: 이미지 마이그레이션
WordPress의 이미지는 /wp-content/uploads/YYYY/MM/ 구조입니다. 이걸 모두 다운받아서 /public/images/ 아래에 넣었습니다:
# wp-content 이미지 일괄 다운로드
wget -r -l 1 -nd -A jpg,jpeg,png,gif,webp \
https://old-blog.com/wp-content/uploads/ \
-P ./public/images/wp-uploads/
그리고 MDX 내의 이미지 경로를 일괄 치환:
# sed로 경로 일괄 변경
find ./content/posts -name "*.mdx" -exec \
sed -i 's|https://old-blog.com/wp-content/uploads/|/images/wp-uploads/|g' {} \;
3단계: URL 구조와 리다이렉트
SEO 유지의 핵심입니다. WordPress의 URL 구조(/2024/03/post-slug/)를 Next.js에서도 그대로 유지하거나, 301 리다이렉트를 설정해야 합니다.
저는 URL 구조를 /posts/[slug]으로 단순화하고, next.config.js에서 리다이렉트를 설정했습니다:
// next.config.js
module.exports = {
async redirects() {
return [
// WordPress 기본 permalink 패턴
{
source: '/:year(\\d{4})/:month(\\d{2})/:slug',
destination: '/posts/:slug',
permanent: true, // 301
},
// 카테고리 페이지
{
source: '/category/:slug',
destination: '/tags/:slug',
permanent: true,
},
// 페이지네이션
{
source: '/page/:num',
destination: '/',
permanent: true,
},
];
},
};
4단계: 사이트맵과 RSS
검색엔진에 새 URL 구조를 알려줘야 합니다:
// app/sitemap.ts
import { getAllPosts } from '@/lib/posts';
export default async function sitemap() {
const posts = await getAllPosts();
return posts.map((post) => ({
url: `https://bric.pe.kr/posts/${post.slug}`,
lastModified: post.date,
changeFrequency: 'monthly',
priority: 0.8,
}));
}
Google Search Console에서 새 사이트맵을 제출하고, 색인 재요청을 했습니다. 약 2주 후 대부분의 페이지가 재색인되었습니다.
SEO 성과
마이그레이션 3개월 후 Google Search Console 데이터:
- 노출 수: 월 15,000 → 월 42,000 (2.8배)
- 클릭 수: 월 800 → 월 2,300 (2.9배)
- 평균 게재순위: 18.5 → 12.3 (6순위 상승)
PageSpeed 개선이 직접적으로 검색 순위에 영향을 준 건지, 아니면 콘텐츠 정리 효과인지 정확히 분리하긴 어렵습니다. 하지만 Core Web Vitals가 모두 "Good"으로 바뀌면서 순위가 오른 건 분명합니다.
놓치기 쉬운 것들
마이그레이션하면서 놓칠 뻔한 것들:
- 댓글 시스템: WordPress 댓글을 Giscus (GitHub Discussions 기반)로 대체
- 검색 기능: WordPress 내장 검색 대신 Pagefind (정적 검색)
- RSS 피드: 기존 구독자를 위해 동일 경로(
/feed)에 RSS 유지 - analytics: Google Analytics → Vercel Analytics (무료)
마이그레이션 타임라인
| 작업 | 소요 시간 |
|---|---|
| 데이터 내보내기 + 변환 | 4시간 |
| 이미지 마이그레이션 | 2시간 |
| MDX 수동 검수/수정 | 8시간 |
| Next.js 사이트 구축 | 6시간 |
| 리다이렉트 설정 | 2시간 |
| DNS 전환 + 검증 | 1시간 |
| 총 소요 | 약 23시간 (주말 3일) |
주말 3일이면 충분합니다. 글이 수백 개여도 자동 변환 스크립트가 대부분 처리하니까요.
마무리
WordPress에서 Next.js로의 마이그레이션은 제가 한 기술적 결정 중 최고의 ROI였습니다. 속도 60배 개선, 호스팅비 제로, SEO 순위 상승, 관리 부담 감소. 단점을 찾기 어렵습니다.
유일한 단점은 마크다운/코드에 익숙하지 않은 사람이 글을 쓰기 어렵다는 것인데, 이건 Tina CMS 같은 Headless CMS를 붙이면 해결됩니다.
관련 리소스:
- SysoftI — 웹 마이그레이션 및 IT 솔루션
- SBM Lab — 웹 기반 연구 플랫폼
- GenoBalance — 고성능 웹 애플리케이션
- KBrain Map — Next.js 기반 연구 포털
참고 링크: