230607.til

Universe·2023년 6월 7일
0

Linking and Navigating

Next.js의 라우터는 'server-centric routing'과 'client-side navigation'이라는 두 가지 방식을 사용한다.

13버전 이후로는 'server-centric routing'을 주로 사용하게 되는데 이러한 라우팅 구조는 서버 컴포넌트와 data fetching 을 중점적으로 수행한다.
또한, 같은 경로로 같은 라우트 요청이 올 때마다 다운로드를 새로 받을 필요 없도록 최적화 되어있다.
서버 중심의 라우팅이 이루어 지지만, Link 컴포넌트를 이용해 클라이언트 사이드에서 이동하는 것 처럼 작동한다는 이야기.

아래와 같은 매커니즘을 가지고 있다.

  1. Link 컴포넌트: Next.js는 Link 컴포넌트를 통해 클라이언트 사이드 라우팅을 지원한다. 해당 컴포넌트는 클릭시 브라우저가 새로운 페이지를 로드하지 않는다. 대신, Next.js 자체에서 새로운 URL로 이동하려 할 때 해당 페이지를 동적으로 로드하고 렌더링한다.
  2. 동적 임포트: Next.js는 코드 스플리팅과 동적 임포트를 사용하여 필요한 컴포넌트만 로드한다.
  3. 브라우저 히스토리 API: 브라우저 히스토리 API를 사용하여 URL을 변경하며, 이로 인해 페이지가 다시 로드되지 않고 URL만 변경된다.
  4. SSR, SSG: 사용자가 새로운 페이지로 이동할 때마다 해당 페이지를 서버에서 렌더링하거나 미리 생성된 정적 페이지를 제공한다. 클라이언트에서 렌더링을 수행할 필요가 없으므로 성능이 향상된다.
import Link from 'next/link'

export default function Page(){
	return <Link href="/about">About</Link>
}

Link 컴포넌트의 기본적인 사용법은 위와 같다.
prefetch 기능을 내장하고 있으며, 링크에 마우스를 올리는 순간 해당 페이지를 백그라운드에서 미리 로드하고,
사용자가 Link 를 클릭했을 때 즉시 표시할 수 있도록 하여 빠르고 부드러운 UX 를 제공한다.

import Link from 'next/link'

export default function Blog({ posts }) {
  return (
    <div>
      <h1>My Blog</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <Link href={`/posts/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

위와 같이 동적 라우팅을 위해 사용할 수도 있다.
예시는 posts 배열을 받아와서 id로 동적 URL 경로로 Link 를 생성하는 예시.

Link 컴포넌트의 기본 동작은 ‘클릭했을 때 URL segment의 최상단으로 스크롤한다’ 이지만
href 에 id를 정의함으로 써 일반적인 a 태그 처럼 특정 위치로 스크롤 할 수 있다.
예를들어 한 페이지 내에,

<div>
  <div id="section1">Section 1</div>
  <div id="section2">Section 2</div>
  <div id="section3">Section 3</div>
</div>

같은 section 이 나뉘어져 있다면,

<Link href="#section2">section2 로 이동하는 링크</Link>

처럼 사용할 수 있다.
이 경우, scroll 옵션을 false 로 설정하는 것으로 페이지 위치를 유지하고 URL 만 변경할 수도 있다.

<Link href="#section2" scroll={false}>URL 만 변경하는 링크</Link>

useRouter()

Link 태그를 사용하는 것 이외에도 useRouter Hook 을 사용할 수도 있다.
hook 의 사용은 클라이언트 컴포넌트에서만 가능함에 주의할 것.
기본적으로는 아래와 같이 사용한다.

'use client';
 
import { useRouter } from 'next/navigation';
 
export default function Page() {
  const router = useRouter();
 
  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  );
}

Soft Navigation, Hard Navigation

“새로운 데이터 요청이 이루어 지는가?” 의 기준으로 Navigation 방식의 차이를 설명할 수 있다.
Soft Navigation 은 URL 이 변경되더라도 캐시된 브라우저 히스토리를 재사용함으로써 서버에 새로운 데이터 요청을 하지 않는다. prefetch 되어있거나, 현재 라우트와 동일한 URL 파라미터를 가지고 있을 때 시행된다.
반면에, Hard Navigation 은 캐시가 무효화 되고 서버에서 다시 데이터를 가져오는 방식이다.

예를들어,
/dashboard/[team]/* 에서
/dashboard/[team]/* 아래의 캐시된 세그먼트들은 [team] 파라미터가 바뀔 때만 무효화된다. 따라서, /dashboard/team-red/*에서 /dashboard/team-red/*로 이동하는 것은 Soft Navigation이 되지만, /dashboard/team-red/*에서 /dashboard/team-blue/*로 이동하는 것은 Hard Navigation이 된다.

추가적으로 앞으로, 뒤로 가는 popstate event 는 soft navigation 방식으로 작동한다.

Route Group

URL 경로에 영향을 미치지 않으면서 체계적으로 라우팅을 조직화 할 수 있다.

위와 같이 설정하면 (marketing)이나 (shop) 등과 같은 ‘라우트 그룹 내에서 공유되는 URL 계층 구조’에도 불구하고 각 그룹에 layout.js 파일을 추가함으로써 각 그룹에 대해 서로 다른 레이아웃을 생성할 수 있다.

서로 다른 root layout 을 설정할 수도 있는데,
최상위 layout 파일을 제거하고 각 route group 내에 layout 파일을 추가하면 된다.
root layout 은 반드시 html, body 태그가 포함되어야 함에 주의할 것.

또한, route group 간 라우팅의 이동이 발생하면 네비게이션이 일어나는 대신 전체적인 페이지 로드가 발생한다.
과도하게 route group 간 root layout 을 설정하게 될 경우 애플리케이션의 전반적인 성능에 영향을 미칠 수 있다. 따라서, “특정 부분이 완전히 다른” UI 를 제공해야 할 때 적절하게 사용할 수 있다.

profile
Always, we are friend 🧡

0개의 댓글