[Next.js] 병렬 라우팅을 활용하여 모달 관리하기

강경서·2024년 4월 17일
0
post-thumbnail

Intro

모달은 웹 서비스 제작 시 자주 활용되며, 사용자의 주의를 집중시키고 상호 작용을 유도하여 사용자 경험을 향상시킬 수 있습니다. 이러한 모달을 React 로 제작한다면 열림/닫힘 상태 관리, 모달안의 이벤트 핸들링 등 신경써야하는 부분이 존재합니다. Next.js 에서는 병렬 라우트과 인터셉션 라우트를 함께 사용하여 멋지게 모달을 관리할 수 있습니다.


Parallel Routes (병렬 라우트)

병렬 라우트를 사용하면 동일한 레이아웃 내에서 하나 이상의 페이지를 동시에 또는 조건부로 렌더링할 수 있습니다. 하나의 페이지에서 대시보드 및 동적인 섹션이 필요한 경우 유용하게 사용할 수 있습니다.

병렬 라우트를 사용하기 위해서는 slots 을 사용해야 합니다. @folder 와 같이 정의한 slots 은 상위 레이아웃에서 props으로 전달해야 하고 경로로 구분되지 않아 URL 구조에 영향을 주지 않습니다.

export default function Layout({
  children,
  team,
  analytics,
}: {
  children: React.ReactNode
  analytics: React.ReactNode
  team: React.ReactNode
}) {
  return (
    <>
      {children}
      {team}
      {analytics}
    </>
  )
}

Intercepting Routes (인터셉션 라우트)

인터셉션 라우트는 현재 레이아웃에서 애플리케이션의 다른 부분의 경로를 로드할 수 있습니다. 이는 다른 컨텍스트로 전환하지 않고도 경로의 내용을 표시하려는 경우 유용할 수 있습니다.

인터셉션 라우트는 (..) 을 사용하여 정의할 수 있습니다.

  • (.) : 동일한 레벨의 세그먼트
  • (..) : 한 레벨 위의 세그먼트
  • (..)(..) : 두 레벨 위의 세그먼트
  • (...) : 루트 레벨인 app 디렉터리의 세그먼트

위와 같이 (..)photo 폴더는 photo 세그먼트를 인터셉트할 수 있습니다.


병렬 라우팅을 활용한 모달

병렬 라우트과 인터셉션 라우트를 함께 사용하여 모달을 관리한다면 여러 이점이 존재합니다.

  • URL을 통한 모달의 콘텐츠 공유가 가능합니다.

  • 모달을 닫는 대신 페이지를 새로 고칠 경우 컨텍스트를 유지합니다.

  • 뒤로 페이지를 이동하여 모달을 닫을 수 있습니다.

  • 앞으로 페이지를 이동하여 모달을 다시 열 수 있습니다.

모달을 제작하기 위해서는 기본 경로와 slots 을 인터셉션 라우트를 사용하여 동일한 레벨의 세그먼트로 일치시켜주어야 합니다.

default.tsx

default.tsx 파일은 Next.js 가 초기 로드 및 전체 페이지를 새로 고침 시 일치하지 않는 slots 에 대한 대체 랜더링 파일입니다.

export default function Default() {
  return null
}

위와 같이 null 을 return 하면 모달이 활성화되지 않을 때 렌더링되지 않습니다.

모달 사용하기

export default function Layout({
  children,
  modal,
}: {
  children: React.ReactNode
  modal: React.ReactNode
}) {
  return (
    <div>
      <Link href='/modal'>Open Modal</Link>
      {children}
      {modal}
    </div>
  )
}

이제 <Link> 를 클릭하면 페이지로 이동하는 대신 모달이 열립니다. 모달이 열린 상태에서 새로고침을 한다면 기본 경로로 이동하게 됩니다.

모달의 닫기 위해서는 router.back()을 사용하거나 Link 를 이용하여 null 을 return하는 catch-all 라우트 사용하여 모달을 닫을 수 있습니다.

import Link from 'next/link'
 
export function Modal({ children }: { children: React.ReactNode }) {
  return (
    <>
      <Link href="/">Close modal</Link>
      <div>{children}</div>
    </>
  )
}
// app/@modal/[...catchAll]/page.tsx
export default function CatchAll() {
  return null
}

또한 병렬 라우트는 독립적으로 스트리밍이 되므로 가 경로에 대해 로딩 및 에러 상태를 정의할 수 있습니다.


📝 후기

Next.js의 병렬 라우트와 인터셉트 라우트를 사용하여 모달을 구성한다면 동적이고 사용자의 경험을 향상시킬 수 있는 서비스를 제작할 수 있을 것 같습니다. 다만 병렬 라우트와 인터셉트 라우트를 사용하여 만든 모달의 장점을 크게 이용할 수 없는 경우(간단한 알림창) 전에 사용하던 방법으로 모달을 구성하는 편이 더 좋아보입니다.


🧾 Reference

profile
기록하고 배우고 시도하고

0개의 댓글