Linking and Navigating
Next.js router는 서버 중심의 라우팅, 클라이언트측 네비게이션을 사용한다. 즉각적인 로딩상태와 동시 렌더링을 지원한다. 이것은 네비게이션이 클라이언트 상태를 유지하고 비싼 리렌더링을 피하고, 방해가 되지 않으며 레이스 상태를 만들지 않는다는 것을 의미한다.
route간 이동은 다음과 같은 두가지 방법이 있다.
- <Link> 컴포넌트
- useRouter hook
이 페이지에서는 <Link>와 useRouter()를 어떻게 쓰는지 알아보고 네비게이션이 어떻게 동작하는지 깊게 알아본다.
<Link> 컴포넌트
<Link> 는 HTML a 태그에서 확장되어 route 간 사전 fetch 및 클라이언트 탐색을 제공하는 React 컴포넌트이다. 이것은 Next.js에서 route 간 탐색의 기본 방법이다.
<Link> 컴포넌트를 사용하기 위해서 next/link에서 import하고 href prop을 해당 컴포넌트에 넣어준다.
// app/page.tsx
import Link from 'next/link'
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}
<Link> 태그에 여러 옵션을 줄 수 있다. API reference 참조.
Examples
Linking to Dynamic Segments
동적인 segment로 연결할 때 탬플릿 리터럴이나 interpolation(보간?)을 사용하여 링크 목록을 생성할 수 있다. 예를 들면 블로그 포스트 리스트를 만들때 다음과 같다.
// app/blog/PostList.js
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>
)
}
Checking Active Links
링크가 활성화 되어있는지를 확인하기 위해 usePathname()을 사용할 수 있다. 예를 들면 활성화된 링크에 class를 추가하기위해 현재 pathname과 href가 같은지 확인할 수 있다.
// app/ui/Navigation.js
'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.startsWith(link.href)
return (
<Link
className={isActive ? 'text-blue' : 'text-black'}
href={link.href}
key={link.name}
>
{link.name}
</Link>
)
})}
</>
)
}
Scrolling to an Id
<Link>의 기본 동작으로 변경된 route segment의 맨위로 스크롤한다. 만약 href에 id가 정의되어 있으면 일반 a 태그와 유사하게 특정 id로 스크롤된다.
route segment 가장 위로 스크롤 되는것을 방지하기 위해 scroll={false}를 설정하고 해시ID를 href에 추가한다.
<Link href="/#hashid" scroll={false}>
Scroll to specific id.
</Link>
useRouter() Hook
useRouter hook은 클라이언트 컴포넌트 내에서 route를 프로그래밍 방식으로 변경할 수 있다.
useRouter를 사용하기 위해 next/navigation에서 import하고 클라이언트 컴포넌트에서 hook을 부른다.
// app/page.js
'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는 push(), refresh()등 메서드들을 제공한다. 자세한 사항은 API reference 참조.
* 추천 : useRouter를 꼭 써야하는 상황이 아니라면 <Link> 컴포넌트를 사용하여 route 사이를 탐색하는 것을 추천한다.
How Navigation Works
- route 변경은 <Link> 태그를 사용하거나 router.push()를 부를 때 발생한다.
- router는 브라우저 주소창의 URL을 업데이트한다.
- router는 바뀌지 않는 segment들(예를들면 공유되는 레이아웃)을 클라이언트측 캐시에서 재사용해서 불필요한 동작을 피한다. 이것을 부분 렌더링이라고도 한다.
- soft 네비게이션 조건이 충족되면 router는 서버가 아니라 캐시에서 새 segment를 fetch한다. 그렇지 않으면 router는 hard 네비게이션을 수행하고 서버에서 서버 컴포넌트 페이로드를 fetch 한다.
- 로딩 UI가 만들어져 있다면 페이로드가 fetch 될 때 로딩 UI가 서버에서 표시된다.
- router는 캐시된 혹은 새로운 페이로드를 사용하여 클라이언트에 새로운 segment를 렌더한다.
Client-side Caching of Rendered Server Components
(렌더된 서버 컴포넌트의 클라이언트 측 캐싱)
* 알면 좋은 것 : 이 클라이언트측 캐시는 서버측 Next.js HTTP 캐시와는 다르다.
새로운 router는 렌더된 서버 컴포넌트(페이로드) 결과를 저장하는 in-memory 클라이언트측 캐시를 가지고있다. 이 캐시는 모든 수준에서 무효화할 수 있고 동시 렌더링간의 일관성을 보장하는 route segment 단위로 나누어져 있다.
사용자가 app을 탐험할 때 router는 이전 fetch된 segment의 페이로드와 사전fetch된 segments를 캐시에 저장한다.
이것은 어떠한 상황에서 router가 서버에 새로운 요청을 보내는 대신 캐시를 재사용 할 수 있다는 것을 의미한다. 이것은 데이더를 다시 요청하거나 불필요한 컴포넌트 리렌더링을 피함으로써 성능을 향상시킨다.
Invalidating the Cache
Server Actions를 사용하여 요청시 경로(revalidatePath) 또는 캐시 태그(revalidateTag)별로 데이터를 재검증 할 수 있다.
Prefetching
사전 fetching은 route를 방문하기전 미리 background에서 미리 로드를 하는 것이다. 사전 fetch된 렌더링 결과는 router의 클라이언트 측 캐시에 추가된다. 따라서 사전 fetch된 route로는 즉시 이동할 수 있다.
기본적으로 route는 <Link> 컴포넌트를 사용할 때 뷰포트에 표시되기전 미리 fetch 된다. 이것은 페이지를 처음 로드하거나 스크롤할 때 발생할 수 있다. useRouter() hook의 사전 fetch 매서드를 사용하여 프로그래밍 방식으로도 사전 fetch를 할 수 있다.
Static and Dynamic Routes(정적,동적 루트) :
- 정적 route이면 route segment의 모든 서버 컴포넌트 페이로드는 사전 fetch된다.
- 동적 route이면 첫 번째 공유 레이아웃에서 첫 번째 loading.js 파일까지의 페이로드가 사전 fetch된다. 따라서 전체 route에서 동적으로 사전 fetch하는 비용이 감소하고 동적 route에서 즉각적인 로딩 상태가 가능하다.
* 알아두면 좋은것 :
- 사전 fetch는 production에서만 가능하다.
- 사전 fetch는 <Link> 태그에 prefetch={false}를 삽입하여 비활성화 할 수 있다.
Soft Navigation
탐색에서 변경된 segment에 대한 캐시는 재사용되며(있는경우에만) 서버에 대한 새로운 데이터 요청은 하지 않는다.
Condition for Soft Navigation
탐색에서 route가 사전 fetch 되었거나 동적 segment가 포함되지 않았거나, 현재 route와 동일한 동적 매개변수가 있는 경우 Next.js는 soft navigation을 사용한다.
예를 들면 동적인 [team] segment가 포함된 route를 보면 : /dashboard/[team]/*
/dashboard/[team]/* 아래에 캐시된 segment는 [team] 파라미터가 변경되는 경우에만 유효하지 않다.
(**[team] 파라미터가 변경되지 않는 경우만 캐시된 데이터를 사용할 수 있고, 이때는 soft navigation된다.)
- /dashboard/team-red/* 에서 /dashboard/team-red/* 로 이동할때는 soft navigation이다.
- /dashboard/team-red/* 에서 /dashboard/team-blue/* 로 이동할 때는 hard navigation이다.
Hard Navigation
탐색시 캐시가 무효화되고 서버가 데이터를 다시 가져와 변경된 segment를 리렌더링 한다.
Back/Forward Navigation
뒤로가기,앞으로가기 네비게이션(popstate event)은 soft navigation 동작을 한다. 즉, 클라이언트 측 캐시가 재사용되고 네비게이션이 즉시 실행된다.
Focus and Scroll Management
기본적으로 Next.js는 포커스를 설정하고 네비게이션 시 변경된 segment를 보기위해 스크롤한다.
Reference
- https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating
Routing: Linking and Navigating | Next.js
Using App Router Features available in /app
nextjs.org
'개인공부' 카테고리의 다른 글
Next.js Docs (6) Dynamic Routes (0) | 2023.06.20 |
---|---|
Next.js Docs (5) Route Groups (0) | 2023.06.16 |
Next.js Docs (3) Defining Routes, Pages and Layouts (0) | 2023.06.10 |
Next.js Docs (2) Routing Fundamentals (0) | 2023.06.07 |
Next.js Docs (1) React Essentials (0) | 2023.06.02 |
댓글