Next.js의 Link와 next/navigation으로 떠나는 라우팅 세계

·2024년 9월 4일

더취페이 프로젝트

목록 보기
3/37

일반적으로 웹에 링크를 추가할 때는 <a> 태그를 많이 사용한다. 하지만 Next.js는 <a> 태그 대신 <Link>라는 Next.js의 컴포넌트를 사용해야 한다. <Link> 컴포넌트를 사용한다고 해서 마크업이 달라지는 것은 아니다. 아래 코드에서 <Link>를 사용해서 마크업을 해주었지만,

실제로는 <a>태그로 마크업되게 된다.


그렇다면 왜 Link 컴포넌트를 사용해야 하는 걸까? Link 컴포넌트를 사용했을 때와 a 태그를 사용했을 때의 차이는 무엇일까? 이 부분을 정리하고자 한다. 추가로 Link와 비슷하게 동작하는 router.push()와의 차이도 알아볼 겸 useRouter와 관련해서도 정리해보고자 한다.

※ 지금 작성하는 시점의 Next.js 버전은 14.2.5이다.

next/Link

다음과 같이 import를 하여 사용할 수 있다.

import Link from 'next/link'

Link 컴포넌트는 a 태그와 같은 방식으로 작성해주면 된다.

<Link href="/">Home</Link>

href에는 이동할 경로 혹은 URL를 넣어준다. 이 값은 필수값으로 해당 속성이 없을 경우 오류가 발생한다.

기타 props로는 다음과 같은 것들이 있다. 이들은 옵션값이다.

  • as : URL의 경로를 마스킹. href는 실제 경로를 가리키고, as는 브라우저에 표시되는 경로를 정의한다. 주로 동적 라우팅에서 사용된다.
 <Link href="/products?category=shoes&color=red&size=9" as="/products/shoes/red/size-9">
	size 9인 red 신발 보기
</Link>

동적라우팅에서는 다음과 같이 사용할 수 있다.

<Link href="/post/[id]" as="/post/123">게시글 보기</Link>
  • prefetch : default=true, 뷰포트 내의 Link 태그 데이터만 미리 받아온다. (전체 페이지가 아니라 스크롤 안의 보이는 요소들을 기준으로 한다.) 이를 통해 페이지 간의 전환 속도가 매우 빨라지게 된다. false 설정을 통해 끌 수 있지만, 마우스 오버 시에는 작동한다. production 모드에서만 실행된다. (개발모드에서 실행 X)

  • replace : default=false 뒤로가기 history에 쌓이지 않고 대체된다

  • scroll : default=true 페이지를 이동할 때 스크롤 위치를 맨 위로 이동시킬지 여부를 결정

  • shallow : default=false URL이 변경될 때 전체 페이지를 다시 로드하지 않고, URL만 변경하면서 현재 페이지의 상태를 유지한다

  • locale : default=false 링크가 클릭되었을 때 사용할 언어를 지정한다 이를 통해 특정 언어로 라우팅할 수 있습니다.

왜 Link를 사용해야 할까?

최초 URL을 통해 접근할 때는 SSR에 의해 이미 생성된 html 파일을 받아오게되고 받아온 html 파일을 화면에 보여주게 된다. 이후에 Link 컴포넌트를 통해 다른 페이지로 이동하게 되면, CSR 형태로 페이지가 이동하게 되어, 클라이언트(브라우저)에서 렌더링을 진행한다.

하지만 a 태그를 사용하게되면 URL을 통해 직접 접근하는 방식으로 이동하기 때문에 서버로부터 html 파일을 새로 받아와서 화면 전체를 다시 만들게 된다.

따라서, a 태그를 사용하기 보단 Link 컴포넌트를 사용해서 라우팅 하는 것이 좋다. 단, 외부 링크로 이동을 한다면 Link를 사용하든 a 태그를 사용하든 상관 없다.

next/navigation

Next.js 13의 app 디렉토리와 함께 도입된 라우팅 관련 훅과 유틸리티를 제공하는 모듈
클라이언트 컴포넌트에서 페이지 네비게이션, URL 조작, 레이아웃 세그먼트 선택 등을 효율적으로 처리할 수 있도록 도와줍니다.

useRouter

Next.js의 클라이언트 라우팅을 관리하는 훅입니다. 페이지 이동, 히스토리 조작, 현재 URL의 쿼리와 경로를 조작할 수 있습니다.

'use client';

import { useRouter } from 'next/navigation';

export default function MyComponent() {
  const router = useRouter();

  const handleNavigation = () => {
    // '/about' 페이지로 이동
    router.push('/about');
  };

  const handleReplace = () => {
    // 현재 페이지를 '/about' 페이지로 대체
    router.replace('/about');
  };

  const goBack = () => {
    // 이전 페이지로 이동
    router.back();
  };

  const goForward = () => {
    // 다음 페이지로 이동
    router.forward();
  };

  const refreshPage = () => {
    // 현재 페이지를 새로 고침
    router.refresh();
  };

  return (
    <div>
      <button onClick={handleNavigation}>Go to About</button>
      <button onClick={handleReplace}>Replace with About</button>
      <button onClick={goBack}>Go Back</button>
      <button onClick={goForward}>Go Forward</button>
      <button onClick={refreshPage}>Refresh</button>
    </div>
  );
}

next/Link와의 차이

useRouter를 사용하여 프로그래밍적으로 페이지를 이동할 경우, 이동할 주소(URL)가 HTML 소스 코드에 직접적으로 드러나지 않아 이로 인해 검색 엔진 크롤러가 페이지를 탐색할 때, 이러한 이동 경로를 쉽게 인식하지 못해 해당 경로가 검색 결과에 반영되지 않을 수 있다. 즉, SEO에 취약하다.

페이지를 이동 할 때에 단순히 즉시 페이지를 이동하는 것이 아니라 어떤 비즈니스 로직 등을 수행한 후, 결과 처리로 페이지를 이동 하는 등 함수 형식의 기능을 수행할 때 사용한다.

페이지 렌더링 시점에서 이동할 주소가 아직 정해지지 않은 경우, 비동기 작업을 통해 클릭 시점에 이동할 주소를 동적으로 결정해야 할 수 있다. <Link> 컴포넌트는 정적으로 미리 지정된 URL을 사용하는 것이 일반적이기 때문에, 이러한 동적 상황을 처리하는 데는 적합하지 않을 수 있습니다.

usePathname

현재 페이지의 경로를 반환한다.

프로젝트의 header에서 현재 경로에 따라 nav item을 활성화시켜주기 위해 pathname을 통해 현재 접근 중인 페이지를 반환하도록 해주었다.

import { usePathname } from 'next/navigation';

export default function Header() {
  const pathname = usePathname();
  const menu = useMemo(() => {
    if (pathname.startsWith('/commerce')) return '공동구매';
    if (pathname.startsWith('/mart')) return '마트/배달';
    if (pathname.startsWith('/used')) return '거래/나눔';
    if (pathname.startsWith('/community')) return '커뮤니티';
    if (pathname.startsWith('/event')) return '이벤트';
    return '';
  }, [pathname]);
}

useSearchParams

URL의 쿼리 매개변수객체 형태로 반환한다. 클라이언트 측에서 URL의 쿼리 매개변수를 쉽게 접근하고 조작할 수 있게 해준다.

프로젝트의 검색 페이지에서 useSearchParams를 이용해 query로 전달된 keyword를 접근하게 해주었다.

import { useSearchParams } from 'next/navigation';

export default function Search() {
  const searchParams = useSearchParams();
  const keyword = searchParams.get('keyword') || '검색어 없음';

  return (
  	<div>
    	<h2 className="mt-[40px] text-2xl font-bold">'{keyword}'에 대한 검색결과</h2>
    </div>
  );
}

redirect

클라이언트 측에서 페이지를 리디렉션하는 함수

import { redirect } from 'next/navigation';

export default function RedirectToHome() {
  if (true) { 
    redirect('/home');
  }

  return <div>Redirecting...</div>;
}

notfound

클라이언트 측에서 404 페이지를 강제로 표시하는 함수

import { notFound } from 'next/navigation';

export default function CheckPage() {
  if (true) {
    notFound();
  }

  return <div>Checking...</div>;
}

참고 자료

[Next.js] next/Link 사용하기 (공식문서 내용 정리)
next.js에서 a 태그 대신 Link를 사용하는 이유
[Next.js] 'Link', 'router.push()', 'a' tag 어떻게 다를까?

profile
Frontend🍓

0개의 댓글