Next.js 라우터는 클라이언트 측 탐색과 함께 서버 중심 라우팅을 사용합니다. 즉각적인 로딩 상태 및 동시 렌더링을 지원합니다. 이는 내비게이션이 클라이언트 측 상태를 유지하고 비용이 많이 드는 재 렌더링을 피하며, 중단 가능하며, 경쟁 조건을 발생시키지 않는다는 것을 의미합니다.
라우트 간 이동하는 두 가지 방법이 있습니다:
- <Link> 컴포넌트
- useRouter 훅
<Link> 컴포넌트
<Link>은 Next.js에서 라우트 간 이동을 위한 주요 방법입니다.
<Link>은 HTML <a> 요소를 확장하여 라우트 간의 사전 로드(prefetching)와 클라이언트 측 탐색을 제공하는 React 컴포넌트입니다. <Link>를 사용하려면 next/link에서 가져와서 컴포넌트에 href 속성을 전달하세요:
/* app/page.tsx */
import Link from 'next/link';
export default function Page() {
return <Link href="/dashboard">Dashboard</Link>;
}
<Link>에 전달할 수 있는 props를 보려면 API를 참조하세요.
Example
동적 세그먼트에 Linking 하기
동적 세그먼트에 링크를 생성할 때, 템플릿 리터럴과 보간을 사용하여 링크 목록을 생성할 수 있습니다. 예를 들어, 블로그 게시물 목록을 생성하려면 다음과 같이 할 수 있습니다:
/* app/blog/PostList.jsx */
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()을 사용하여 링크가 활성 상태인지 확인할 수 있습니다. 예를 들어 활성 링크에 클래스를 추가하려면 현재 경로 이름이 링크의 href와 일치하는지 확인할 수 있습니다.
특정 id로 스크롤하기
<Link>의 기본 동작은 변경된 route 세그먼트의 맨 위로 스크롤하는 것입니다. href에 정의된 id가 있으면 일반 <a> 태그와 마찬가지로 특정 id로 스크롤됩니다.
route 세그먼트의 맨 위로 스크롤되는 것을 방지하려면 scroll={false}를 설정하고 hashed id를 href에 이으면 됩니다.
useRouter() Hook
useRouter hook을 사용하면 클라이언트 구성 요소 내에서 프로그래밍 방식으로 경로를 변경할 수 있습니다
useRouter를 사용하려면 next/navigation에서 import 하고 클라이언트 컴포넌트 내부에서 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>
);
}
useRouter는 push(), refresh() 등과 같은 메서드를 제공합니다. 자세한 내용은 API reference을 읽어주세요
권장 사항: 특정 요구 사항이 없는 한 useRouter대신 <Link> 컴포넌트를 사용해 주세요
Navigation 작동 방식
- <Link> 또는 router.push()를 사용하여 경로 전환을 시작합니다.
- 라우터는 브라우저 주소 표시줄의 URL을 업데이트합니다.
- 라우터는 변경되지 않은 세그먼트(예: 공유 레이아웃)를 클라이언트 측 캐시에서 재사용함으로써 불필요한 작업을 피합니다. 이를 부분 렌더링이라고도 합니다.
- 소프트 내비게이션의 조건이 충족되면, 라우터는 서버가 아닌 캐시에서 새로운 세그먼트를 가져옵니다. 그렇지 않으면, 라우터는 하드 내비게이션을 수행하고 서버에서 서버 컴포넌트 페이로드를 가져옵니다.
- 로딩 UI가 생성된 경우, 서버에서 페이로드를 가져오는 동안에는 로딩 UI가 표시됩니다.
- 라우터는 캐시 된 페이로드 또는 새로운 페이로드를 사용하여 클라이언트에서 새 세그먼트를 렌더링 합니다.
렌더링 된 서버 컴포넌트의 클라이언트 측 캐싱
알아두면 좋은 정보: 이 클라이언트 측 캐시는 서버 측 Next.js HTTP 캐시와 다릅니다.
- 새로운 라우터에는 서버 컴포넌트(payload)의 렌더링 결과를 저장하는 클라이언트 측 인메모리 캐시가 있습니다. 이 캐시는 라우트 세그먼트별로 분리되어 있어 어느 수준에서든 무효화가 가능하며, 동시에 렌더링 되는 상황에서 일관성을 보장합니다.
- 사용자가 앱을 탐색할 때 라우터는 이전에 가져온 세그먼트와 미리 가져온 세그먼트의 페이로드를 캐시에 저장합니다. 이는 특정 경우에 라우터가 서버에 새로운 요청을 보내지 않고 캐시를 재사용할 수 있다는 것을 의미합니다. 이는 데이터를 다시 가져오거나 컴포넌트를 불필요하게 다시 렌더링 하는 것을 피함으로써 성능을 향상합니다.
캐시 무효화
Server Actions는 경로(revalidatePath) 또는 캐시 태그(revalidateTag)의 on-demand 데이터를 재검증하는 데 사용할 수 있습니다.
Prefetching
프리페칭은 방문하기 전에 백그라운드에서 라우트를 사전로드하는 방법입니다. 프리페칭된 라우트의 렌더링 결과는 라우터의 클라이언트 측 캐시에 추가됩니다. 이를 통해 프리페칭된 라우트로의 이동이 거의 즉시 가능해집니다.
기본적으로, <Link> 컴포넌트를 사용할 때 뷰포트에 표시되는 시점에 라우트가 프리페치됩니다. 이는 페이지가 처음로딩될 때나 스크롤링을 통해 발생할 수 있습니다. 라우트는 또한 useRouter() 훅의 prefetch 메서드를 사용하여 프로그래밍적으로 프리페치할 수도 있습니다.
정적 및 동적 경로:
- 만약 라우트가 정적이라면, 해당 라우트 세그먼트의 모든 서버 컴포넌트 페이로드가 프리페치됩니다.
- 만약 라우트가 동적이라면, 첫 번째 공유 레이아웃부터 첫 번째 loading.js 파일이 나올 때까지의 페이로드가 프리페치됩니다. 이렇게 함으로써 동적으로 전체 라우트를 프리페치하는 비용을 줄이고 동적 라우트에 대한 즉시 로딩 상태를 가능하게 합니다.
알아두면 좋은점:
- 프리페치는 프로덕션에서만 활성화됩니다.
- prefetch={false}를 <Link>에 전달하여 미리 가져오기를 비활성화할 수 있습니다.
Soft Navigation
내비게이션 시 변경된 세그먼트의 캐시가 있는 경우 재사용되며, 서버에 데이터를 새로 요청하지 않습니다.
Soft Navigation 조건
Next.js에서는 네비게이션 시, 프리페치된 라우트로 이동하는 경우에만 소프트 내비게이션을 사용합니다. 또한, 이동하는 라우트에 동적 세그먼트가 없거나 현재 라우트와 동일한 동적 매개변수를 가지고 있는 경우에도 소프트 네비게이션을 사용합니다.
예를 들어, 다음과 같은 동적 [team] 세그먼트를 포함하는 경로를 고려해 보겠습니다: /dashboard/[team]/**.*
/dashboard/[team]/* 아래의 캐시 된 세그먼트는 [team] 매개변수가 변경될 때에만 무효화됩니다.
- /dashboard/team-red/* 에서 /dashboard/team-red/* 로 이동하는 경우 소프트 내비게이션이 됩니다.
- /dashboard/team-red/* 에서 /dashboard/team-blue/* 로 이동하는 경우 하드 네비게이션이 됩니다.
Hard Navigation
네비게이션 시 캐시는 무효화되고 서버는 데이터를 다시 가져와 변경된 세그먼트를 다시 렌더링 합니다
Back/Forward Navigation
뒤로 및 앞으로 내비게이션시(popstate 이벤트)에는 소프트 탐색 동작이 있습니다. 즉, 클라이언트 측 캐시가 재사용되고 내비게이션이 거의 즉각적입니다.
요약&느낀 점
- 문서를 정리하다가 페이로드의 정의를 모르고 있다는 것을 깨닫고 조사해 봤습니다. 서버 컴포넌트의 페이로드는 Next.js에서 렌더링 된 결과물을 말합니다. 즉, 서버 측에서 생성된 컴포넌트를 클라이언트로 전송하는 데이터입니다. 이는 페이지의 HTML 콘텐츠와 클라이언트 측에서 실행되는 JavaScript 코드 등을 포함할 수 있습니다.
- 페이로드는 네트워크를 통해 전송되는 데이터의 일부입니다. 일반적으로, 페이로드는 요청에 대한 응답으로 받는 데이터를 의미합니다. 이 데이터는 주로 클라이언트에게 필요한 정보를 포함하고 있으며, 예를 들어 HTML, JSON, 이미지, 오디오 파일 등이 될 수 있습니다.
- 세그먼트의 프리패치 자동 적용을 위해 useRouter() 훅을 이용한 경로 이동보다는 <Link/> 컴포넌트를 사용하는 것이 코드 최적화에 더 좋아 보입니다. useRouter()의 prefetch 메서드를 사용해 적용할 수 있지만 이는 개발자가 프리패치에 관한 코드를 수동으로 입력해야 하는 번거로움이 있습니다.
- NextJS의 내비게이션 작동 방식을 내재적으로 깔고 들어가면 최적화된 서비스 개발을 쉽게 할 수 있을 것으로 보입니다.
참조
'기억보단 기록을 > Next JS (App Router)' 카테고리의 다른 글
[NextJS 13] Routing - Dynamic Routes (0) | 2023.06.06 |
---|---|
[NextJS 13] Routing - Route Groups (0) | 2023.06.04 |
[NextJS 13] Routing - Pages and Layouts (1) | 2023.05.31 |
[NextJS 13] Routing - Defining Routes (0) | 2023.05.30 |
[NextJS 13] Routing - Routing Fundamentals (0) | 2023.05.30 |