Skill/Next.js

[Next.js 14] 1. Routing - 2

뜸부깅 2025. 2. 3. 23:42
반응형

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.pushStatewindow.history.replaceState의 사용을 허용하며 새로고침 없이 history stack을 관리.
  • 이렇게 관리된 history stack은 usePathnameuseSearchParams 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 사용하면서 처음 본 개념이거나, 이해하기 어려운 부분(?)은 붉은색 볼드처리 해봤다.

  1. redirect: Server Components에서 사용할 수 있는 redirect 함수라는데, Server Components에 대해서 모르는게 많다..
  2. server action: 서버 측에서 실행시킬 함수를 정의하는 것이라는데, 해당 실행 위치가 React Component란다. 뭐지? 어떻게 가능해?
  3. router cache: 개념적으로는 이해가 간다. Route 간 캐시를 저장하는 공간 개념인 것 같은데, 공식문서 내용이 상당히 길더라. 계속 보다보면 뭐가 나오겠지..?

Preference

 

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