NextJS - Routing/Linking and Navigating

Hunter Joe·2025년 1월 30일

Next.js에는 4가지 네비게이션 방법이 존재한다.

📌<Link> Component

  • <Link><a>를 확장한 built-in 컴포넌트이다.
  • 라우트 간 prefetching 그리고 클라이언트 측 네비게이션을 제공한다.

Good to Know
<a>태그의 className이나 target="_blank"같은 속성은 <Link>의 props로 추가할 수 있으며, 내부의 <a> 요소로 전달된다.

EX

  • className<a> 요소에 적용되어 파란색 링크 스타일 적용
  • target="_blank" : 새 탭에서 링크가 열리도록 설정된다.
import Link from 'next/link';

export default function Example() {
  return (
    <div>
      <h2>Next.js Link Example</h2>
      <Link href="https://www.google.com" className="text-blue-500 underline" target="_blank">
        Open Google in New Tab
      </Link>
    </div>
  );
}
// 코드를 실행하면 <Link>컴포넌트가 내부적으로 <a>태그를 생성하고, 해당 속성을 전달한다. 

Reference

href(required)

import Link from 'next/link'
 
// Navigate to /about?name=test
export default function Page() {
  return (
    <Link
      href={{
        pathname: '/about',
        query: { name: 'test' },
      }}
    >
      About
    </Link>
  )
}

replace(optional)

  • Default 값은 false
  • true로 설정하면 브라우저의 히스토리 스택에 새로운 URL을 추가하는 대신 현재 히스토리 상태를 대체

기본적으로<Link>를 사용해 페이지를 이동하면 브라우저의 히스토리 스택에 새 URL이 추가된다.
하지만 replace={true}를 설정하면 기존 URL을 대체하고 새로운 히스토리 항목을 추가하지 않는다.
즉, 뒤로가기 버튼을 눌러도 이전 페이지로 돌아갈 수 없게 된다.
replace는 이전 URL이 필요 없을 때 사용하면 적절!

import Link from 'next/link';

export default function Example() {
  return (
    <div>
      <h2>Replace Example</h2>
      <Link href="/new-page" replace={true}>
        Go to New Page (Replace)
      </Link>
    </div>
  );
}

scroll

  • Default 값은 true
  • 새 페이지로 이동할 때, 해당 페이지가 뷰포트(화면)에 보이는 경우 스크롤 위치가 그대로 유지
  • 페이지가 화면에 보이지 않는 경우, Next.js는 페이지의 첫 번째 요소로 자동 스크롤(최상단)
  • false로 설정하면, 페이지 이동 시 첫 번째 요소로 자동 스크롤하지 않는다.
import Link from 'next/link'
 
export default function Page() {
  return (
    <Link href="/dashboard" scroll={false}>
      Dashboard
    </Link>
  )
}

prefetch

  • Default 값은 null
  • <Link>컴포넌트가 사용자의 뷰포트에 진입할 때 Next.js는 해당 링크의 href경로와 관련된 데이터르를 백그라운드에서 미리 불러온다.
  • 이를 통해 네비게이션 성능을 향상시킬 수 있다.
  • 프리페칭은 프로덕션 환경에서만 활성화된다.
  • true로 설정할 경우, 정적 및 동적 경로 모두 전체 페이지와 모든 데이터를 프리페칭
  • false 프리페칭이 완전히 비활성화
import Link from 'next/link'
 
export default function Page() {
  return (
    <Link href="/dashboard" prefetch={false}>
      Dashboard
    </Link>
  )
}

prefetching이 개발 환경에서 비활성 되는 이유

📌useRouter() hook

  • useRouter훅을 사용하면 프로그래밍 방식으로 클라이언트 구성요소를 변경할 수 있다.

    프로그래밍 방식이란 사용자가 직접 링크를 클릭하지 않아도 코드에서 특정 조건이나 동작에 따라 자동으로 경로를 변경할 수 있다는 것

  • Next.js App Router를 사용할 경우 useRouter hook은 next/router가 아닌 next/navigation에서 가져와야 한다.

권장 사항

  • 특별한 이유가 없다면 네비게이션에는 <Link>컴포넌트를 사용하는 것이 좋다.
  • useRouter는 특정한 요구사항이 있을 때만 사용할 것

useRouter 메서드

✅1. router.push(href: string, { scroll: boolean })

  • 클라이언트 측 네비게이션을 수행해 제공된 경로로 이동
  • 브라우저 히스토리 스택에 새로운 항목 추가

✅2. router.replace(href: string, { scroll: boolean })

  • 클라이언트 측 네비게이션을 수행해 제공된경로로 이동
  • 브라우저의 히스토리 스택을 변경하지만 새로운 항목을 추가하지 않는다.
    즉, 뒤로가기를 눌러도 이전 페이지로 돌아갈 수 없다.

✅3. router.refresh()

  • 현재 경로를 새로고침
  • 서버에 새 요청을 보내고 데이터를 다시 가져오며, 서버 컴포넌트를 다시 렌더링
  • 하지만 클라이언트 상태(useState)나 브라우저 상태(스크롤 위치)는 유지 된다.

✅4. router.prefetch(href: string)

  • 제공된 경로를 프리페칭해 빠른 클라이언트 측 전환이 가능하게 한다.

✅5. router.back()

  • 브라우저의 히스토리 스택에서 이전 페이지로 이동한다.

✅6. router.forward()

  • 브라우저 히스토리 스택에서 다음 페이지로 이동한다.

Good to know
🚨 보안

  • rotuer.push또는 router.replace에 신뢰할 수 없거나 필터링되지 않은 URL를 전달하면 안됨
  • XXS 공격에 최약해질 수 있음
  • Ex) : js 프로토콜이 포함된 URL을 전달하면 현재 페이지에서 악성 코드가 실행될 위험이 있음

<Link> 컴포넌트의 프리페칭 기능

  • <Link> 컴포넌트는 viewport에 보이는 경로를 자동으로 프리페칭 하여 빠른 네비게이션 지원

🔄 refresh()와 캐싱된 요청

  • refresh를 호출해도 이미 캐시된 요청이 있다면 동일한 결과가 나올 수 있다.
  • 하지만 cookie나 header같은 동적 API가 포함된 경우 응답이 변경될 수 있다.

정리하자면 router.pushrouter.replace를 사용할 때는 반드시 URL을 검증하고,
refresh()의 캐싱 동작을 고려할 것.

📌redirect function

  • 서버 컴포넌트에서는 redircet를 사용한다.

Good to know

  • 기본적으로 redirect는 307(Temporary Redirect) 상태 코드를 반환한다.
  • Server Action에서 사용하면 303(See Other)을 반환하며, 이는 POST 요청 후 성공 페이지로 리디렉션할 때 일반적으로 사용된다.

⚠️ 주의

  • redirect는 내부적으로 에러를 발생시키므로 try/catch블록안에서 호출 하면 안된다.
    try/catch블록 이 끝나고 나서 호출하는건 가능
  • 클라이언트 컴포넌트에서 렌더링 과정 중에는 호출할 수 있지만, 이벤트 핸들러 내에서는 사용할 수 없다.
    이벤트 핸들러에서 redirect 하라면 useRouter`훅을 사용할 것
  • redirect는 절대 URL 경로를 지원하며, 외부 링크로도 redirect가 가능하다.
  • 🔄 렌더링 이전에 redirect를 하러면 next.config.js 또는 middleware를 사용할 것

📌Using the native History API

  • window.history.pushState & window.history.replaceState 제공 : 페이지를 다시 로드하지 않고도 브라우저의 기록 스택을 업데이트 하는 방법
  • pushState & replaceState 호출은 Next.js 라우터와 통합되어 usePathnameuseSearchParams와 동기화 될 수 있다.

pusState, replaceState 예제

Ex.1

✅ 2초 후 window.history.pushState()로 경로를 /new-path로 변경
usePathname()이 변경된 URL을 감지하고 자동으로 업데이트됨

"use client";

import { useEffect } from "react";
import { usePathname } from "next/navigation";

export default function Page() {
  const pathname = usePathname();

  useEffect(() => {
    setTimeout(() => {
      window.history.pushState({}, "", "/new-path");
    }, 2000);
  }, []);

  return (
    <div>
      <h1>Current Path: {pathname}</h1>
      <p>2초 후에 URL"/new-path"로 변경됩니다.</p>
    </div>
  );
}

Ex.2

✅ 2초 후 window.history.replaceState()로 쿼리 스트링만 변경 (?query=nextjs)
useSearchParams()가 변경 사항을 감지하고 즉시 업데이트 됨

"use client";

import { useEffect } from "react";
import { useSearchParams } from "next/navigation";

export default function Page() {
  const searchParams = useSearchParams();

  useEffect(() => {
    setTimeout(() => {
      window.history.replaceState({}, "", "?query=nextjs");
    }, 2000);
  }, []);

  return (
    <div>
      <h1>Current Query: {searchParams.get("query")}</h1>
      <p>2초 후에 URL 쿼리가 "?query=nextjs"로 변경됩니다.</p>
    </div>
  );
}
  1. 브라우저의 history.pushState와 history.replaceState를 사용하면, URL을 변경하면서 페이지를 새로고침하지 않을 수 있음.
  2. Next.js의 usePathname과 useSearchParams는 이러한 변경 사항을 자동으로 감지하여 UI를 즉시 업데이트함.
  3. 이 기능을 활용하면, 클라이언트에서 URL 변경을 쉽게 처리하면서도 SPA처럼 동작하는 부드러운 내비게이션을 구현할 수 있음.

📌How Routing and Navigation Works(Next.js에서 제공하는 라우트를 사용하면 무슨 장점이 있을까?)

Next.js에서 Navigate를 하는 4가지 방법은 알아보았고 이러한 Navigate이 주는 장점을 알아보자

7개나 있는데 좀 압축해서 작성해보겠음

1. Code Splitting

  • 코드 스플리팅은 애플리케이션 코드를 더 작은 번들로 나누어서 브라우저에서 다운로드 및 실행할 수 있도록 하는 기술
  • 이를 통해 전송되는 데이터 양과 실행 시간을 줄여 성능 향상 가능
  • 서버 컴포넌트는 애플리케이션 코드를 자동으로 Segment(경로) 단위로 코드 스플리팅을 진행

✅ 즉 사용자가 페이지를 탐색할 때 해당 경로에 필요한 코드만 로드 되므로, 불필요한 코드 로딩이 줄어 성능 최적화

2. Prefetching

  • 위에서도 알아 보았듯이 <Link> 옵션 중 prefetch를 사용 할 수 있었고 router.prefecth()를 통해서도 가능

프리페칭 경계 : layout.js, loading.js

  • 기본적으로 shared layout 및 첫 번째 loading.js경계까지만 프리페칭(30s)
  • 전체 동적 경로를 미리 가져오는 비용을 줄이고, 즉각적인 로딩 상태를 제공하는 데 도움

3. Caching

  • Next.js에서 제공하는 라우팅 방식을 사용하면 캐싱이 된다.
  • <a>쓰면 안해줌

4. Partical Rendering(부분 렌더링)

  • /dashboard/settings/dashboard/analytics 로 이동할 경우
    settings는 Unmount
    analytics는 Mount
    공유 레이아웃 /dashboard는 그대로 유지 되고 변경된 부분만 렌더링 됨
  • 즉, Next.js는 경로를 이동할 경우 자동적으로 팔요한 변경점만 렌더링 해준다

이정도 Linking and Navigating은 거의 1차적으로 정리 완료

profile
Async FE 취업 준비중.. Await .. (취업완료 대기중) ..

0개의 댓글