https://nextjs.org/learn/dashboard-app/navigating-between-pages
전 챕터에서, 대시보드 레이아웃, 페이지를 만들었다.
이제 사용자들이 대시보드 루트 간 이동을 할 수 있는 링크를 추가하자.
next/link 컴포넌트 사용법
usePathname( ) 훅을 통해 활성화된 링크를 보여주는 법
Next.js 내 네비게이션 동작 원리
페이지 간 연결을 위해, 보통 a 태그를 써왔다.
사이드바 링크는 a 요소를 쓰지만, 브라우저에서 hom, invoices,customer 페이지를 이동할 때 어떤 일이 일어나는지 자각해라
=> 각 페이지 네비게이션마다 전체 페이지 새로고침이 일어난다
Next.js에서, 앱 내 페이지간 연결을 위해 Link 컴포넌트를 사용할 수 있다.
Link 는 JS로 클라이언트-사이드 네비게이션을 하게 한다.
/app/ui/dashboard/nav-links.tsx 을 연다. Link 컴포넌트가 a 태그와 비슷해보이지만, <a href="…"> 대신
<Link href="…">
를 쓴다.
변경한 걸 저장하고 localhost에서 작동하는지 확인해보자
이제 페이지간 이동이 새로고침 없이 되는 것을 볼 수 있다.
네비게이션 경험 향상을 위해, Next.js는 자동으로 루트 세그먼트에 의해 코드를 나눈다.
이것은 초기에만 앱 코드를 로드하는 일반적 리액트 SPA와 다르다.
루트에 의한 코트 스플리팅은 페이지가 isolate 되는 것을 말한다.
만약 페이지가 에러를 던져도, 나머지는 동작한다.
그리고, Link 컴포넌트가 브라우저의 뷰포트에 나타날 때마다, Next.js는 자동적으로 백그라운드에서 연결된 코드를 prefetch 한다.
사용자가 링크 클릭 시, 목적지 페이지로의 코드는 배경에서 이미 로드된다.
그리고 이것이 페이지 이동을 거의 즉시 응답하게 만든다.
공통 UI 패턴은 사용자에게 지금 어떤 페이지에 있는지 활성화된 링크를 보여주는 것이다. 이럭 위해, 사용자의 현재 경로를 URL로부터 가져와야한다.
Next.js는 경로를 확인하고 이 패턴을 구현하기 위해 usePathname( )이라는 훅을 제공한다.
usePathname( )이 훅이기 때문에, nav-link.tsx를 클라이언트 컴포넌트로 바꿔야한다.
1. 리액트의 "use client" 지시어를 파일 상단에 추가한다.
2. next/navigation의 usePathname( ) 을 불러온다.
3. NavLinks 컴포넌트 내 pathname이라는 변수에 경로를 할당한다.
링크가 활성화 돼있을 때, clsx 라이브러리를 스타일링을 위해 쓸 수 있다.
link.href가 pathname과 일치하게 되면, 링크는 파란 글씨와 밝은 파랑 배경으로 보여진다.
nav-links.tsx의 최종 코드이다.
'use client';
import {
UserGroupIcon,
HomeIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
// Map of links to display in the side navigation.
// Depending on the size of the application, this would be stored in a database.
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>
);
})}
</>
);
}
