본문 바로가기
프로그래밍/Next.js

NEXT.JS 페이지 이동(Navigating)과 코드 스플리팅

by K-인사이터 2024. 4. 21.
반응형

안녕하세요 

K-인사이트입니다. 

 

 

웹사이트 개발에서 페이지간의 이동을 구현하는 기술은 매우 중요합니다. 간단한 앵커 태그(a tag)를 활용해서 이를 구현하는 경우도 있으나 이는 전통적인 구현 방법입니다. 반응성이 높고 효율적인 네비게이션 구현 전략을 통해 고객 경험을 확대하는 등 긍정적인 효과를 높일 수 있습니다. 이는 고객의 체류시간을 늘리는 역할을 합니다. 이 글에서는 페이지 간에 이동(navigating)을 위한 next.js 의 기능을 살펴보고 간단한 응용 패턴인 활성 링크 표시하는 방법을 다루어 보도록 하겠습니다. 

 

이전 글 바로가기 

이 글은 이어진 글입니다. 샘플 프로젝트를 다운로드 받아 환경을 구성해야 한다면 아래의 글을 통해 편리하게 실습 환경을 구성할 수 있습니다. 

https://k-in.tistory.com/203 

 

NEXT.JS 일단 프로젝트부터 생성해서 공부해보자!

안녕하세요 K-인사이트입니다. Next.js 란? 기존 리액트에 없는 서버 사이드 렌더링(SSR,Server-Side Rendering), 정적 사이트 생성(SSG, Static Site Generation), 증분 정적 재생성(ISR, Incremental Static Regeneration)과

k-in.tistory.com

 

 

관련하여 Next.js 에서 페이지 생성 및 레이아웃을 적용하는 방법을 알고싶다면 아래의 글을 추천합니다. 

https://k-in.tistory.com/225

 

NEXT.JS 중첩 라우팅(Nested Routing)과 레이아웃(Layout) 적용

안녕하세요 K-인사이트입니다. 웹 사이트에서 공통된 레이아웃을 유지하며 새로운 페이지들을 개발하는 것은 중요한 작업입니다. 페이지들이 기존 디자인을 훼손하지 않으면서도 각 페이지들

k-in.tistory.com

이 글에서 다루는 내용

Next.js 에서 페이지 간의 이동을 구현하는 방법을 배웁니다. 이 과정에서 응용패턴으로 현재 활성 링크를 표시하는 구현을 진행합니다. 

  • next/link 컴포넌트의 사용방법
  • usePathname() 훅을 이용한 활성 링크 표시방법
  • Next.js 에서 이동(navigation) 메커니즘 이해

이동 최적화가 필요한 이유

페이지간의 링크를 걸기 위해 일반적으로 사용되는 앵커 태그(a 태그)를 사용하게 되면 페이지 이동할 때 페이지 전체가 리프레시되게됩니다. 이는 효율적이지 못한 방법으로 변경된 부분만 렌더링하는 클라이언트 사이드 렌더링 기술을 통해서 극복할 수 있습니다. next.js 의 Link 컴포넌트를 사용하게되면 클라이언트 사이드에서 리프레시가 발생하게되고 이를 페이지 전체가 리프레시되는 것을 방지합니다.

 

Link 컴포넌트

클라이언트 사이드 이동을 위해서 Link 컴포넌트를 사용하는 방법을 소개합니다. 예제 프로젝트에서 app/ui/dashboard/nav-links.tsx 파일을 열어서 a 태그를 Link 태그로 변경합니다. 이를 위해 next/link 를 임포트해야합니다.

 

import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link'; // 추가 
 
// ...
 
export default function NavLinks() {
  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link // 변경 
            key={link.name}
            href={link.href}
            className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link> // 변경 
        );
      })}
    </>
  );
}

 

이제 브라우저로 돌아와서 어떻게 동작하는지 살펴보겠습니다. Link 컴포넌트를 사용하게되면 네비게이션을 통해 경로를 이동할 때마다 전체 페이지를 다시그리는 현상이 발생하지 않습니다. 그리고 경로 이동 시 필요한 데이터를 가져와서 클라이언트 사이드에서 렌더링을 하게됩니다.

 

자동화된 코드 스플리팅과 프리페칭

네비게이션 환경을 개선하기 위해 Next.js는 경로별로 자동으로 코드 분할(코드 스플리팅)합니다. 이는 브라우저가 초기 로드 시 모든 애플리케이션 코드를 로드하는 기존의 React SPA와는 다릅니다. 즉, 경로별로 코드를 분할한다는 것은 페이지가 분리된다는 것을 의미합니다. 특정 페이지에서 오류가 발생해도 나머지 애플리케이션은 계속 작동합니다.

또한 프로덕션 환경에서 Link 컴포넌트가 브라우저의 뷰포트에 나타날 때마다 Next.js는 백그라운드에서 연결된 경로에 대한 코드를 자동으로 프리페치(Prefetch)합니다. 사용자가 링크를 클릭할 때쯤이면 대상 페이지의 코드가 이미 백그라운드에서 로드되어 있으므로 페이지 전환이 거의 즉각적으로 이루어집니다.

요약하면, 경로마다 코드 스플리팅을 자동으로 적용하므로 페이지가 분리되는 효과가 있으며 특정 페이지에서 오류가 발생하여도 전체 앱의 중단에 이르지 않음을 말합니다. 또한, 미리 뷰포트에 노출될 때 백그라운드에서 코드를 미리 가져오는 프리페치(Prefetch)기술을 통해 끊김없이 페이지 전환이 바로 이루어진다고 이해할 수 있습니다. 

 

응용 패턴. 활성화 링크(active link) 표시하기 

일반적인 UI 패턴은 사용자에게 현재 어떤 페이지에 있는지를 알려주는 활성 링크를 표시하는 것입니다. 이를 위해서 URL에서 사용자의 현재 경로를 가져와야 합니다. Next.js는 이러한 패턴을 구현하는 데 사용할 수 있는 usePathname 훅을 제공합니다.

usePathname는 훅이므로, nav-links.tsx를 클라이언트 컴포넌트로 전환해야 합니다. 파일 상단에 React의 "use client" 지시문을 추가하고, next/navigation에서 usePathname()을 임포트합니다.

 

'use client'; // 추가 
 
import {
  UserGroupIcon,
  HomeIcon,
  InboxIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation'; // 추가 
 
// ...

 

다음으로 pathname 변수를 훅을 통해서 초기화하는 구문을 추가합니다.

export default function NavLinks() {
  const pathname = usePathname();
  // ...
}

 

앞서 CSS 스타일링을 위해서 배웠던 clsx 를 이용해서 link.href 가 pathname 과 일치할때만 액티브 링크를 표시하도록 코드를 수정합니다. 스타일링은 파란색 텍스트와 옅은 파란색 배경색을 적용하도록 합니다.

'use client';
 
import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import clsx from 'clsx';
 
// ...
 
export default function NavLinks() {
  const pathname = usePathname();
 
  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link
            key={link.name}
            href={link.href}
            className={clsx(
              'flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3',
              {
                'bg-sky-100 text-blue-600': pathname === link.href,
              },
            )}
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link>
        );
      })}
    </>
  );
}

 

 

변경된 내용을 적용하게되면 아래와 같이 현재 경로가 네비게이션 UI를 통해서 표시됩니다.

 

 

이상입니다.

K-인사이트 올림.

반응형