Next.js 라우터는 클라이언트 측 탐색과 함께 서버 중심 라우팅을 사용한다. 즉각적인 로딩 상태 및 동시 렌더링을 지원한다. 이것은 내비게이션이 클라이언트 측 상태를 유지하고 비용이 많이 드는 재렌더링을 피하고 중단 가능하며 경험 상태를 일으키지 않는다는 것을 의미한다.
경로 사이를 탐색하는 방법에는 <Link> 엘리먼트와 useRouter hook 두 가지 방법이 있다.
- <Link> 엘리먼트
<Link>는 <a> HTML 엘리먼트를 확장하여 경로 간 프리페칭 및 클라이언트 측 탐색을 제공하는 React 컴포넌트이다. Next.js에서 경로 사이를 탐색하는 기본 방법이다.
<Link>를 사용하려면 next/link에서 가져오고 href prop을 컴포넌트에 전달한다.
// app/page.tsx
import Link from 'next/link';
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>;
}
<Link>에 전달할 수 있는 옵션 prop도 물론 있다.
- Examples
동적 세그먼트에 연결
동적 세그먼트에 연결할 때 템플릿 리터럴 및 보간을 사용할 수 있다.
// app/blog/PostList.tsx
import Link from 'next/link'
export default function PostList({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
활성 링크 확인
링크가 활성 상태인지 확인하는 데 usePathname()을 사용할 수 있다. 예를 들어 활성 링크에 클래스를 추가하려면 link의 href가 현재 pathname과 일치하는지를 체크할 수 있다.
// app/ui/Navigation.jsx
'use client'
import { usePathname } from 'next/navigation';
import { Link } from 'next/link';
export function Navigation({ navLinks }) {
const pathname = usePathname();
return (
<>
{navLinks.map((link) => {
const isActive = pathname.startWith(link.href);
return (
<Link
className={isActive ? 'text-blue': 'text-black'}
href={link.href}
key={link.name}
>
{link.name}
</Link>
)
})}
</>
)
}
id로 스크롤
<Link>의 기본 동작은 변경된 경로 세그먼트의 맨 위로 스크롤 하는 것이다. href에 정의된 id가 있으면 일반 <a> 태그와 마찬가지로 특정 id로 스크롤된다. 경로 세그먼트의 맨 위로 스크롤되는 것을 방지하려면 scroll={false}를 설정하고, 해시된 id를 href에 추가한다.
<Link href="/#hashid" scroll={false}>
Scroll to specific id.
</Link>
- useRouter() Hook
useRouter hook을 사용하면 클라이언트 컴포넌트 내에서 프로그래밍 방식으로 경로를 변경할 수 있다. useRouter를 사용하려면 next/navigation에서 가져오고 클라이언트 컴포넌트 내에서 hook을 호출한다.
// app/page.jsx
'use client'
import { useRouter } from 'next/navigation';
export default function Page() {
const router = useRouter();
return (
<button type="button" onClick={() => router.push('/dashbarod')}>
Dashboard
</button>
)
}
useRouter는 push(), refresh() 등의 메서드를 제공한다. <Link> 사용에 대한 특정 요구 사항이 없는 한 useRouter 컴포넌트를 사용하여 경로 사이를 탐색하는 것이 좋다.
- 탐색 작동 방식
- 경로 전환은 <Link> 또는 router.push() 호출을 사용하여 시작한다.
- 라우터는 브라우저의 주소 표시줄에서 URL을 업데이트한다.
- 라우터는 클라이언트 측 캐시에서 변경되지 않은 세그먼트(예: 공유 레아아웃)를 재사용하여 불필요한 작업을 방지한다. 이를 부분 렌더링이라고도 한다.
- 소프트 탐색 조건이 충족되면 라우터는 서버가 아닌 캐시에서 새 세그먼트를 가져온다. 그렇지 않은 경우 라우터는 하드 탐색을 수행하고 서버에서 서버 컴포넌트 페이로드를 가져온다.
- 생성된 경우 페이로드를 가져오는 동안 서버에서 로드 UI가 표시된다.
- 라우터는 캐시 된 페이로드 또는 새로운 페이로드를 사용하여 클라이언트에서 새 세그먼트를 렌더링 한다.
- 렌더링 된 서버 컴포넌트의 클라이언트 측 캐싱
새 라우터에는 서버 컴포넌트(페이로드)의 렌더링 된 결과를 저장하는 메모리 내 클라이언트 측 캐시가 있다. 캐시는 모든 수준에서 무효화를 허용하고 동시 렌더링에서 일관성을 보장하는 경로 세그먼트로 분할된다.
사용자가 앱을 탐색할 때 라우터는 이전에 가져온 세그먼트와 미리 가져온 세그먼트의 페이로드를 캐시에 저장한다. 이는 특정 경우에 라우터가 서버에 새 요청을 하는 대신 캐시를 재사용할 수 있음을 의미한다. 이렇게 하면 불필요하게 데이터를 다시 가져오고 컴포넌트를 다시 렌더링 하는 것이 방지하여 성능이 향상된다.
- 캐시 무효화
Server Actions는 경로(revalidatePath) 또는 캐시 태그(revalidateTag)로 온디맨드 데이터를 재검증하는 데 사용할 수 있다.
- 미리 가져오기
미리 가져오기는 경로를 방문하기 전에 백그라운드에서 미리 로드하는 방법이다. 미리 가져온 경로와 렌더링 결과는 라우터의 클라이언트 측 캐시에 추가된다. 이렇게 하면 미리 가져온 경로로 거의 즉시 탐색할 수 있다.
기본적으로 <Link> 컴포넌트를 사용할 때 뷰포트에 표시될 때 미리 가져온다. 이는 페이지가 처음 로드 되거나 스크롤할 때 발생할 수 있다. 경로는 useRouter() hook의 prefetch 메서드를 사용하여 프로그래밍 방식으로 미리 가져올 수도 있다.
경로가 정적이면 경로 세그먼트에 대한 모든 서버 컴포넌트 페이로드가 미리 가져온다. 경로가 동적이면 첫 번째 공유 레이아웃에서 첫 번째 loading.js파일까지의 페이로드를 프리페치한다. 이렇게 하면 전체 경로를 동적으로 미리 가져오는 비용이 줄어들고 동적 경로에 대한 상태를 즉시 로드 할 수 있다.
프리페치는 프로덕에서만 활성화되고, <Link>에 prefetch={false}를 전달하여 미리 가져오기를 비활성화할 수도 있다.
- 하드 탐색
탐색 시 캐시는 무효화되고 서버는 데이터를 다시 가져와 변경된 세그먼트를 다시 렌더링 한다.
- 소프트 탐색
탐색 시 변경된 세그먼트의 캐시가 재사용되며(있는 경우) 서버에 데이터를 새로 요청하지 않는다. 내비게이션에서 Next.js는 내비게이션 중인 경로가 미리 가져오고 동적 세그먼트를 포함하지 않거나 현재 경로와 동일한 동적 매개변수를 갖는 경우 소프트 내비게이션을 사용한다.
예를 들어 동적 [team] 세그먼트를 포함하는 다음 경로를 고려한다. /dashboard/[team]/*. /dashboard/[team]/* 아래의 캐시 된 세그먼트는 [team] 매개변수가 변경될 때만 무효화된다.
/dashbaord/team-red/* 에서 /dashboard/team-red/* 로 이동하면 소프트 탐색이 된다. /dashbaord/team-red/* 에서 /dashboard/team-blue/* 로 이동하는 것은 하드 탐색이 될 것이다.
- 뒤로/앞으로 탐색
뒤로 및 앞으로 탐색(popstate 이벤트)에는 소프트 탐색 동작이 있다. 즉, 클라이언트 측 캐시가 재사용되고 탐색이 거의 즉각적이다.
- 포커스 및 스크롤 관리
기본적으로 Next.js는 포커스를 설정하고 탐색에서 변경된 세그먼트를 보기 위해 스크롤한다.
'Next.js' 카테고리의 다른 글
Next.js 11-5 Routing Dynamic Routes (0) | 2023.05.24 |
---|---|
Next.js 11-4 Routing Route Groups (0) | 2023.05.24 |
Next.js 11-2 Routing Pages and Layouts (1) | 2023.05.19 |
Next.js 11-1 Routing Fundamentals (0) | 2023.05.18 |
Next.js 10-5 React Essential Context (0) | 2023.05.18 |