[개발자 포트폴리오 > AboutMe] 목차 네비게이션 구현 | 마크다운 컴파일, withSlugs, withToc, withTocExport
이번 포스팅에서는 마크다운 내용에서 목차를 추출한 후 해당 목차로 이동할 수 있는 네비게이션을 구현해보려 한다.
지난 포스팅
[개발자 포트폴리오 > AboutMe] 마크다운 화면에 뿌리기, word highlighting 적용 | MDXRemote, Tailwind
이번 포스팅에서는 저번 포스팅에서 구현한 getAboutMeContent 함수를 사용하여노션페이지에서 조회한 마크다운을 화면에 뿌리는 과정에 대해 정리해보려 한다. 지난 포스팅 AboutMe] 노션 페이지 내
yooputer-devlog.tistory.com
interface TocEntry {
value: string;
depth: number;
id?: string;
children?: Array<TocEntry>;
}
function TableOfContentsLink({ item }: { item: TocEntry }) {
return (
<div className="space-y-2">
<Link
key={item.id}
href={`#${item.id}`}
className={`hover:text-foreground text-muted-foreground block font-medium transition-colors`}
>
{item.value}
</Link>
{item.children && item.children.length > 0 && (
<div className="space-y-2 pl-4">
{item.children
.map((subItem) => {
return {
...subItem,
value: subItem.value
}
})
.map((subItem: TocEntry) => (
<TableOfContentsLink key={subItem.id} item={subItem} />)
)
}
</div>
)}
</div>
);
}
마크다운 문자열에서 목차를 추출하기 위해서는 마크다운을 컴파일하여야 한다.
import { compile } from '@mdx-js/mdx';
import { getAboutMeContent } from '@/lib/notion';
import rehypeSanitize from 'rehype-sanitize';
import withSlugs from 'rehype-slug';
import withToc from '@stefanprobst/rehype-extract-toc';
import withTocExport from '@stefanprobst/rehype-extract-toc/mdx';
export default async function AboutMe() {
const { markdown } = await getAboutMeContent();
const { data } = await compile(markdown, {
rehypePlugins: [
withSlugs,
rehypeSanitize,
withToc,
withTocExport,
],
});
...
그리고 사이드바에서 컴파일한 data 객체를 사용하여 목차 링크 컴포넌트로 매핑 한다
{/* 왼쪽 사이드바 */}
<div className="hidden md:block">
<div className="sticky top-16">
<div className="bg-muted/60 space-y-4 rounded-lg p-6 backdrop-blur-sm">
<h3 className="text-lg font-semibold">About Me</h3>
<nav className="space-y-3 text-sm">
{data?.toc?.map((item) => <TableOfContentsLink key={item.id} item={item} />)}
</nav>
</div>
</div>
</div>
이때 마크다운을 렌더링하는 MDXRemote 컴포넌트의 mdxOptions에 withSlugs 플러그인이 추가되어야
목차 링크를 클릭하였을 때 정상적으로 해당 위치를 이동한다.
// 기존 코드 수정(withSlugs 추가)
<MDXRemote
source={markdown}
options={{
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [withSlugs, rehypeSanitize],
},
}}
/>
[Next.js] 동적 라우팅 페이지에 SSG 적용해서 페이지 로딩 속도 개선하기 (1) | 2025.07.16 |
---|---|
[개발자 포트폴리오 > Projects] 노션 데이터베이스 조회하기 | 화면 구현하기 (0) | 2025.06.11 |
[개발자 포트폴리오 > AboutMe] 마크다운 화면에 뿌리기, word highlighting 적용 | MDXRemote, Tailwind (1) | 2025.06.05 |
[개발자 포트폴리오 > AboutMe] 노션 페이지 내용 조회 함수 구현 | pageToMarkdown (1) | 2025.06.04 |
[개발자 포트폴리오] 프로젝트 개요, 기술 스택 및 선정 이유, 핵심 기능 (2) | 2025.06.02 |