[Next.js] Linking과 Navigating

파이리·2023년 7월 27일
0

Next.js

목록 보기
5/18
post-thumbnail

Next.js 라우터는 클라이언트 측 navigating과 서버 중심 라우팅을 사용합니다. 즉각적인 로딩 상태와 동시 랜더링을 지원합니다. 즉, navigating은 클라이언트 측 상태를 유지하고 비용이 많이 드는 리랜더링을 피하고, 중단이 가능하며 race condition을 일으키지 않습니다.

Navigaiting을 하는 방법은 두 가지가 제공됩니다.

  • <Link> 컴포넌트

  • useRoute


<Link> 컴포넌트는 HTML의 <a> 태그를 확장하여 라우트 간 prefetching과 클라이언트 측 navigation을 제공합니다. Next.js에서 navigating을 하는 주요 방법입니다.

<Link> 컴포넌트를 사용하기 위해서는 next/link에서 컴포넌트를 import한 뒤, herf 프로퍼티을 전달하면 됩니다.

import Link from 'next/link'
 
export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}

props

  • href

이동할 경로 혹은 URL입니다.

tpyerequired
String or Objecttrue
<Link
  href={{
    pathname: '/about',
    query: { name: 'test' },
  }}
>
  About
</Link>

  • replace

기본값은 false입니다. true로 지정하면 next/link는 현재 History 상태 스택에 새로운 URL을 추가하는 대신 현재 History 상태를 대체합니다.

tpyerequired
booleanfalse
import Link from 'next/link'
 
export default function Page() {
  return (
    <Link href="/dashboard" replace>
      Dashboard
    </Link>
  )
}

  • prefetch

기본값은 true 입니다. true인 경우, next/link는 백그라운드에서 페이지를 미리 가져오게 됩니다. 이는 클라이언트 측 navigating 성능을 개선하는데 유용합니다. 뷰포트이 모든 <Link>는 미리 로드됩니다.

tpyerequired
booleanfalse
import Link from 'next/link'
 
export default function Page() {
  return (
    <Link href="/dashboard" prefetch={false}>
      Dashboard
    </Link>
  )
}

동적 Segments 연결하기

동적 Segments에 연결할 때, 탬플릿 리터럴 등을 사용하여 링크 목록을 생셩할 수 있습니다.

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()을 사용하여 링크가 활성 상태인지 확인할 수 있습니다.

'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.startsWith(link.href)
 
        return (
          <Link
            className={isActive ? 'text-blue' : 'text-black'}
            href={link.href}
            key={link.name}
          >
            {link.name}
          </Link>
        )
      })}
    </>
  )
}

Id로 스크롤하기

<Link>의 기본 동작은 변경된 route segment의 상단으로 스크롤하는 것입니다. 이때 herf에 정의된 ID가 있다면 일반 <a> 태그와 유사하게 특정 ID로 스크롤 됩니다.


useRouter() 훅

useRouter 훅은 사용하면 클라이언트 컴포넌트 내에서 프로그래밍 방식으로 라우트를 변경할 수 있습니다. useRouter를 사용하려면 next/navigation에서 import 한 후, 클라이언트 컴포넌트 내부에서 사용하면 됩니다.

'use client'
 
import { useRouter } from 'next/navigation'
 
export default function Page() {
  const router = useRouter()
 
  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}
  • router.push(herf : string) : 제공된 라우트로 클라이언트 측 navigating을 수행합니다. 브라우저의 히스토리 스택에 새 항목을 추가합니다.

  • router.replace(herf : string) : 브라우저의 히스토리 스택에 새 항목을 추가하지 않고 제공된 경로로 클라이언트 측 탐색을 수행합니다.

  • router.refresh() : 현재 경로를 새로 고칩니다. 서버에 새 요청을 하고, 데이터 요청을 다시 가져오고, 서버 컴포넌트를 다시 랜더링합니다. 클라이언트는 영향을 받지 않는 클라이언트 측 React 상태 또는 브라우저 상태를 잃지 않고 업데이트된 React 서버 컴포넌트 페이로드와 병합합니다.

  • router.back() : soft navigation을 사용하여 브라우저의 히스트리 스택에서 이전 경로로 이동합니다.

  • router.forward() : soft navigation을 사용하여 브라우저의 히스트리 스택에서 다 경로로 이동합니다.


<Link>를 사용하거나 router.push()를 호출하여 경로 전환이 시작됩니다.

라우터는 브라우저 주소 표시줄에서 URL을 업데이트합니다.

라우터는 클라이언트 측 캐시에서 변경되지 않은 세그먼트를 재사용하여 불필요한 작업을 피합니다. 이를 부분 랜더링이라고 합니다.

soft navigation 조건이 충족되면 라우터는 서버가 아닌 캐시에서 새 새그먼트를 가져옵니다. 그렇지 않은 경우 라우터는 hard navigation을 수행하고 서버에서 컴포넌트 페이로드를 가져옵니다.

생성된 경우 페이로드를 가져오는 동안 서버에서 로딩 UI가 표시됩니다.

라우터는 캐시된 페이로드 또는 새로운 페이로드를 사용하여 클라이언트에서 새 새그먼트를 랜더링합니다.

랜더링된 서버 컴포넌트의 클라이언트 측 캐싱

새 라우터에는 서버 컴포넌트의 랜더링 결과를 저장하는 인메모리 클라이언트 측 캐시가 있습니다. 캐시는 route segments 별로 분할되어 어느 수준에서든 무효화가 가능하며 동시 랜더링 전반에서 일관성을 보장합니다.

사용자가 앱을 탐색할 때 라우터는 이전에 가져온 세그면트와 미리 가져온 세그먼트의 페이로드를 캐시에 저장합니다.

즉, 특정 경우에 라우터는 서버에 새로 요청하는 대신 캐시를 재사용할 수 있습니다. 이렇게 하면 데이터를 다시 가져오고 불필요한 컴포넌트를 다시 랜더링하지 않아도 되므로 성능이 향상됩니다.

캐시 무효화

Server Action은 경로 또는 캐시 태그를 기준으로 온디맨드 데이터를 재검증할 수 있습니다.

Prefetching

Prefetching은 라우트에 방문하기 전에 백그라운드에서 미리 로드하는 방식입니다. prefetching 된 경로의 랜더링 겨로가는 클라이언트 측 캐시에 추가됩니다. 이렇게 하면 prefetching된 경로로 거의 즉시 이동할 수 있습니다.

기본적으로 라우트는 <Link> 컴포넌트를 사용할 때 뷰포트에 표시되는 대로 Prefetching됩니다. 페이지가 처음 로드될 때, 스크롤할 떄 발생할 수 있습니다. useRouter() 훅의 prefetch 메서드를 사용하여 프로그래밍 방식으로 라우트를 Prefetching 할 수 있습니다.

라우트가 정적 라우트인 경우, Route Segment에 대한 모든 서버 컴포넌트 페이로드가 프리패치 됩니다.

라우트가 동적 라우트인 경우, 첫 번쨰 공유 레이아웃부터 첫 번째 loading.js 파일까지 페이로드가 프리패치됩니다. 이렇게 하면 전체 라우트를 동적으로 프리패치하는 데 드는 비용이 줄어들고 동작 라우트에 대한 로딩 상태를 즉시 확인할 수 있습니다.

Soft Navigation

내비게이션에서 변경된 세그먼트에 대한 캐시가 재사용되며 서버에 새로운 데이터를 요청합니다.

탐식 시 탐색 중인 라우트에 동적 세그먼트가 포함되어 있지 않거나 현재 경로와 동일한 동적 매개변수 있는 경우 Next.js는 Soft Navigation을 사용합니다.

Hard Navigation

탐색 시 캐시가 무효화되고 서버가 데이터를 새로 고침하여 변경된 세그먼트를 다시 랜더링됩니다.

Back / Forward Navigation

뒤로 / 앞으로 탐색은 Soft Navigaton으로 동작합니다. 즉, 클라이언트 측 캐시가 재사용되고 즉각적으로 이동합니다.

Focus와 Scroll 관리

기본적으로 Next.js 탐색에서 변경된 세그먼트를 보기 위해 포커스를 설정하고 스크롤합니다.

profile
프론트엔드 개발자

0개의 댓글