포스트 목록 만들기 — 최신순, 태그별 필터, 페이징까지

2025. 6. 24. 09:00·Next.js
728x90
반응형

지금까지 우리는 Markdown으로 글을 만들고, URL을 동적으로 연결하고, MDX까지 적용했어요.
이제 진짜 블로그의 “얼굴”인 포스트 목록 페이지를 꾸며볼 차례입니다.

단순한 목록만 있는 블로그는 이제 지났어요.
최신순 정렬, 태그 필터링, 페이지네이션까지 있는 진짜 포스트 리스트를 만들어봅시다.


🌀 1. 최신순 정렬된 목록 만들기

기본적으로는 getSortedPostsData()에서 이미 날짜를 기준으로 정렬하고 있을 거예요.

// lib/posts.ts
export function getSortedPostsData() {
  const files = fs.readdirSync(postsDirectory);
  const posts = files.map((fileName) => {
    const id = fileName.replace(/\.mdx?$/, "");
    const fullPath = path.join(postsDirectory, fileName);
    const fileContents = fs.readFileSync(fullPath, "utf8");
    const { data } = matter(fileContents);

    return {
      id,
      ...(data as { title: string; date: string; tags: string[] }),
    };
  });

  return posts.sort((a, b) => (a.date < b.date ? 1 : -1));
}

이제 가장 최근에 쓴 글이 가장 위에 뜨는 구조가 됩니다.


🏷️ 2. 태그별 필터링 기능 추가

각 포스트의 frontmatter에 tags 배열이 있다고 가정할게요.

---
title: "MDX 완전정복"
date: "2025-06-10"
tags: ["Next.js", "MDX", "블로그"]
---

전체 포스트에서 고유한 태그 목록을 추출합니다:

export function getAllTags(posts: PostData[]) {
  const tagSet = new Set<string>();
  posts.forEach((post) => {
    post.tags?.forEach((tag) => tagSet.add(tag));
  });
  return Array.from(tagSet);
}

컴포넌트에서 태그를 클릭하면 해당 태그를 포함한 포스트만 필터링되도록 만듭니다:

const [selectedTag, setSelectedTag] = useState<string | null>(null);

const filteredPosts = selectedTag
  ? posts.filter((p) => p.tags?.includes(selectedTag))
  : posts;

return (
  <div>
    <div className="flex gap-2 mb-4">
      {tags.map((tag) => (
        <button
          key={tag}
          onClick={() => setSelectedTag(tag)}
          className={`px-3 py-1 border ${selectedTag === tag ? "bg-blue-200" : ""}`}
        >
          #{tag}
        </button>
      ))}
    </div>
    ...
  </div>
);

이제 태그 버튼을 누르면 해당 글들만 쏙쏙 보입니다.


📄 3. 페이지네이션 기능 추가

글이 많아질수록 목록을 쪼개서 보여줘야 해요. 간단하게 페이징을 구현해볼게요.

const POSTS_PER_PAGE = 5;
const [page, setPage] = useState(1);

const paginatedPosts = filteredPosts.slice(
  (page - 1) * POSTS_PER_PAGE,
  page * POSTS_PER_PAGE
);

const totalPages = Math.ceil(filteredPosts.length / POSTS_PER_PAGE);

그리고 아래처럼 페이지 버튼을 추가해줍니다:

<div className="mt-6 flex gap-2">
  {Array.from({ length: totalPages }, (_, i) => (
    <button
      key={i}
      onClick={() => setPage(i + 1)}
      className={`px-3 py-1 border ${page === i + 1 ? "bg-gray-300" : ""}`}
    >
      {i + 1}
    </button>
  ))}
</div>

이제 페이지마다 최대 5개씩의 글이 정리되어 보입니다.


✅ 마무리하며

단순한 목록을 넘어서, 필터, 정렬, 페이징이 있는 포스트 리스트는
블로그의 사용성을 크게 향상시켜줍니다.

Next.js와 React의 상태관리, 배열 메서드만으로도 충분히 유연한 구현이 가능하죠.

“정보는 많지만, 정리는 기술이다.”

 

728x90
반응형

'Next.js' 카테고리의 다른 글

마크다운 에디터 연결하기 — CMS 없이 블로그 글 쓰는 워크플로우 만들기  (3) 2025.06.26
SEO 최적화 — next/head와 Open Graph 메타 태그 제대로 쓰기  (0) 2025.06.25
블로그에 다크모드 적용하기 — next-themes로 UX 높이기  (2) 2025.06.23
스타일링 선택하기 — Tailwind CSS vs Styled Components  (2) 2025.06.22
MDX로 Markdown에 컴포넌트 삽입하기 — 코드블럭, 이미지도 자유롭게!  (1) 2025.06.21
'Next.js' 카테고리의 다른 글
  • 마크다운 에디터 연결하기 — CMS 없이 블로그 글 쓰는 워크플로우 만들기
  • SEO 최적화 — next/head와 Open Graph 메타 태그 제대로 쓰기
  • 블로그에 다크모드 적용하기 — next-themes로 UX 높이기
  • 스타일링 선택하기 — Tailwind CSS vs Styled Components
코드를 걷는 사람
코드를 걷는 사람
devwanderer 님의 블로그 입니다.
  • 코드를 걷는 사람
    터미널 밖으로 나온 개발자
    코드를 걷는 사람
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Flutter
        • Flutter 게시판 앱 만들기
        • Flutter 뉴스 앱 만들기
        • Flutter 메모 앱 만들기
        • Flutter 캘린더 앱 만들기
        • Flutter 날씨 앱 만들기
      • Next.js
      • Ruby On Rails
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    뉴스앱
    백엔드개발
    모바일앱개발
    flutter기초
    Nextjs
    RubyOnRails
    table_calendar
    rails보안
    캘린더앱
    flutter디자인
    Firebase
    코드를걷는사람
    flutter게시판
    Flutter
    fluttertips
    flutter개발
    날씨앱
    ActiveRecord
    정적사이트
    flutter상태관리
    flutter앱개발
    openweather
    메모앱
    flutterui
    다크모드
    UI디자인
    감성앱
    북마크기능
    개발블로그
    UIUX
  • 최근 댓글

  • 최근 글

  • 반응형
    250x250
  • hELLO· Designed By정상우.v4.10.3
코드를 걷는 사람
포스트 목록 만들기 — 최신순, 태그별 필터, 페이징까지
상단으로

티스토리툴바