- Published on
- ·7 min read
Next.js 블로그 글에 연관 글 목록 추가하기
개요
제가 사용하는 Tailwind CSS Blog Starter 템플릿에서는 기본으로 이전글
, 다음글
보기가 있습니다.
저에게 이전, 다음글은 별 의미가 없게 느껴져서,
이전글, 다음글 대신에 태그와 연관된 글 목록
을 보여주도록 변경했습니다.
미리보기
구현
1. 연관된 글 필터링
글에서 지정된 태그와 동일한 태그를 사용하는 글 목록 5개를 필터링합니다.
pages/blog/[...slug].js
파일을 엽니다.getRelatedPosts
함수를 추가합니다.
import kebabCase from '@/lib/utils/kebabCase'
function getRelatedPosts(allPosts, currentPost) {
const defaultCount = 5
return allPosts
.filter(
(item) =>
item.draft !== true &&
item.slug !== currentPost.frontMatter.slug &&
item.tags.filter((tag) =>
currentPost.frontMatter.tags.map((m) => kebabCase(m)).includes(kebabCase(tag))
).length > 0
)
.slice(0, defaultCount)
}
- draft가 true인 글은 제외
- 현재 글은 제외
- 현재 글의 태그들과 동일한 태그를 포함하는 글 필터
- 그 중 최근 글 5개만 필터링
getStaticProps
함수를 수정합니다.
위에서 추가한 getRelatedPosts
함수를 호출하고, relatedPosts
변수에 담아서 props
에 추가합니다.
export async function getStaticProps({ params }) {
const allPosts = await getAllFilesFrontMatter('blog')
// ... 생략
const relatedPosts = getRelatedPosts(allPosts, post) // <- 추가
// ... 생략
return { props: { post, authorDetails, prev, next, relatedPosts } } // <- relatedPosts 추가
}
Blog
컴포넌트를 수정합니다.
위 props에 추가한 relatedPosts
를 Blog
컴포넌트에 전달합니다.
export default function Blog({ post, authorDetails, prev, next, relatedPosts }) { // <- relatedPosts 추가
const { mdxSource, toc, frontMatter } = post
return (
<>
{frontMatter.draft !== true ? (
<MDXLayoutRenderer
layout={frontMatter.layout || DEFAULT_LAYOUT}
toc={toc}
mdxSource={mdxSource}
frontMatter={frontMatter}
authorDetails={authorDetails}
prev={prev}
next={next}
relatedPosts={relatedPosts} {/* <- relatedPosts 추가 */}
/>
) : (
<div className="mt-24 text-center">...생략</div>
)}
</>
)
}
2. RelatedPosts 컴포넌트 추가
components/RelatedPosts.js
파일을 추가합니다.내용은 아래와 같습니다. UI는 취향에 따라서 변경하시면 됩니다.
import Link from 'next/link'
const RelatedPosts = ({ posts }) => {
if (!posts || posts.length === 0) return null
return (
<div className="my-2 rounded-lg bg-gray-100 py-4 pl-4 pr-4 dark:bg-gray-800 xl:py-8">
<h2 className="toc-ignore mb-2 text-base font-bold uppercase tracking-wide text-gray-800 dark:text-gray-200">
Related Tags Posts
</h2>
{posts.map((post, index) => (
<div key={post.slug} className="py-2">
<div className="flex flex-row content-center justify-start space-x-6">
<div className="min-w-[80px] text-xs font-semibold text-rose-400">
{new Date(post.date).toLocaleDateString(siteMetadata.locale, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})}
</div>
<Link key={index} href={`/blog/${post.slug}`}>
<a className="truncate text-sm font-semibold text-gray-500 hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300">
{post.title}
</a>
</Link>
</div>
</div>
))}
</div>
)
}
export default RelatedPosts
3. RelatedPosts 가 표시되기 원하는 Layout에 추가합니다.
표시되기 원하는 Layout 파일 열기
(저는 이전에 만들어 둔 기본 Layout인layouts/PostToc.js
에 추가했습니다.)원하는 Layout에 RelatedPosts 컴포넌트 호출
import RelatedPosts from '@/components/RelatedPosts' // 추가
const postDateTemplate = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
export default function PostLayout({ frontMatter, authorDetails, relatedPosts, children }) { // <- relatedPosts 추가
const { slug, date, title, tags } = frontMatter
return (
<SectionContainer>
// ...
<ScrollTopAndComment />
<article>
<div className="...">
<div className="..." style={{ gridTemplateRows: 'auto 1fr' }}
>
<div className="...">
<div className="...">{children}</div>
<Comments frontMatter={frontMatter} />
<RelatedPosts posts={relatedPosts} /> {/* <- RelatedPosts 추가 */}
</div>
</div>
</div>
</article>
</SectionContainer>
)
}
코드
코드는 related_post 브랜치 또는 commit history로 확인하실 수 있습니다.
태그와 연관된 글
2023. 09. 27.
Next.js - 블로그 다국어(i18n)로 만들기 Part 42023. 09. 26.
Next.js - 블로그 다국어(i18n)로 만들기 Part 32023. 09. 25.
Next.js - 블로그 다국어(i18n)로 만들기 Part 22023. 09. 24.
Next.js - 블로그 다국어(i18n)로 만들기 Part 12023. 09. 19.
Next.js - 다국어(i18n) 설정 및 static html로 내보내기 Part 2