본문 바로가기

넥스트

[next.js] 3. Linking and Navigating :: next.js 에서의 라우트 간 이동법 ?

반응형

Next.js에서 라우트 간 이동하는 방법은 두 가지가 있습니다

 컴포넌트 사용
useRouter Hook 사용

이 페이지에서는 <Link>, useRouter()를 사용하는 방법을 설명하고, 또한 이동 작동 방식에 대해 더 자세히 살펴보겠습니다.

 

 <Link> 컴포넌트

<Link>는 내장된 컴포넌트로, HTML <a> 태그를 확장하여 라우트 간 사전 로딩 및 클라이언트 측 이동을 제공합니다. 이는 Next.js에서 라우트 간 이동을 위한 주요 방법입니다.


next/link에서 가져와서 컴포넌트에 href 속성을 전달하여 사용할 수 있습니다

// app/page.tsx
import Link from 'next/link';

export default function Page() {
  return <Link href="/dashboard">대시보드</Link>;
}

<Link>에 전달할 수 있는 다른 선택적 속성도 있습니다. 더 자세한 내용은 API 참조를 참조하세요.

 API 문서) https://nextjs.org/docs/app/api-reference/components/link

 

 예제

  동적 세그먼트로 링크 설정하기

동적 세그먼트로 링크를 설정할 때, 템플릿 리터럴과 보간을 사용하여 링크 목록을 생성할 수 있습니다. 예를 들어, 블로그 게시물 목록을 생성하는 방법은 다음과 같습니다:

// 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>
  );
}

 

 활성 링크 확인하기

usePathname()을 사용하여 링크가 활성인지 확인할 수 있습니다. 예를 들어, 현재 경로명이 링크의 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 === link.href;

        return (
          <Link
            className={isActive ? 'text-blue' : 'text-black'}
            href={link.href}
            key={link.name}
          >
            {link.name}
          </Link>
        );
      })}
    </>
  );
}

 

  id로 스크롤하기

Next.js 앱 라우터(appRouter)의 기본 동작은 새 경로로 스크롤하거나 뒤로 및 앞으로 이동할 때 스크롤 위치를 유지하는 것입니다.

특정 id로 스크롤하려면 URL에 # 해시 링크를 추가하거나 href 속성에 해시 링크를 전달할 수 있습니다. 이것은 <Link>가 <a> 요소로 렌더링되기 때문에 가능합니다.

<Link href="/dashboard#settings">설정</Link>

// 출력
<a href="/dashboard#settings">설정</a>
next.js 13 버전 부터는 Link 컴포넌트의 내부에 a 태그가 숨겨져 있어서 따로 속성으로 지정 할 필요가 없다고 한다. 본인은 12 버전을 써본 적이 없어서 어떤 상황인지는 잘 몰랐지만, 알아보니 그렇다고 하더라.

 

 스크롤 복원 비활성화하기

Next.js 앱 라우터의 기본 동작은 새 경로로 스크롤하거나 뒤로 및 앞으로 이동할 때 스크롤 위치를 유지하거나 스크롤 위치를 유지하는 것입니다. 이 동작을 비활성화하려면 <Link> 컴포넌트에 scroll={false}를 전달하거나 router.push() 또는 router.replace()scroll: false를 전달할 수 있습니다.

// next/link
<Link href="/dashboard" scroll={false}>
  대시보드
</Link>

// useRouter
import { useRouter } from 'next/navigation';
 
router.push('/dashboard', { scroll: false });

 

 useRouter() Hook

useRouter 훅을 사용하면 프로그래밍 방식으로 라우트를 변경할 수 있습니다.

 

이 훅은 클라이언트 컴포넌트 내에서만 사용할 수 있으며 next/navigation에서 가져옵니다.

// 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')}>
      대시보드
    </button>
  );
}

useRouter 메서드의 전체 목록은 API 참조를 참조하세요.

https://nextjs.org/docs/app/api-reference/functions/use-router
추천
특별한 요구 사항이 없다면 라우트 간 이동에는  컴포넌트를 사용하십시오. useRouter를 사용해야 하는 특별한 요구 사항이 없는 경우입니다.

 

 라우팅 및 이동 작동 방식

앱 라우터는 라우팅 및 이동에 하이브리드 접근 방식을 사용합니다. 서버에서는 애플리케이션 코드가 라우트 세그먼트별로 자동으로 코드 분할됩니다. 클라이언트에서는 Next.js가 라우트 세그먼트를 사전 로드하고 캐시합니다. 따라서 사용자가 새로운 경로로 이동할 때 브라우저는 페이지를 다시 로드하지 않으며 변경된 라우트 세그먼트만 다시 렌더링되어 탐색 경험과 성능이 향상됩니다.

(개인 정리) 쉽게 말해 클라이언트 측에서 사용자가 링크를 타고 다른 페이지로 이동할 떄 새로운 경로에 대한 페이지를 Next.js 측에서 사전에 로드 해두기 때문에 이동 시 해당 페이지 전체를 다시 로드하지 않고 변경된 부분만 재렌더링한다는 것

 

  사전 로드

사전 로드는 사용자가 해당 페이지를 방문하기 전에 미리 라우트를 백그라운드에서 로드하는 방식입니다.

 

○ Next.js에서 라우트가 사전 로드되는 방법은 다음과 같습니다

 <Link>컴포넌트: 라우트가 사용자 뷰포트에 표시되는 시점에서 자동으로 사전 로드됩니다. 사전 로드는 페이지가 처음 로드될 때 또는 스크롤을 통해 뷰에 나타날 때 발생합니다.
router.prefetch(): useRouter 훅을 사용하여 프로그래밍 방식으로 라우트를 사전 로드할 수 있습니다.

 

○ <Link>의 사전 로드 동작은 정적 및 동적 라우트에 따라 다릅니다

정적 라우트: prefetch 기본값은 true입니다. 전체 라우트가 사전 로드되고 캐시됩니다.
동적 라우트: prefetch 기본값은 automatic입니다. 공유 레이아웃이 로드되고 30초 동안 캐시됩니다. 이렇게 함으로써 전체 동적 라우트를 가져오는 비용을 줄이고 사용자에게 시각적 피드백을 제공하기 위한 즉각적인 로딩 상태를 표시할 수 있습니다.
prefetching을 비활성화하려면 prefetch prop을 false로 설정할 수 있습니다.

 

(개인 정리) 동적 라우트 부분에 대해서 예를 들면, 동적 라우트를 가지는 웹 페이지가 있다고 가정해볼 때, 사용자가 해당 페이지로 이동하려고 할 때, 페이지가 아직 로드되지 않았다면 사용자에게 로딩 상태를 보여주기 위해 먼저 공유 레이아웃(layout)만 로드하고 보여준다. 이후 페이지 컨텐츠는 필요한 시점에 로드되며, 이로써 전체 페이지를 로드하는 데 필요한 시간과 데이터 사용량을 줄일 수 있게 된다. 

 

알아둘 사항
개발 중에는 사전 로드가 활성화되지 않으며, 프로덕션에서만 활성화됩니다.

 

 캐싱

Next.js에는 Router Cache라고 하는 인메모리 클라이언트 측 캐시가 있습니다. 사용자가 앱 내에서 이동할 때, 사전 로드된 라우트 세그먼트의 React Server Component Payload와 방문한 라우트가 캐시에 저장됩니다.

 

이는 탐색 시에 가능한 한 캐시를 재사용하며, 서버로의 새로운 요청 수를 줄이고 데이터 전송량을 줄여 성능을 향상시킵니다.

(개인 정리) 리액트 서버 컴포넌트 페이로드에 대해서 잘 알지 못해서, 명확하게 정리하지는 못하겠으나, 간략하게 이해한 내용대로 정리해보면 사용자가 방문한 라우트에 대한 정보와 미리 전송받은 서버 데이터를 미리 캐시해 둠으로써 불필요한 데이터 중복 요청을 방지하여 성능을 향상시키고 있다라고 이해 된다.
(캐시 관련) https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#caching-data

 

 부분 렌더링

부분 렌더링은 탐색 시 변경되는 라우트 세그먼트만 클라이언트에서 다시 렌더링하고 공유 세그먼트는 유지하는 방식을 의미합니다.


예를 들어 두 개의 형제 라우트, /dashboard/settings 및 /dashboard/analytics 사이를 이동할 때, settings 및 analytics 페이지가 렌더링되고 공유되는 dashboard 레이아웃이 유지됩니다.

 

  부분 렌더링 작동 방식

부분 렌더링을 사용하지 않으면 각각의 탐색마다 서버에서 전체 페이지를 다시 렌더링합니다. 변경된 세그먼트만 렌더링하면 데이터 전송량과 실행 시간이 줄어들어 성능이 향상됩니다.

 

  소프트 네비게이션

기본적으로 브라우저는 페이지 간에 하드 네비게이션을 수행합니다. 즉, 브라우저는 페이지를 다시 로드하고 앱 내에서 useState 훅과 같은 React 상태, 사용자의 스크롤 위치 또는 초점된 요소와 같은 브라우저 상태를 재설정합니다.

 

그러나 Next.js에서는 앱 라우터가 소프트 네비게이션을 사용합니다. 즉, React는 변경된 세그먼트만 렌더링하며 React 및 브라우저 상태를 유지하며 전체 페이지를 다시 로드하지 않습니다.

(개인 정리) 이건 기본적인 내용인 듯하다. 일반적인 브라우저는 페이지 이동하면 전체 페이지가 모두 재렌더링(하드 네비게이션)되기 때문에 반짝거리는 현상이 발생하는데, 리액트와 next.js 는 브라우저의 상태를 변동된 내용에 대해서만 렌더링(소프트 네비게이션)하고 변동이 없는 것은 이전 상태와 동일하게 유지 하기 때문에 여러모로 성능이슈 문제를 개선하고 있음을 말하는 듯 하다.

 

  뒤로 및 앞으로 이동

기본적으로 Next.js는 뒤로 및 앞으로 이동할 때 스크롤 위치를 유지하고 라우트 세그먼트를 Router Cache에서 다시 사용합니다.

 


(마무리 말) 이번 챕터에서 제일 흥미로웠던 점은 사용자의 뷰포트에 Link 컴포넌트가 보이는 순간 해당 Link 와 연결되어 있는 페이지 컴포넌트가 사전로드 된다는 사실이다. 물론 개발모드에서는 실행되지 않기에 직접 확인하려면 배포모드에서 확인해야 한다.

. Next.js 는 전반적으로 성능 최적화를 위한 다양한 기능들을 구비해두고 있다는 점이 많이 보인다. 아직 살펴보지는 않았지만, image 나 font 또한 최적화된 상태로 활용할 수 있는 옵션이 존재한다고 한다. 원래라면 일일이 라이브러리를 설치하고 해야 했던 전반적인 기능들을 거의 다 구비되어 있는 것으로 보이고, 사용하는 방법만 따라주면 즉시 적용할 수 있으니, 왜 리액트의 프레임워크 라고 하는지 단편적으로나마 이해할 수 있었다.
반응형

'넥스트' 카테고리의 다른 글

[next.js] 5. 동적 라우팅  (0) 2023.08.27
[next.js] 4. Route Groups  (0) 2023.08.26
[next.js] 2. 페이지와 레이아웃  (0) 2023.08.26
[next.js] 1. 라우팅 경로 정의  (0) 2023.08.26
[next.js] CSR(Clinet Side Rendering)  (0) 2023.04.01