Intercepting Routes란?
경로를 가로채어 현재 레이아웃 내에서 애플레이케이션의 다른 부분의 경로를 로드할 수 있는 것을 말합니다.
https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes
해당 패턴을 사용하여 모달을 구현하면 상황에따라 여러 이점이 있습니다.
- 모달의 컨텐츠가 URL로 공유가 가능합니다.
- 페이지를 새로고침하여도 모달을 닫는 대신 컨텐스 트는 유지 가능합니다.
- 뒤로 가기를 했을 때 모달이 닫히기 때문에 이전경로로 이동하지 않게 됩니다.
- 앞으로 가기를 했을 경우 모달을 다시 열 수 있습니다.
구현 목표
디자이너가 만들어주신 검색 모달입니다. 다음부터 어떻게 해당 모달을 구현했는지 코드와 함께 알아보겠습니다.
modal slot 폴더 만들기
보통 Intercepting Routes를 활용하여 모달을 구현할 때 Parallel Routes를 같이 사용하여 구현합니다. Parallel Routes를 사용하면 동일한 레이아웃에서 하나 이상의 페이지를 동시에 또는 조건부로 렌더링 할 수 있습니다.
// (main)/layout.tsx
import type { Metadata } from 'next';
import Sidebar from '@/components/pages/main/layout/Sidebar';
import Header from '@/components/pages/main/layout/Header';
import Footer from '@/components/pages/main/layout/Footer';
export const metadata: Metadata = {
title: 'pawpaw | Home',
description: '우리 반려동물을 위한 최적의 커뮤니티',
};
export default function MainLayout({
children,
modal,
}: {
children: React.ReactNode;
modal: React.ReactNode;
}) {
return (
<div className="flex flex-col flex-wrap h-full tablet:flex-row">
<Header />
<Sidebar />
<div id="modal-root" />
{children}
{modal}
<Footer />
</div>
);
}
(main) 폴더는 auth 페이지 즉 회원가입, 로그인을 제외한 페이지들을 그룹핑해 놓은 폴더입니다. 즉 사이드바, 헤더, 모달등은 (main) 폴더 안에 존재하는 모든 페이지에 공유되어야 하기 때문에 layout.tsx 에서 사용을 하였습니다.
Intercepting Routes 폴더 만들기
검색 모달을 만들기 위해 폴더 두 개를 만들어야 합니다.
검색 페이지가 될 search
모달 컴포넌트가 될 (.) search
이제 특정버튼을 눌러 http://localhost:3000/search 라우팅 하게 해 주면 (.) search가 먼저 렌더링이 될 것입니다.
검색 모달 레이아웃
보통 다른 페이지들에서 똑같은 컴포넌트들을 렌더링 해야 할 때 layout을 사용하게 되는데 Intercepting Routes에서도 layout을 사용할 수 있습니다.
위 사진에서는 검색창, 필터탭, 최근검색어 기록 등은 필터가 바뀌어도 계속 똑같이 랜더링 되어야 하기 때문에 layout.tsx에서 import 하여 사용하였습니다.
import React from 'react';
import ContentTab from './_components/ContentTab';
import SearchQueryInput from './_components/SearchQueryInput';
import SearchModal from './_components/SearchModal';
export default function SearchLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<SearchModal>
<header>
<SearchQueryInput />
</header>
<ContentTab />
{children}
</SearchModal>
);
}
위와 같이 구현하게 된다면 필터에 따라 페이지 이동이 이루어지기 때문에 layout은 그대로 렌더링 되고 children만 바뀌어서 랜더링 되게 할 수 있습니다.
Modal 컴포넌트
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
'use client';
import { useRouter } from 'next/navigation';
import React from 'react';
export default function SearchModal({
children,
}: {
children: React.ReactNode;
}) {
const router = useRouter();
return (
<div className="fixed inset-0 z-50">
<div
className="fixed top-0 bottom-0 right-0 w-1/2 bg-black opacity-70"
onClick={() => router.back()}
/>
<div className="fixed top-0 bottom-0 left-0 flex flex-col w-full h-full bg-white sm:w-2/3 p-7">
<button
type="button"
className="flex self-end px-4 py-2 rounded-[10px] hover:bg-primary-200 mb-2 bg-primary-100 hover:text-white sm:hidden"
onClick={() => router.back()}
>
닫기
</button>
{children}
</div>
</div>
);
}
결과
이번 글에서는 모달을 URL로 랜더링 하는 방법에 대해 작성해 보았습니다. 해당 컴포넌트를 구현하면서 Next.js의 라우팅 시스템에 대해 조금 더 깊이 알게 된 것 같아 아주 만족스러운 작업이었습니다.
'Next.js' 카테고리의 다른 글
Next.js - Suspense와 SSR을 적용한 모달 검색기능 구현 (0) | 2023.11.13 |
---|---|
Next.js 14 App Router 가이드를 통한 Dashboard 구현 (0) | 2023.10.28 |
Nextjs - Link 태그의 Prefetch 기능 (0) | 2023.06.29 |
Next.js - Next.js 13 Metadata 동적 생성하기 (with 13.4 version) (0) | 2023.06.27 |
Next.js - Nextjs 13 정리 (1) (0) | 2023.06.20 |