
웹사이트를 이용할 때, 유저는 현재 위치를 직관적으로 파악할 수 있어야 한다.
특히, 계층 구조가 깊은 웹사이트에선 사용자가 어느 페이지에 있는지 쉽게 이해할 수 있도록 도와주는 네비게이션 요소가 필요하다.
Breadcrumb(탐색 경로)은 웹사이트에서 사용자의 현재 위치를 계층 구조로 표시하는 네비게이션 UI이다.
일반적으로 다음과 같은 형태로 나타낸다.
홈 > 카테고리 > 세부 페이지
Home / Category / Subcategory / Product

웹사이트에 Breadcrumb을 적용하면 다음과 같은 이점이 있다.
1. 현재 위치를 쉽게 파악 가능
2. 빠른 네비게이션 제공
3. SEO 최적화
검색 엔진에서 사이트의 구조를 쉽게 이해할 수 있도록 도와준다.
Google의 검색 결과에서도 탐색 경로가 표시될 수 있어 클릭률(CTR)이 향상된다.
4. UX 개선
이제 Next.js에서 동적으로 Breadcrumb을 구현하는 방법을 알아보자.
현재 프로젝트는 Next.js 14버전과 App Router 방식을 사용하고 있다.
Breadcrumb은 현재 페이지의 경로를 자동으로 감지해 표시하는 역할을 한다.
Next.js에서 제공하는 usePathname 훅을 사용하면 현재 URL을 배열로 변환하여 경로를 쉽게 조작할 수 있다.
구현 순서
usePathname을 사용해 현재 URL을 가져옴
URL을 / 기준으로 나누어 배열로 변환
첫 번째 요소는 "홈" 링크로 설정
마지막 요소는 비활성화된 상태(클릭 불가)
특정 경로에서는 Breadcrumb을 숨김 처리
Breadcrumb.tsx
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
// 특정 페이지에서 Breadcrumb을 숨길 수 있도록 설정
const EXCLUDED_PAGES = ["/home", "/login", "/signup", "/dashboard", "/404"];
const BreadCrumb = () => {
const paths = usePathname(); // 현재 경로 가져오기
const pathNames = paths.split("/").filter((path) => path); // URL을 배열로 변환
// 특정 페이지에서는 Breadcrumb을 숨김
if (EXCLUDED_PAGES.includes(paths)) return null;
return (
<nav>
<ol>
{/* 홈 링크 */}
<li>
<Link href="/">홈</Link>
</li>
{pathNames.map((segment, index) => {
const href = "/" + pathNames.slice(0, index + 1).join("/");
return (
<li key={`breadcrumb-${segment}-${index}`}>
<span> > </span>
{/* 마지막 경로는 클릭 불가능하도록 처리 */}
{index === pathNames.length - 1 ? (
<span>{decodeURIComponent(segment)}</span>
) : (
<Link href={href}>{decodeURIComponent(segment)}</Link>
)}
</li>
);
})}
</ol>
</nav>
);
};
export default BreadCrumb;
이 코드는 usePathname을 이용해 현재 URL을 가져온 다음, / 기준으로 잘라 배열을 만든다.
그리고 배열을 기반으로 Breadcrumb을 동적으로 생성하며
마지막 경로는 현재 위치를 나타내므로 클릭이 불가능하도록 처리한다.
또한, EXCLUDED_PAGES 배열을 통해 특정 경로에서는 Breadcrumb이 표시되지 않도록 했다.
Breadcrumb은 단순한 UI 요소가 아니라, SEO에도 중요한 역할을 한다.
특히, Google 검색에서 schema.org의 BreadcrumbList 구조를 지원하기 때문에
JSON-LD 데이터를 추가하면 검색 결과에서 탐색 경로가 표시될 가능성이 높아진다.
BreadCrumbJsonLd.tsx
"use client";
import { usePathname } from "next/navigation";
import { useEffect } from "react";
// 사이트의 기본 URL (실제 서비스에서는 도메인으로 변경)
const BASE_URL = "https://example.com";
const BreadCrumbJsonLd = () => {
const pathname = usePathname(); // 현재 경로 가져오기
const pathSegments = pathname.split("/").filter(Boolean); // URL을 배열로 변환
// JSON-LD 형식의 Breadcrumb 데이터 생성
const breadcrumbList = [
{
"@type": "ListItem",
position: 1,
name: "홈",
item: BASE_URL,
},
...pathSegments.map((segment, idx) => ({
"@type": "ListItem",
position: idx + 2, // 홈을 포함하므로 +2
name: decodeURIComponent(segment),
item: `${BASE_URL}/${pathSegments.slice(0, idx + 1).join("/")}`,
})),
];
useEffect(() => {
const jsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: breadcrumbList,
};
// JSON-LD 스크립트 태그 생성 및 추가
const scriptTag = document.createElement("script");
scriptTag.type = "application/ld+json";
scriptTag.textContent = JSON.stringify(jsonLd);
document.head.appendChild(scriptTag);
return () => {
document.head.removeChild(scriptTag);
};
}, [pathname]);
return null;
};
export default BreadCrumbJsonLd;
여기서도 usePathname으로 현재 경로를 가져온 다음
JSON-LD 형식의 데이터를 동적으로 생성한다.
그리고 useEffect로 <head> 태그에 <script type="application/ld+json">를 삽입함으로써
검색 엔진이 사이트의 계층 구조를 이해할 수 있도록 한다.
위 코드를 적용하면 사이트를 접속했을 때 브라우저의 개발자 도구에서
<head> 태그 안에 자동으로 JSON-LD <script> 태그가 삽입되는 것을 볼 수 있다.
JSON-LD 예제
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "홈",
"item": "https://example.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "products",
"item": "https://example.com/products"
},
{
"@type": "ListItem",
"position": 3,
"name": "category",
"item": "https://example.com/products/category"
},
{
"@type": "ListItem",
"position": 4,
"name": "laptop",
"item": "https://example.com/products/category/laptop"
}
]
}
</script>
@context는 이 JSON-LD 데이터가 schema.org 표준을 따른다는 것을 의미한다.
@type을 BreadcrumbList로 지정하면, 이 데이터가 Breadcrumb 정보를 제공한다는 걸 알 수 있다.
itemListElement는 Breadcrumb을 구성하는 요소들의 목록을 정의하고
검색 엔진은 이 정보를 활용해 페이지의 탐색 경로를 분석할 수 있다.
itemListElement 구성요소
"@type": "Listitem" : 이 항목이 목록의 한 요소라는 것을 의미"position" : Breadcrumb에서 이 항목이 몇 번째인지 지정"name" : 해당 항목의 표시 이름 (ex. "홈", "products", "category" 등)"item" : 해당 항목의 실제 URL이제 Breadcrumb을 모든 페이지에서 사용할 수 있도록 app/layout.tsx에 추가해준다.
layout.tsx
import BreadCrumb from "../components/BreadCrumb";
import BreadCrumbJsonLd from "../components/BreadCrumbJsonLd";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>
{/* Breadcrumb UI 및 SEO 데이터 추가 */}
<BreadCrumb />
<BreadCrumbJsonLd />
{children}
</body>
</html>
);
}
이렇게 하면 모든 페이지에서 Breadcrumb이 전역으로 적용될 것이다.
유저는 탐색 경로를 바로 확인할 수 있고, 검색 엔진도 구조화된 데이터를 활용해 사이트 구조를 파악하게 된다.