반응형
3. Linking and Navigating
- Next.js에서 route 간 네비게이션 방법에는 4가지가 존재.
1. <Link>
2. useRouter hook (Client Components)
3. redirect function (Client Components)
4. History API
3-1. Link Component
- HTML <a> 태그를 확장한 내장 컴포넌트로 prefetching과 client-side에서 route 간 네비게이션 기능 제공.
prefetching: 사용자가 방문하기 전에 background에서 해당 페이지의 정적 데이터 (JS, CSS 등)를 미리 로드하는 것.
1. Link Component: 컴포넌트가 사용자 ViewPort 내 들어오면, prefetching 수행.
2. router.prefetch(): useRouter 훅을 이용해 직접 prefetching 수행.
- Next.js에서 Route 시 권장되는 방법.
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export function Links() {
const pathname = usePathname() // client component hook.
return (
<nav>
<ul>
<li>
<Link className={`link ${pathname === '/' ? 'active' : ''}`} href="/">
Home
</Link>
</li>
<li>
<Link
className={`link ${pathname === '/about' ? 'active' : ''}`}
href="/about"
>
About
</Link>
</li>
</ul>
</nav>
)
}
- 기본적인 사용 방법.
<Link href="/dashboard#settings">Settings</Link>
// Output
<a href="/dashboard#settings">Settings</a>
- Next.js의 App Router는 기본적으로 새로운 route로 이동 시 최상단으로 이동하고, 앞 뒤로 이동할 때 스크롤 위치를 유지.
이 기본 동작을 비활성화 하려면 아래와 같은 방법이 가능.
1. Link: scroll props false 지정.
2. useRouter: router 객체의 push or replace 함수의 두 번째 인자에 {scroll: false} 옵션 지정.
- 특정 위치로 이동시키고 싶다면, hash link # 를 사용. viewport 내 보이지 않는다면, 해당 위치로 스크롤 된다.
3-2. useRouter hook
- Client Components에서 프로그래밍 적으로 router를 컨트롤할 수 있는 훅.
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter() // Client Components hook.
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
- 공식 문서 상에선 웬만하면 Link Component 사용을 권장한다.
3-3. redirect fucntion
- Server Components에서 사용할 수 있는 route 방법.
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}
// ...
}
1. redirect는 기본적으로 307 status code를 반환하는데, server action 에서 사용하면 303 status code를 반환 (새로 고침 시 중복 제출 방지로 POST/PUT -> GET 메소드로 Client 측에서 redirect를 위함.)
2. redirect는 내부적으로 에러가 발생하므로 try/catch 외부에서 사용. (흐름 제어를 위해 일부러 에러를 발생시킴 -> redirect 이후 코드가 실행 될 확률이 0이므로 redirect 과정이 성공적으로 수행.)
3. 렌더링 전에 redirect 실행을 원하면, next.config.js or Middleware를 사용.
3-4. History API
- Next.js는 window.history.pushState와 window.history.replaceState의 사용을 허용하며 새로고침 없이 history stack을 관리.
- 이렇게 관리된 history stack은 usePathname과 useSearchParams hook과 동기화 된다.
'use client'
import { useSearchParams } from 'next/navigation'
export default function SortProducts() {
const searchParams = useSearchParams()
function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString()) // 현재의 searchParams
params.set('sort', sortOrder) // sort params 추가.
window.history.pushState(null, '', `?${params.toString()}`) // history 상태 추가.
}
return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}
3-5. Routing과 Navigation 동작 원리
- App Router에서 Server Components는 자동으로 Code Spliting이 발생하고, 이를 prefetching 하여 cache.
- Client Components는 <Link> component의 prefetch prop에 true를 지정해야 prefetching.
- 단, <Link> component의 prefetch prop이 null or undefined이 지정된 경우 (= Server Components의 경우) loading.js와 함께 사용될 때, 공유 레이아웃과 loading Component만 prefetching이 발생하고 해당 Server Components는 접근한 뒤, 30초간 캐싱된다.
요기가 좀 헷갈릴 수 있는데, 정리하자면 아래와 같다.
1. <Link> 컴포넌트의 prefetch prop은 Client Component를 사용할 때 true 지정.
2. 이 말은, Server Component인 경우는 <Link> 컴포넌트의 prefetch prop은 undefined or null.
3. Server Component page가 prefetching 되어 cache를 통해 제공될 수 있다. (1번 경우.)
4. Server Component page가 loading.js와 함께 사용되면, prefetching 되어 cache를 통해 제공될 수 없다.(2번 경우.)
4-1. 대신, loading 컴포넌트와 공유 레이아웃이 prefetching되어 제공된다.
4-2. loading이 끝난 뒤, Server Component는 30초간 cache 되어 제공된다.
- development 모드에서는 prefetching 기능이 제공되지 않는다고 한다~~
- Next.js는 client side의 in memory cache인 Router Cache가 있는데 사용자가 App을 둘러 볼 때, Server Component에 대한 정보를 저장하고 이를 제공하여 성능을 높인다.
- 레이아웃을 공유하는 세그먼트들은 전체 레이아웃이 재 렌더링되지 않고, 해당 세그먼트들만 부분렌더링이 발생.
- 페이지간 Navigation 시 Soft Navigation 방식을 사용해서 React state를 유지시킨다. (?!!!!?!? next 12버전에는 없는 기능이란다.)
처음 뵙겠습니다.
Next.js 사용하면서 처음 본 개념이거나, 이해하기 어려운 부분(?)은 붉은색 볼드처리 해봤다.
- redirect: Server Components에서 사용할 수 있는 redirect 함수라는데, Server Components에 대해서 모르는게 많다..
- server action: 서버 측에서 실행시킬 함수를 정의하는 것이라는데, 해당 실행 위치가 React Component란다. 뭐지? 어떻게 가능해?
- router cache: 개념적으로는 이해가 간다. Route 간 캐시를 저장하는 공간 개념인 것 같은데, 공식문서 내용이 상당히 길더라. 계속 보다보면 뭐가 나오겠지..?
Preference
- https://parkgang.github.io/blog/2023/07/15/how-nextjs-prefetch-work/
- https://nextjs.org/docs/14/app/building-your-application/routing/linking-and-navigating
Next.js의 prefetch는 어떻게 동작하는가? | parkgang.log
Next.js 에서 prefetch 를 사용하면 미리 데이터가 로드되어 페이지 로드 시간이 단축된다는데 꼭 Next.js 의 Link 컴포넌트가 아니면 달성이 불가능한 것인가? SSR 인 경우는 어떻게 되는가? 미리 불러오
parkgang.github.io
Routing: Linking and Navigating | Next.js
Learn how navigation works in Next.js, and how to use the Link Component and `useRouter` hook.
nextjs.org