Next.js 라우팅, 레이아웃, 네비게이션

Minboy·2024년 3월 4일
1
post-thumbnail

Chapter 4

Nested routing

Next.js는 폴더들이 중첩 라우팅을 하는데 사용되는 파일 시스템 기반 라우팅을 사용한다. 각각의 폴더가 route segment가 되어 URL segment에 대응된다.

1

layout.tsxpage.tsx 라는 특별한 파일을 통해 각각의 라우트에 해당하는 개별 UI를 만들 수 있다.

2

폴더명을 통해 라우트를 정의하고, page.tsx 파일에서 export하는 리액트 컴포넌트를 통해 해당 라우트에 접근했을 때 보여질 UI를 정의한다. 예를 들어 /dashboard 라우트에 접근하면 app/dashboard/page.tsx 에 정의되어있는 리액트 컴포넌트가 렌더링 될 것이다.

3

위와 같이 중첩 라우팅을 구성해주자.

Creating the dashboard layout

여러 라우트에서 공통된 UI - 예를들면 Nav, Footer 등과 같은 - 가 필요하다면 layout.tsx 파일을 이용하면된다.

예를들어 /dashboard/customers 라우트와 /dashboard/invoices 라우트에서 공통적으로 사용되는 SideNav 가 필요하다면 /dashboard 폴더에 layout.tsx 파일을 만들어주면 된다.

import SideNav from '@/app/ui/dashboard/sidenav';

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
      <div className="w-full flex-none md:w-64">
        <SideNav />
      </div>
      <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
    </div>
  );
}

이렇게 layout.tsx 를 활용하면 여러 라우트에서 공통적으로 활용하는 UI를 정의해줄 수 있다. <Layout /> 컴포넌트는 children prop을 받는데, 여기에 다른 레이아웃들과 페이지들이 전달된다.

4

이렇게 Next.js의 레이아웃을 활용하면 좋은 점으로 부분 렌더링을 지원해준다. 즉 라우팅 변경 시 children 부분만 업데이트 되고 레이아웃은 재렌더링 하지 않음으로써 자원을 절약할 수 있다.

5

Root layout

import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

/app/layout.tsx 파일은 반드시 존재해야하는 Root layout이다. 이곳에 추가하는 모든 UI는 모든 페이지에 적용될 것이다. 여기서 <html> 태그와 <body> 태그를 수정할 수 있고, 메타데이터도 추가할 수 있다.

Chapter 5

Why optimize navigation?

원래 링크간의 연결을 구현하기 위해서 전통적으로는 HTML의 <a> 태그를 활용하지만, 이를 이용하면 전체 페이지가 리프레쉬 되는 문제가 발생한다. 이를 해결하기 위한 방법을 알아보자.

Next.js에서는 페이지 간의 링크를 연결하기 위해 <Link /> 컴포넌트를 사용한다. <Link> 컴포넌트는 자바스크립트를 통해 클라언트 측 네비게이션을 가능하게 해준다.

import Link from 'next/link';

...
	<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>
...

위와 같이 <a> 태그 대신에 next/link 에서 <Link> 컴포넌트를 import 해와 사용하면 된다.

이렇게 <Link> 컴포넌트를 사용하면 페이지 이동 시에 리프레쉬 되지않고 렌더링이 되는 모습을 확인할 수 있다.

Automatic code-splitting and prefetching

네비게이션 경험 향상을 위해, Next.js는 자동적으로 우리의 코드를 라우트에 따라 분할한다. 이는 첫 initial load에 모든 코드를 브라우저가 로드해오는 전통적인 React SPA 방식과는 차별화된다.

코드를 라우트에 따라 분할하는 것으로 페이지는 독립적이게 되고, 특정 페이지가 에러가 발생하더라도 전체 앱이 crash 되지 않고 여전히 동작할 수 있다.

추가로, 브라우저의 화면에 <Link> 컴포넌트가 등장하면, Next.js는 자동적으로 백그라운드에서 해당 링크에 연결된 라우트의 코드를 prefetch, 미리 가져온다. 유저가 해당 링크를 클릭하면, 이미 준비된 코드를 보여줌으로써 페이지 전환이 거의 즉각적으로 보여지게 되는 것이다.

현재 사용자가 있는 페이지를 표현하기 위한 UI 패턴으로, 액티브 링크를 보여줄 수 있다. 이를 위해서는 현재 유저가 있는 URL path를 가져올 필요가 있는데, Next.js에서는 usePathname() 훅을 통해 이를 가져올 수 있다.

usePathname() 은 훅이기 때문에 사용하는 곳을 클라이언트 컴포넌트로 선언해주어야한다. 해당 컴포넌트의 최상단에 "use client" 를 선언해주고, next/navigation 에서 usePathname() 훅을 import 해오자.

'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>
        );
      })}
    </>
  );
}

이렇게 clsx를 함께 활용해 사용자의 현재 URL과 일치하는 링크의 스타일을 다르게 적용해주는 것으로 액티브 링크를 구현해줄 수 있다.

profile
🐧

0개의 댓글

관련 채용 정보