NextJS - Routing/Linking and Navigating

Hunter Joe·2025년 1월 30일
0

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개의 댓글

관련 채용 정보