Next.js

🚀 Next.js로 블로그 만들기 (SSG + 동적 라우팅 + API Routes)

수아파파's 2025. 2. 25. 19:53
반응형

1️⃣ 프로젝트 개요 및 필요 기능 설명
2️⃣ Next.js 설치 및 기본 설정
3️⃣ 정적 사이트 생성 (SSG) & 동적 라우팅 구현
4️⃣ API Routes 활용하여 백엔드 연동
5️⃣ 스타일링 및 SEO 최적화


1️⃣ 프로젝트 개요 및 필요 기능 설명

🎯 목표: Next.js를 활용하여 **정적 사이트 생성(SSG)**과 동적 라우팅을 적용한 블로그 웹사이트 만들기

  • SSG → 빌드 시 정적 HTML 파일 생성으로 빠른 로딩 속도 & SEO 최적화
  • 동적 라우팅 → 블로그 글 개수와 내용에 따라 동적으로 URL 생성
  • API Routes백엔드 서버 없이 Next.js 내부에서 데이터를 관리

📌 주요 기능

블로그 목록 페이지 → 정적 사이트 생성(SSG)
블로그 글 상세 페이지 → 동적 라우팅 적용
글 작성 & 수정 (API Routes 활용)
SEO 최적화 (메타태그 설정)

🔥 Next.js의 SSG, 동적 라우팅, API Routes를 모두 활용한 실전 프로젝트!


2️⃣ Next.js 설치 및 기본 설정

🔹 설치 및 프로젝트 생성

📌 터미널에서 실행

npx create-next-app@latest nextjs-blog
cd nextjs-blog
npm run dev
  • npx create-next-app@latest: 최신 Next.js 버전으로 프로젝트 생성
  • npm run dev: 개발 서버 실행 (http://localhost:3000)

🔹 디렉토리 구조 설명

nextjs-blog/
├── pages/            # 파일 기반 라우팅 디렉토리
│   ├── index.js      # 홈 (블로그 목록 페이지)
│   └── posts/
│       ├── [id].js   # 동적 라우팅 (개별 블로그 글)
│       └── create.js # 글 작성 페이지
├── public/           # 정적 파일 (이미지, 폰트 등)
├── styles/           # CSS 및 스타일 파일
└── data/              # 블로그 글 데이터 저장 (JSON 파일)

🔹 데이터 관리

  • 정적 데이터 관리: data 디렉토리에 JSON 파일로 저장
  • 동적 데이터 관리: API Routes를 활용하여 JSON 데이터를 추가/수정/삭제

3️⃣ 정적 사이트 생성 (SSG) & 동적 라우팅 구현

🔹 1. 블로그 목록 페이지 (pages/index.js)

  • **getStaticProps**를 사용하여 SSG 적용
  • data/posts.json에서 블로그 글 목록을 불러옴

📌 예제 코드 (pages/index.js)

import Link from "next/link";
import fs from "fs";
import path from "path";

export async function getStaticProps() {
  const filePath = path.join(process.cwd(), "data", "posts.json");
  const jsonData = fs.readFileSync(filePath, "utf-8");
  const posts = JSON.parse(jsonData);

  return { props: { posts } };
}

export default function Home({ posts }) {
  return (
    <div>
      <h1>블로그 목록</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <Link href={`/posts/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
      <Link href="/posts/create">
        <button>글 작성하기</button>
      </Link>
    </div>
  );
}

 

📌 예제 데이터 (data/posts.json)

[
  {
    "id": "1",
    "title": "Next.js SSG 소개",
    "content": "Next.js의 정적 사이트 생성에 대해 알아봅니다."
  },
  {
    "id": "2",
    "title": "Next.js 동적 라우팅",
    "content": "동적 라우팅을 사용하여 페이지를 동적으로 생성합니다."
  }
]

✅ **getStaticProps**로 빌드 시 정적 HTML 생성 → 빠른 로딩 & SEO 최적화

  • JSON 데이터에서 블로그 목록을 불러와서 정적으로 렌더링

🔹 2. 동적 라우팅 (개별 글 페이지)

  • **getStaticPaths**와 **getStaticProps**를 함께 사용하여 동적 라우팅 + SSG 구현
  • **URL 파라미터 (id)**에 따라 동적으로 페이지 생성
import fs from "fs";
import path from "path";

export async function getStaticPaths() {
  const filePath = path.join(process.cwd(), "data", "posts.json");
  const jsonData = fs.readFileSync(filePath, "utf-8");
  const posts = JSON.parse(jsonData);

  const paths = posts.map((post) => ({
    params: { id: post.id }
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const filePath = path.join(process.cwd(), "data", "posts.json");
  const jsonData = fs.readFileSync(filePath, "utf-8");
  const posts = JSON.parse(jsonData);

  const post = posts.find((p) => p.id === params.id);

  return { props: { post } };
}

export default function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

 

📌 예제 코드 (pages/posts/[id].js)

import fs from "fs";
import path from "path";

export async function getStaticPaths() {
  const filePath = path.join(process.cwd(), "data", "posts.json");
  const jsonData = fs.readFileSync(filePath, "utf-8");
  const posts = JSON.parse(jsonData);

  const paths = posts.map((post) => ({
    params: { id: post.id }
  }));

  return { paths, fallback: false };
}

export async function getStaticProps({ params }) {
  const filePath = path.join(process.cwd(), "data", "posts.json");
  const jsonData = fs.readFileSync(filePath, "utf-8");
  const posts = JSON.parse(jsonData);

  const post = posts.find((p) => p.id === params.id);

  return { props: { post } };
}

export default function Post({ post }) {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

✅ **getStaticPaths**로 모든 페이지 경로를 미리 생성하고,
✅ **getStaticProps**로 정적 HTML 생성하여 SEO와 성능 최적화!


4️⃣ API Routes 활용하여 백엔드 연동

🔹 1. 글 작성 API (pages/api/posts/create.js)

  • API Routes를 사용하여 서버리스 백엔드 구현
  • POST 요청으로 새 블로그 글 추가

📌 예제 코드 (pages/api/posts/create.js)

import fs from "fs";
import path from "path";

export default function handler(req, res) {
  if (req.method === "POST") {
    const filePath = path.join(process.cwd(), "data", "posts.json");
    const jsonData = fs.readFileSync(filePath, "utf-8");
    const posts = JSON.parse(jsonData);

    const newPost = {
      id: String(posts.length + 1),
      title: req.body.title,
      content: req.body.content
    };

    posts.push(newPost);
    fs.writeFileSync(filePath, JSON.stringify(posts, null, 2));

    res.status(201).json({ message: "글이 추가되었습니다." });
  } else {
    res.status(405).end(); // Method Not Allowed
  }
}

✅ **API Routes**를 활용하면 백엔드 서버 없이풀스택 애플리케이션 개발 가능!


5️⃣ 스타일링 및 SEO 최적화

📌 스타일링 (CSS 모듈 또는 Tailwind CSS 추천)

  • CSS Modules → styles/Home.module.css 사용
  • Tailwind CSS → 빠르고 직관적인 스타일링 가능 (npm install tailwindcss)

📌 SEO 최적화 (next/head)

  • **next/head**를 사용하여 메타태그 설정으로 SEO 강화
    📌 예제 코드
import Head from "next/head";

<Head>
  <title>Next.js 블로그 - {post.title}</title>
  <meta name="description" content={post.content} />
</Head>

SEO 최적화검색 엔진 노출 극대화!


🎯 마무리: Next.js로 완성한 블로그 웹사이트

🔥 Next.js의 SSG, 동적 라우팅, API Routes를 모두 적용한 완벽한 블로그 웹사이트!
🚀 이제 완성된 블로그를 Vercel에 배포하고, 실전 프로젝트에 도전해보자!

반응형