일반적인 HTML에서는 <a>
태그를 사용하여 페이지를 연결합니다. 하지만 이 방식은 전체 페이지 새로고침이라는 치명적인 단점이 있습니다.
// /app/ui/dashboard/nav-links.tsx
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
const links = [
{ name: 'Home', href: '/dashboard', icon: HomeIcon },
{ name: 'Invoices', href: '/dashboard/invoices', icon: DocumentDuplicateIcon },
{ name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
];
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<a
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</a>
);
})}
</>
);
}
⚠️ 문제점: 링크 클릭 시 전체 페이지 새로고침 발생
Next.js의 <Link>
컴포넌트는 JavaScript 기반 클라이언트 사이드 네비게이션을 제공하여 사용자 경험을 크게 향상시킵니다.
// /app/ui/dashboard/nav-links.tsx
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link'; // 추가
const links = [
{ name: 'Home', href: '/dashboard', icon: HomeIcon },
{ name: 'Invoices', href: '/dashboard/invoices', icon: DocumentDuplicateIcon },
{ name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
];
export default function NavLinks() {
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
prefetch={false}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
💡 Prefetch 참고자료: Beomy님의 preload, preconnect, prefetch 포스트에서 자세한 내용을 확인할 수 있습니다.
Production 환경에서의 동작:
1. 브라우저 Viewport에 <Link>
컴포넌트가 나타남
2. 연결된 route의 코드를 백그라운드에서 자동 Prefetch
3. 사용자가 링크 클릭 시 이미 로드된 코드로 즉시 전환
결과: ⚡ 초고속 페이지 전환 실현
사용자가 현재 어떤 페이지에 있는지 명확하게 알려주는 활성 링크 표시는 필수적인 UI 패턴입니다.
// /app/ui/dashboard/nav-links.tsx
"use client"; // 클라이언트 컴포넌트 선언
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from "@heroicons/react/24/outline";
import clsx from "clsx";
import Link from "next/link";
import { usePathname } from "next/navigation"; // 추가
export default function NavLinks() {
const pathname = usePathname();
console.log("pathname is ", pathname); // 현재 경로 출력
// 예: '/dashboard'에서 호출 시 → '/dashboard' 출력
}
"use client";
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from "@heroicons/react/24/outline";
import clsx from "clsx";
import Link from "next/link";
import { usePathname } from "next/navigation";
const links = [
{ name: "Home", href: "/dashboard", icon: HomeIcon },
{ name: "Invoices", href: "/dashboard/invoices", icon: DocumentDuplicateIcon },
{ name: "Customers", href: "/dashboard/customers", icon: UserGroupIcon },
];
export default function NavLinks() {
const pathname = usePathname();
return (
<>
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className={clsx(
"flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3",
{
// 현재 경로와 링크 경로가 일치하면 활성 스타일 적용
"bg-sky-100 text-blue-600": pathname === link.href,
}
)}
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
</>
);
}
"bg-gray-50 text-gray-800" /* 비활성 상태 */
"bg-sky-100 text-blue-600" /* 활성 상태 */
"hover:bg-sky-100 hover:text-blue-600" /* 호버 상태 */
구분 | 전통적인 <a> 태그 | Next.js <Link> |
---|---|---|
페이지 전환 | 전체 새로고침 | 부분 업데이트 |
로딩 속도 | 느림 | 초고속 |
코드 분할 | 없음 | 자동 분할 |
Prefetching | 없음 | 자동 실행 |
사용자 경험 | 끊김 | 매끄러움 |
usePathname
을 통한 현재 위치 표시Next.js의 네비게이션 시스템을 활용하면 성능과 사용자 경험을 동시에 최적화할 수 있습니다.