Next Routing

이종경·2024년 6월 6일
0

Next, 너 뭐 돼?

목록 보기
2/8
post-thumbnail

React를 단독으로 사용할 땐, 라우팅 관련 기능을 사용하려면 react-router-dom을 설치하여 구현해야 했다. 하지만 Next는 Routing기능이 내장된 프레임워크로 이 글에서는 App Router 구현 방식을 정리해보겠다.

Defining Routes

react에서는 route를 정의하기 위해서는 react-router-dom의 Routes 컴포넌트와 Route 컴포넌트를 사용하여 매핑해야했다. 반면에, Next에서는 app 디렉토리 하위에 폴더를 생성하는 것으로 라우팅을 정의할 수 있다.

routing

예를 들어, /dashboard/settings와 같은 라우팅을 구현할 때 위와 같이 폴더를 생성하면 된다.

단, 주의해야할 점은 생성한 dashboard, setting 폴더 내에는 반드시 page.jsx 혹은 page.tsx가 반드시 존재해야 한다.

만약, page.tsx 파일이 없으면 notFound 페이지로 이동한다.

여기서 page.jsx 혹은 page.tsx의 역할은 렌더링되는 페이지를 의미한다.
예를 들어, app/page.tsx는 root 디렉토리의 페이지를 렌더링한다.

위 과정을 통해 생성된 디렉토리 구조를 살펴보면 다음과 같다.
define route

Not Found Page

Next에서는 아래와 같은 Not Found 페이지를 기본 제공한다.
NotFound
만약, 커스텀 Not Found 페이지를 만들고 싶다면
app 디렉토리 하위에 not-found.jsx|.tsx를 파일을 만든 후 컴포넌트를 생성해주면 된다.

import Link from 'next/link'
 
export default function NotFound() {
  return (
    <div>
      <h2>Not Found</h2>
      <p>Could not find requested resource</p>
      <Link href="/">Return Home</Link>
    </div>
  )
}

이때 반드시 컴포넌트명이 NotFound일 필요는 없다. 이렇게 생성된 NotFound 페이지는 데이터 페칭시 실패할 경우 notFound()함수를 통해 해당 페이지로 사용자를 이동시킬 수 있다.

import { notFound } from 'next/navigation'
 
async function fetchUser(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}
 
export default async function Profile({ params }) {
  const user = await fetchUser(params.id)
 
  if (!user) {
    notFound()
  }
 
  // ...
}

Pages and Layouts

위에서도 설명이 되었지만 라우팅은 폴더의 구조를 통해 설계할 수 있으며 실제로 렌더링되는 페이지는 page.jsx 혹은 page.tsx를 통해 구현한다.

Layouts

Next에서는 react-router-dom의 Outlet과 유사한 Layout기능이 있다.

이때 반드시 최상위 레이아웃에서는 html 태그와 body 태그가 반드시 작성되어 있어야 한다.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* Layout UI */}
        <main>{children}</main>
      </body>
    </html>
  )
}

또한, 레이아웃은 여러개를 중첩하여 사용할 수 있다.

예를 들어, 루트 디렉토리인 app의 layout에서 일부분을 dashboard에서 사용될 레이아웃을 중첩하여 설계할 수 있다.
layout

굳이 포함관계를 따진다면 dashboard의 layout ⊂ App의 layout이다.
만약, dashboard의 하위에 comment라는 라우팅이 추가된다면 포함관계는
comment의 layout ⊂ dashboard의 layout ⊂ App의 layout 이 된다.

이렇게 생성된 레이아웃에 page.tsx가 렌더링된다.

Templates

Layout.jsx는 기본적으로 리렌더링이 안된다.
만약, 페이지 이동마다 새롭게 마운트 되게 하고싶다면 template.jsx를 생성해주면 된다.

주의할점은, template이랑 layout은 같이 사용되면 안된다.

Metadata

Next에서 제공하는 Metatdata APIs를 통해 head의 메타데이터를 쉽게 수정할 수 있다.

보통 layout.jsx에 import하여 사용한다.

import { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'Next.js',
}
 
export default function Page() {
  return '...'
}

Loading UI and Streaming

페이지가 로딩중일 경우 loading.tsx를 생성하면 로딩화면을 구현할 수 있다.
이 기능은 React의 Suspense기능을 활용 한 것이다.

이 기능을 사용하려면 page.tsx와 같은 경로에 loading.tsx를 생성한다.

Error Handling

페이지가 에러가 발생했을 경우 error.tsx를 생성하면 에러 화면을 구현할 수 있다.
이 기능은 React의 Error Boundary기능을 활용한 것이다.

이 기능을 사용하려면 page.tsx와 같은 경로에 error.tsx를 생성한다.

Route Groups

Next에서는 Route Groups라는 그룹별로 URL을 분류할 수 있는 편리한 기능을 제공한다.
사용방법은 그룹으로 묶어줄 디렉토리명을 소괄호로 다음과 같이 작성하면 된다.

(그룹화할 폴더이름)

예를 들어, 로그인 하기 전 접근가능한 URL과, 로그인 후 접근가능한 URL이 분리되어 있으면 해당 기능을 사용하여 (beforeLogin), (afterLogin)과 같이 URL 그룹을 분류할 수 있다.

아래 Next에서 제공하는 예시를 보면 더 직관적으로 이해할 수 있다.
Route Groups

Next에서는 shop이라는 그룹과 marketing이라는 그룹으로 나누었다.

Dynamic Routes

Next에서는 Dynamic Routes라는 기능을 제공한다.
디렉토리명을 대괄호로 다음과 같이 작성하면 된다.

[폴더이름]

예를 들어, post의 상세페이지인 /post/1과 같은 페이지를 만들려면
post 디렉토리 하위에 [id]라는 명칭으로 디렉토리를 생성한 후 해당 디렉토리에 page.jsx를 생성해주면 된다.

Parallel Routes

Next에서는 동시에 두개의 페이지를 보여주고자 할 때 parallel Route기능을 제공한다.
이 기능을 사용하려면 디렉토리명을 다음과 같이 작성하면 된다.

@폴더이름

이렇게 생성된 Parallel Route @폴더를 Slot이라한다.

parallel Routes

위의 예시와 같이 @team slot과 @analytics slot을 생성하였으면 이들을 layout.js에서 Props로 넘겨주어야 렌더링할 수 있다.

default.js

parallel Route에 대한 fallback으로서 사용할 수 있다.

예를 들어, 다음과 같은 폴더구조로 설계했을 때
folder

(beforeLogin)/layout.tsx파일은 다음과 같이 작성된다

export default function BeforeLoginLayout({ children, modal }) {
  return (
    <div>
      {children}
      {modal}
    </div>
  );
}

그런데, (beforeLogin)/@modal/default.tsx가 없으면 Next는 layout.tsx에서 props로 가져올 modal이 없어서 404 페이지가 렌더링된다.

이때 이를 방지하기 위해 default.tsx를 통해 modal에 전달될 props를 연결해준다.

Intercepting Routes

현재 레이아웃에서 주소가 다른 레이아웃을 같이 렌더링될 수 있게 해주는 기능이다.
이 기능을 사용하려면 디렉토리명을 다음과 같이 작성하면 된다.

(.)폴더이름 # 같은 레벨의 세그먼트와 매치된다
(..)폴더이름 # 한 단계 위의 세그먼트와 매치된다.
(..)(..)폴더이름 # 두 단계 위의 세그먼트와 매치된다.
(...)폴더이름 # 루트인 app의 세그먼트와 매치된다.

intercepting Route가 실행되는 조건은 Link를 통해 이동할 경우 실행된다.
만약 브라우저를 통해 직접 주소를 입력해서 접근하거나 새로고침을 하게되면 기존 라우트가 실행된다.

intercepting Routes
Next에서 제공하는 예시와 같은 폴더구조를 설계 했을때,

Next에서 제공하는 Link를 사용하여 페이지를 이동할 경우 다음과 같이 렌더링되고
intercepting-1

브라우저를 통해 직접 주소를 입력하거나 새로고침을 할 경우는 다음과 같이 렌더링 된다.
intercepting-2

이때 일반적으로 Intercepting Routes를 구현한 폴더의 파일들과 기존의 파일들의 구성은 같게한다.

또한 이 기능은 주로 모달창 기능을 구현할 때, Parallel Routes와 함께 사용된다.

Private folder

Next에서는 Private folder라는 기능을 지원한다. Private folder로 생성하면 주소창에 표시되지 않는다.
이 기능을 사용하려면 디렉토리명을 다음과 같이 작성하면 된다.

_폴더명

private folder
위의 예시를 보면 Private folder는 라우팅 되지 않는다.

보통 폴더를 정리하기위해 사용된다.

참고
Building Your Application: Routing | Next.js
Next + React Query로 SNS 서비스 만들기

profile
작은 성취들이 모여 큰 결과를 만든다고 믿으며, 꾸준함을 바탕으로 개발 역량을 키워가고 있습니다

0개의 댓글