- Next.js에서 경로 간의 탐색하는 방법에는 두 가지가 있습니다.
<Link>
컴포넌트 활용
useRouter()
hook 활용
<Link>
컴포넌트
<Link>
는 HTML <a>
태그를 확장하여 경로 간 프리패치 및 클라이언트 측 탐색을 제공하는 내장 구성 요소입니다.
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
동적 세그먼트에 연결
- 동적 세그먼트에 연결할 때 템플릿 리터럴과 interpolation을 사용하여 링크 목록을 생성할 수 있습니다. 예를 들어 블로그 게시물 목록을 생성하려면 다음을 수행하세요.
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()은 링크가 활성 상태인지 확인하는 데 사용할 수 있습니다. 예를 들어 활성 링크에 클래스를 추가하려면 현재 링크의 링크 pathname과 일치하는 지 확인할 수 있습니다.
'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 === link.href
return (
<Link
className={isActive ? 'text-blue' : 'text-black'}
href={link.href}
key={link.name}
>
{link.name}
</Link>
)
})}
</>
)
}
ID로 스크롤
- Next.js 앱 라우터의 기본 동작은 새 경로의 맨 위로 스크롤하거나 앞뒤 탐색을 위해 스크롤 위치를 유지하는 것입니다.
- 탐색 시 특정 ID로 스크롤하려면 # 해시 링크를 URL에 추가하거나 해시 링크를 href 속성에 전달할 수 있습니다. (이미
<a>
태그에 있는 기능이죠?)
- 이는
<Link>
컴포넌트가 <a>
태그로 렌더링되기 때문에 가능합니다.
<Link href="/dashboard#settings">Settings</Link>
<a href="/dashboard#settings">Settings</a>
스크롤 복원 비활성화
- Next.js 앱 라우터의 기본 동작은 새 경로의 맨 위로 스크롤하거나 앞뒤 탐색을 위해 스크롤 위치를 유지하는 것입니다.
- 이 동작을 비활성화하려면
<Link>
컴포넌트에 scroll={false}
를 전달해주거나 router.push
또는 router.replace()
에 scroll: false를 전달하면 됩니다.
useRouter() Hook
useRouter()
hook을 사용하면 프로그래밍 방식으로 경로를 변경할 수 있습니다.
- 이 hook은 클라이언트 컴포넌트 내에서만 사용할 수 있으며 next/navigation에서 가져올 수 있습니다. (client-side에서만 실행되기 때문이죠)
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
useRouter
를 사용해야 하는 특별한 요구 사항이 없을 경우 <Link>
컴포넌트를 사용하는 것을 권장합니다.
라우팅 및 탐색 작동 방식
- App Router는 라우팅 및 탐색을 위해 하이브리드 접근 방식을 사용합니다. 서버에서 애플리케이션 코드는 경로 세그먼트 별로 자동으로 코드 분할됩니다.
- 클라이언트에서 Next.js는 경로 세그먼트를 미리 가져오고 캐시합니다. 즉 사용자가 새 경로로 이동할 때 브라우저는 페이지를 다시 로드하지 않고 변경된 경로 세그먼트만 다시 렌더링하여 탐색 경험과 성능을 향상 시킵니다.
1. Prefetching (프리패칭)
- 프리 패칭은 사용자가 경로를 방문하기 전에 백그라운드에서 경로를 미리 로드하는 방법입니다. Next.js에서 경로를 미리 가져오는 방법에는 두 가지가 있습니다.
<Link>
컴포넌트 : 경로가 사용자의 뷰포트에 표시되면 자동으로 미리 가져옵니다. 프리 패칭는 페이지가 처음 로드될 때 또는 스크롤을 통해 표시될 때 발생합니다
router.prefetch()
: useRouter
hook을 사용하여 프로그래밍 방식으로 경로를 미리 가져올 수 있습니다.
<Link>
의 프리패치 동작은 정적 경로와 동적 경로에 따라 다릅니다.
- 정적 경로 : prefetch 기본값은 true입니다. 전체 경로가 프리패치되고 캐시됩니다.
- 동적 경로 : prefetch 기본값은 auto 입니다. 첫 번째 loading.js 파일이 프리패치되고 30초동안 캐시될 때까지 공유 레이아웃만 표시됩니다.
- 이렇게 하면 전체 동적 경로를 가져오는 비용이 줄어들고 사용자에게 더 나은 시각적 피드백을 제공하기 위해 즉시 로드 상태를 표시할 수 있습니다.
- prefetch prop을 false로 설정하여 프리패칭을 비활성화 할 수 있습니다.
- 프리페칭은 개발 중에는 활성화되지 않고 프로덕션에서만 활성화됩니다.
2. Caching (캐싱)
- Next.js에는 라우터 캐시라는 메모리 내 클라이언트 측 캐시가 있습니다.
- 사용자가 앱을 탐색할 때 미리 가져온 경로 세그먼트와 방문한 경로의 React Server 컴포넌트 페이로드가 캐시에 저장됩니다.
- 이는 탐색 시 서버에 새로운 요청을 하는 대신 캐시를 최대한 재사용하여 요청 수와 전송되는 데이터 수를 줄여 성능을 향상한다는 의미입니다. (Router 캐시 더 알아보기!)
3. Partial Rendering (부분 렌더링)
- 부분 렌더링은 클라이언트에서 탐색을 다시 렌더링할 때 변경되는 경로 세그먼트만 의미하며 모든 공유 세그먼트는 보존됩니다.
- 예를 들어 두 형제 경로 및 사이를 탐색하는 경우 /dashboard/settings 에서 /dashboard/analytics 로 이동하는 경우 analytics page만 렌더링되고 dashboard의 layout.js은 유지됩니다.
4. Soft Navigation (소프트 네비게이션)
- 기본적으로 브라우저는 페이지 간 하드 탐색을 수행합니다. useState는 브라우저가 페이지를 다시 로드하고 앱의 hook과 같은 React 상태와 사용자의 스크롤 위치 또는 초점이 맞춰진 요소와 같은 브라우저 상태로 재설정한다는 것을 의미합니다.
- 그러나 Next.js에서 앱 라우터는 소프트 탐색을 사용합니다. 이는 React가 React와 브라우저 상태를 유지하면서 변경된 세그먼트만 렌더링하며 전체 페이지를 다시 로드하지 않는 다는 것을 의미합니다.
5. Back and Forward Navigation (뒤로 또는 앞으로 탐색)
- 기본적으로 Next.js는 앞뒤 탐색을 위한 스크롤 위치를 유지하고 라우터 캐시의 경로 세그먼트를 재사용합니다.
Reference