๐ Next.js ์ฌํ 5์ฅ: Parallel Routes & Intercepting Routes โ URL์ด ์ด์์๋ ๋ชจ๋ฌ์ ๋น๋ฐ
๐ ๊ฐ์
Parallel Routes์ Intercepting Routes์ ๊ณ ๊ธ ํ์ฉ โ ๋ณต์กํ ๋ชจ๋ฌยทํญ UI ๊ตฌํ ์ ๋ต์ ๋๋ค.
๐ ๋ชฉ์ฐจ
- ๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
- ๐ค ์ ์์์ผ ํ๋๊ฐ
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ Parallel Routes โ ํ๋์ ํ๋ฉด์ ์ฌ๋ฌ ์ฌ๋กฏ ๋ฐฐ์นํ๊ธฐ ๐ข
- ๐ฏ Intercepting Routes โ URL์ ์ ์งํ๊ณ ์ปจํ ์คํธ๋ง ๋ฐ๊พธ๊ธฐ ๐ก
- ๐ ๋์ ์กฐํฉ: URL์ ๊ฐ์ง ๋ชจ๋ฌ (Instagram ์คํ์ผ) ๐ด
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
- ๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
- ๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
- ๐ ๋ ์์๋ณด๊ธฐ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 18๋ถ (์ ์ฒด) / ํต์ฌ ํํธ๋ง: 10๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์ฒ (์ ์
): "์ธ์คํ๊ทธ๋จ ํผ๋์์ ์ฌ์ง ํด๋ฆญํ๋ฉด URL์ด
/p/ABC123์ผ๋ก ๋ฐ๋๋ฉด์ ๋ชจ๋ฌ์ด ๋จ๋๋ฐ, ๊ทธ ์ํ๋ก ์๋ก๊ณ ์นจํ๋ฉด ๋ชจ๋ฌ ์์ด ์ ์ฒด ํ์ด์ง๋ก ์ด๋ฆฌ์์์. ์ด๊ฑฐ ์ด๋ป๊ฒ ๊ตฌํํ๋ ๊ฑฐ์์?useState๋ก ๋ชจ๋ฌ ์ด๊ณ ๋ซ๋ ๊ฑด URL์ด ์ ๋ฐ๋์ด์ ๋งํฌ ๊ณต์ ๊ฐ ์ ๋๊ณ ..." - ์ํธ(๋ฆฌ๋): "๋ฐ๋ก Parallel Routes + Intercepting Routes ์กฐํฉ์ด์์.
@modal์ฌ๋กฏ๊ณผ(..)์ธํฐ์ ํฐ๋ฅผ ์กฐํฉํ๋ฉด, ๊ฐ์ URL์์ ๋ค๋น๊ฒ์ด์ ํ์ ๋๋ ๋ชจ๋ฌ๋ก, ์ง์ ์ ๊ทผํ๊ฑฐ๋ ์๋ก๊ณ ์นจํ์ ๋๋ ์ ์ฒด ํ์ด์ง๋ก ์๋ ๋ถ๊ธฐ๋ผ์. URL ๊ณต์ ๋ ๋๊ณ , ๋ค๋ก๊ฐ๊ธฐ๋ ์์ฐ์ค๋ฝ๊ณ ."
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
Parallel Routes(์ฌ๋กฏ ๊ฐ๋
) โ Intercepting Routes(URL ๊ฐ๋ก์ฑ๊ธฐ) โ ๋ ๊ธฐ๋ฅ ์กฐํฉํ URL ๋ชจ๋ฌ
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
-
@folder๋ฌธ๋ฒ์ผ๋ก ๋ ์ด์์์ ๋ ๋ฆฝ์ ์ธ ์ฌ๋กฏ์ ์ถ๊ฐํ ์ ์๋ค -
(..)route๋ฌธ๋ฒ์ผ๋ก URL์ ์ ์งํ๋ฉด์ ์ปจํ ์คํธ๋ฅผ ๋ฐ๊ฟ ์ ์๋ค - Instagram/Pinterest ์คํ์ผ์ URL์ด ์ด์์๋ ๋ชจ๋ฌ์ ๊ตฌํํ ์ ์๋ค
๐ค ์ ์์์ผ ํ๋๊ฐ
์ผ๋ฐ์ ์ธ ๋ชจ๋ฌ ๊ตฌํ์ ๋ฌธ์ ์ ์ ์๊ฐํด๋ด:
// ๊ธฐ์กด ๋ฐฉ์: useState๋ก ๋ชจ๋ฌ ์ ์ด
const [isOpen, setIsOpen] = useState(false)
<button onClick={() => setIsOpen(true)}>๊ฒ์๊ธ ๋ณด๊ธฐ</button>
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
<PostDetail />
</Modal>์ด ๋ฐฉ์์ ๋ฌธ์ :
- URL์ด ์ ๋ฐ๋์ด โ ๋ชจ๋ฌ์ ์น๊ตฌ์๊ฒ ๊ณต์ ํ ์ ์์
- ์๋ก๊ณ ์นจํ๋ฉด ์ฌ๋ผ์ ธ โ UX ์ผ๊ด์ฑ ์์
- ๋ค๋ก๊ฐ๊ธฐ๊ฐ ์ด์ํด โ ๋ชจ๋ฌ ๋ซ๋ ๊ฒ ์๋๋ผ ์ด์ ํ์ด์ง๋ก ๊ฐ๋ฒ๋ฆผ
- SEO ๋ถ๊ฐ โ ๋ชจ๋ฌ ๋ด์ฉ์ด ํฌ๋กค๋ง ์ ๋จ
Parallel + Intercepting Routes ์กฐํฉ์ด ํด๊ฒฐํ๋ ๊ฒ:
- ๋ชจ๋ฌ์ด ์ด๋ฆด ๋ URL์ด ์ค์ ๋ก ๋ณ๊ฒฝ๋จ (
/postsโ/posts/123) - URL์ ์ง์ ์ ๋ ฅํ๊ฑฐ๋ ์๋ก๊ณ ์นจํ๋ฉด ์ ์ฒด ํ์ด์ง๋ก ์ด๋ฆผ
- ๋ค๋ก๊ฐ๊ธฐํ๋ฉด ๋ชจ๋ฌ๋ง ๋ซํ (ํผ๋๋ก ๋์์ด)
- ๋ชจ๋ฌ URL์ ๊ณต์ ํ๋ฉด ๋ฐ์ ์ฌ๋๋ ํด๋น ๊ฒ์๊ธ์ ์ง์ ์ ๊ทผ ๊ฐ๋ฅ
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
ํ์ฌ ๊ฑด๋ฌผ์ ๋น์ ํ๋ฉด: ๋ณดํต ์ฌ๋ฌด์ค(page.tsx)์ ํ ์ธต์ ํ๋์ผ.
๊ทธ๋ฐ๋ฐ Parallel Routes๋ ๊ฐ์ ์ธต์ ๋ฐฉ์ด ์ฌ๋ฌ ๊ฐ์ผ. ํ์ฅ ๋ฐฉ์ด๋ ํ์์ค์ด ๋์์ ์ด๋ ค์๋ ๊ฒ์ฒ๋ผ.Intercepting์ "ํ์์ค ์์ฝ"์ด์ผ. ๋ณดํต์ 3์ธต ํ์์ค ์ง์ ์ฐพ์๊ฐ์ผ ํด. ๊ทผ๋ฐ ์์ฝ ์์คํ ์ ํตํ๋ฉด ํ์ฌ ์๋ ๊ณณ(2์ธต ์ฌ๋ฌด์ค)์์ ํ์ ํ์(๋ชจ๋ฌ)๋ฅผ ํ ์ ์์ด. ๊ฐ์ ๋ฐฉ ๋ฒํธ(URL)์ธ๋ฐ ๋ณด์ด๋ ๊ฒ์ด ๋ฌ๋ผ.
Parallel Routes ์๊ฐํ:
app/
layout.tsx โ { children } + { @team } + { @analytics } ์ธ ์ฌ๋กฏ์ ๋์์ ๋ ๋
page.tsx โ children ์ฌ๋กฏ
@team/
page.tsx โ @team ์ฌ๋กฏ ๋ด์ฉ
@analytics/
page.tsx โ @analytics ์ฌ๋กฏ ๋ด์ฉ
Intercepting Routes ๊ธฐํธ:
| ๊ธฐํธ | ์๋ฏธ |
|---|---|
(.)folder | ๊ฐ์ ๋ ๋ฒจ ์ธํฐ์ ํธ |
(..)folder | ํ ๋จ๊ณ ์ ์ธํฐ์ ํธ |
(..)(..)folder | ๋ ๋จ๊ณ ์ ์ธํฐ์ ํธ |
(...)folder | ๋ฃจํธ๋ถํฐ ์ธํฐ์ ํธ |
๐งฉ Parallel Routes โ ํ๋์ ํ๋ฉด์ ์ฌ๋ฌ ์ฌ๋กฏ ๋ฐฐ์นํ๊ธฐ ๐ข
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
@slotํด๋ ๋ฌธ๋ฒ์ผ๋ก ๋ ์ด์์์ ๋ ๋ฆฝ์ ์ธ ๋ณ๋ ฌ ์์ญ์ ๋ง๋ค ์ ์๋คdefault.tsx๊ฐ ์ ํ์ํ์ง ์ดํดํ๋ค
Parallel Routes๋ ํ๋์ URL์์ ์ฌ๋ฌ ๋ ๋ฆฝ์ ์ธ ์์ญ(์ฌ๋กฏ)์ ๋์์ ๋ ๋๋งํ๋ ๊ธฐ๋ฅ์ด์ผ.
// app/(dashboard)/layout.tsx
// @team, @analytics ๋ ์ฌ๋กฏ์ props๋ก ๋ฐ์
interface DashboardLayoutProps {
children: React.ReactNode
team: React.ReactNode // @team ์ฌ๋กฏ
analytics: React.ReactNode // @analytics ์ฌ๋กฏ
}
export default function DashboardLayout({
children,
team,
analytics,
}: DashboardLayoutProps) {
return (
<div className="dashboard">
<main>{children}</main>
<aside className="team-panel">{team}</aside>
<section className="analytics-panel">{analytics}</section>
</div>
)
}app/(dashboard)/
layout.tsx โ ์์ ๋ ์ด์์
page.tsx โ children ์ฌ๋กฏ (๊ธฐ๋ณธ ๋์๋ณด๋ ๋ด์ฉ)
@team/
page.tsx โ team ์ฌ๋กฏ ๋ด์ฉ (ํ์ ๋ชฉ๋ก)
default.tsx โ โ ๏ธ ํ์! ์ฌ๋กฏ์ ๋งค์นญ ํ์ด์ง ์์ ๋ fallback
@analytics/
page.tsx โ analytics ์ฌ๋กฏ ๋ด์ฉ (ํต๊ณ)
default.tsx โ โ ๏ธ ํ์!
default.tsx๊ฐ ์ ํ์์ธ๊ฐ:
// app/(dashboard)/@team/default.tsx
// ์ด ํ์ผ์ด ์์ผ๋ฉด: ๋ค๋ฅธ ์ฌ๋กฏ๋ง ์๋ URL๋ก ๋ค๋น๊ฒ์ด์
ํ ๋ Next.js๊ฐ
// "์ด ์ฌ๋กฏ์ ๋ญ ๋ ๋ํด์ผ ํ์ง?"๋ฅผ ๋ชจ๋ฅด๊ณ ์๋ฌ๋ฅผ ๋
export default function TeamDefault() {
return null // ๋๋ ๋ก๋ฉ ์ค์ผ๋ ํค, ๊ธฐ๋ณธ ์ปจํ
์ธ ๋ฑ
}๐ก ํ ์ค๋ก ๊ธฐ์ตํ๊ธฐ
Parallel Routes์@slot์ ๋ ์ด์์์ ๋ ๋ฆฝ์ ์ธ "ํ๋ฉด ๊ตฌ์ญ"์ ์ถ๊ฐํ๋ ๊ฑฐ์ผ. ๊ฐ ๊ตฌ์ญ์ ์์ฒด ๋ก๋ฉ, ์๋ฌ ์ํ๋ฅผ ๊ฐ์ง ์ ์์ด.
๐ฏ Intercepting Routes โ URL์ ์ ์งํ๊ณ ์ปจํ ์คํธ๋ง ๋ฐ๊พธ๊ธฐ ๐ก
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
(..)route๋ฌธ๋ฒ์ผ๋ก ๋ค๋น๊ฒ์ด์ ์ URL์ "๊ฐ๋ก์ฑ์" ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๋ณด์ฌ์ค ์ ์๋ค- ์ง์ ์ ๊ทผ(์๋ก๊ณ ์นจ)๊ณผ ๋ค๋น๊ฒ์ด์ ์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋๋ ์๋ฆฌ๋ฅผ ์ดํดํ๋ค
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
/posts/123์ผ๋ก ๋งํฌ ํด๋ฆญ ์์๋ ๋ชจ๋ฌ๋ก, URL ์ง์ ์ ๋ ฅ ์์๋ ์ ์ฒด ํ์ด์ง๋ก ๋ณด์ฌ์ฃผ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
Intercepting Routes๋ Next.js ๋ด๋ถ์์ ๋ค๋น๊ฒ์ด์ ํ ๋ URL์ ๊ฐ๋ก์ฑ์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ๊ธฐ๋ฅ์ด์ผ.
app/
posts/
page.tsx โ ๊ฒ์๊ธ ๋ชฉ๋ก (/posts)
[id]/
page.tsx โ ๊ฒ์๊ธ ์ ์ฒด ํ์ด์ง (/posts/123 ์ง์ ์ ๊ทผ ์)
@modal/
(.)posts/ โ (.): ๊ฐ์ ๋ ๋ฒจ(/posts) ์ธํฐ์
ํธ
[id]/
page.tsx โ ๊ฒ์๊ธ ๋ชจ๋ฌ (๋ชฉ๋ก์์ ํด๋ฆญ ์, URL์ /posts/123)
default.tsx โ ๋ชจ๋ฌ ์ฌ๋กฏ ๊ธฐ๋ณธ๊ฐ (๋ชจ๋ฌ ์์ ๋)
layout.tsx โ { children } + { @modal } ์ฌ๋กฏ ํฌํจ
์ค์ ๋์ ํ๋ฆ:
์๋๋ฆฌ์ค 1: /posts ํ์ด์ง์์ ๊ฒ์๊ธ ํด๋ฆญ
โ URL: /posts โ /posts/123
โ Next.js: "์ง๊ธ ๋ด๋ถ ๋ค๋น๊ฒ์ด์
์ด๊ณ , @modal ์ฌ๋กฏ์ (.)posts/[id]๊ฐ ์๋ค"
โ ๋ ๋: ๋ฐฐ๊ฒฝ(ํผ๋) + ๋ชจ๋ฌ(๊ฒ์๊ธ ์์ธ)
์๋๋ฆฌ์ค 2: ๋ธ๋ผ์ฐ์ ์ /posts/123 ์ง์ ์
๋ ฅ
โ URL: /posts/123
โ Next.js: "์ง์ ์ ๊ทผ์ด๋ ์ธํฐ์
ํธ ์์ด ๊ทธ๋ฅ posts/[id]/page.tsx ๋ ๋"
โ ๋ ๋: ๊ฒ์๊ธ ์ ์ฒด ํ์ด์ง
์๋๋ฆฌ์ค 3: ๋ชจ๋ฌ ์ํ์์ ๋ค๋ก๊ฐ๊ธฐ
โ URL: /posts/123 โ /posts
โ ๋ชจ๋ฌ ๋ซํ, ํผ๋๋ก ๋ณต๊ท
๐ ๋์ ์กฐํฉ: URL์ ๊ฐ์ง ๋ชจ๋ฌ (Instagram ์คํ์ผ) ๐ด
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- Parallel Routes + Intercepting Routes๋ฅผ ์กฐํฉํด Instagram ์คํ์ผ ๋ชจ๋ฌ์ ๊ตฌํํ ์ ์๋ค
// app/layout.tsx โ @modal ์ฌ๋กฏ ํฌํจ
interface RootLayoutProps {
children: React.ReactNode
modal: React.ReactNode // @modal ์ฌ๋กฏ
}
export default function RootLayout({ children, modal }: RootLayoutProps) {
return (
<html lang="ko">
<body>
{children}
{modal} {/* ๋ชจ๋ฌ์ด ์ด๋ฆด ๋ ์ฌ๊ธฐ์ ๋ ๋๋จ */}
</body>
</html>
)
}// app/@modal/(.)posts/[id]/page.tsx โ ์ธํฐ์
ํธ๋ ๋ชจ๋ฌ ๋ฒ์
import { Modal } from '@/components/ui/Modal'
import { getPost } from '@/lib/dal'
export default async function PostModal({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const post = await getPost(id)
return (
<Modal>
{/* ๋ชจ๋ฌ ๋ด์์ ๋ณด์ฌ์ค ๊ฒ์๊ธ ์์ธ ๋ด์ฉ */}
<h1>{post.title}</h1>
<p>{post.content}</p>
</Modal>
)
}// components/ui/Modal.tsx โ ๋ชจ๋ฌ ์ปดํฌ๋ํธ
'use client'
import { useRouter } from 'next/navigation'
export function Modal({ children }: { children: React.ReactNode }) {
const router = useRouter()
return (
<div
className="modal-backdrop"
onClick={() => router.back()} // ๋ฐฐ๊ฒฝ ํด๋ฆญ ์ ๋ค๋ก๊ฐ๊ธฐ โ ๋ชจ๋ฌ ๋ซํ
>
<div
className="modal-content"
onClick={(e) => e.stopPropagation()} // ๋ด์ฉ ํด๋ฆญ ์ ๋ซํ ๋ฐฉ์ง
>
{children}
</div>
</div>
)
}// app/@modal/default.tsx โ ๋ชจ๋ฌ ์์ ๋ null ๋ ๋
export default function ModalDefault() {
return null
}๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
โ Parallel Route ์ฌ๋กฏ์์ default.tsx ์์ด์ ์๋ฌ
์ธ์ ๋์ค๋๊ฐ?
Error: Missing default export in @modal/default.tsx
์์ธ: ์ฌ๋กฏ์ด ์๋ ๋ ์ด์์์์ ํ์ฌ URL๊ณผ ๋งค์นญ๋๋ ์ฌ๋กฏ ํ์ด์ง๊ฐ ์์ ๋ default.tsx๊ฐ fallback.
ํด๊ฒฐ์ฑ
: ๋ชจ๋ @slot ํด๋์ default.tsx ํ์ผ์ ๋ง๋ค์ด. ๋ด์ฉ์ null์ด์ด๋ ๋จ.
โ Intercepting Routes๊ฐ ๋์ ์ ํ๊ณ ๊ทธ๋ฅ ์ ์ฒด ํ์ด์ง๋ก ์ด๋
์์ธ: (..) ๊ธฐํธ์ ๋ ๋ฒจ์ด ์๋ชป๋จ. ํ์ผ ์์คํ
๋ ๋ฒจ์ด ์๋ URL ์ธ๊ทธ๋จผํธ ๋ ๋ฒจ๋ก ๊ณ์ฐํด์ผ ํด.
ํด๊ฒฐ์ฑ :
// URL: /posts/[id]๋ฅผ ์ธํฐ์
ํธํ๋ ค๋ฉด
// @modal ์ฌ๋กฏ์ด / (๋ฃจํธ) ๋ ๋ฒจ์ ์์ผ๋ฉด: (.)posts/[id]
// @modal ์ฌ๋กฏ์ด /posts ๋ ๋ฒจ์ ์์ผ๋ฉด: (.)/ ๋๋ ์ง์ [id] ํด๋
๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
๐ ์ฃผ์ ํ์ผ ๊ตฌ์กฐ ํจํด
| ํจํด | ํ์ผ ๊ตฌ์กฐ | ๊ฒฐ๊ณผ |
|---|---|---|
| Parallel Route | @slot/page.tsx | ๋ ์ด์์์์ ์ฌ๋กฏ์ผ๋ก ๋์ ๋ ๋ |
| Intercepting | (.)route/page.tsx | ๋ค๋น๊ฒ์ด์ ์ ์ธํฐ์ ํธ, ์ง์ ์ ๊ทผ์ ์๋ณธ |
| URL ๋ชจ๋ฌ | Parallel + Intercepting ์กฐํฉ | Instagram ์คํ์ผ ๋ชจ๋ฌ |
โ ๏ธ ์ ๋ ํ์ง ๋ง ๊ฒ
| ์ํฉ | โ ๋์ ์ | โ ์ข์ ์ |
|---|---|---|
| ์ฌ๋กฏ ํด๋ฐฑ ์์ | @modal/default.tsx ์์ | ๋ฐ๋์ default.tsx ์ถ๊ฐ |
| ๋ชจ๋ฌ์ ๋ค๋ก๊ฐ๊ธฐ ์์ | router.push('/') | router.back() |
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. (.)posts/[id]/page.tsx ์์ (.) ์ด ์๋ฏธํ๋ ๊ฒ์?
- A) ํ์ฌ ๋๋ ํ ๋ฆฌ์ ํ์ผ ์ฐธ์กฐ
- B) ๊ฐ์ URL ์ธ๊ทธ๋จผํธ ๋ ๋ฒจ์ ๊ฒฝ๋ก ์ธํฐ์ ํธ
- C) ํ ๋จ๊ณ ์์ ๊ฒฝ๋ก ์ธํฐ์ ํธ
- D) ๋ฃจํธ ๊ฒฝ๋ก๋ถํฐ ์ธํฐ์ ํธ
โ ์ ๋ต: B
์ค๋ต ํด์ค:
- C โ
(..)๊ฐ ํ ๋จ๊ณ ์์- D โ
(...)๊ฐ ๋ฃจํธ๋ถํฐ๐ ํต์ฌ ๊ธฐ์ต๋ฒ:
.ํ๋ = ๊ฐ์ ๋ ๋ฒจ,..๋ ๊ฐ = ํ ๋จ๊ณ ์.
Q2. Instagram ์คํ์ผ URL ๋ชจ๋ฌ์์ ๋ชจ๋ฌ์ ๋ซ์ผ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋๊ฐ?
- A)
useState๋กisOpen = false - B)
router.push('/posts') - C)
router.back() - D) ๋ชจ๋ฌ ์ปดํฌ๋ํธ๋ฅผ
null๋ก ์กฐ๊ฑด๋ถ ๋ ๋
โ ์ ๋ต: C
ํด์ค:
router.back()์ด ํ์คํ ๋ฆฌ ์คํ์ ๋ค๋ก ์ด๋์ํค๋ฉด์ Intercepting Route๊ฐ ํด์ ๋์ด@modal์ฌ๋กฏ์ดdefault.tsx(null)๋ก ๋์๊ฐ.router.push()๋ ์ ํ์คํ ๋ฆฌ๋ฅผ ์ถ๊ฐํด์ ๋์ ๋ฐฉ์์ด ๋ฌ๋ผ.๐ ํต์ฌ ๊ธฐ์ต๋ฒ: ๋ชจ๋ฌ ๋ซ๊ธฐ = ๋ค๋ก๊ฐ๊ธฐ(
back). ํ์คํ ๋ฆฌ ์คํ์ ์ด์ฉํ๋ ๊ฑฐ์ผ.
Q3. ์น๊ตฌ์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
Intercepting Routes๊ฐ "๊ฐ์ URL์ธ๋ฐ ๋ค๋ฅด๊ฒ ๋ณด์ฌ์ค๋ค"๋ ๊ฒ ์ด๋ค ์๋ฏธ์ธ์ง ๋น์ ๋ก ์ค๋ช ํด๋ด.
์์ ๋ต๋ณ:
"๋์๊ด ๋น์ ์ผ. ๋์๊ด ๋ด๋ถ ์๋ฆฌ๋ฒ ์ดํฐ(Next.js ๋ค๋น๊ฒ์ด์ )๋ฅผ ํ๊ณ 3์ธต ์ด๋์ค์ ๊ฐ๋ฉด ์ด๋์ค ์ฌ์๊ฐ ์ฑ ์ ๋ฐ๋ก ๋ณด์ฌ์ค(๋ชจ๋ฌ). ๊ทผ๋ฐ ๊ฑด๋ฌผ ์ ๋ฌธ์ผ๋ก ์ง์ 3์ธต์ผ๋ก ์ฌ๋ผ๊ฐ๋ฉด(์ง์ URL ์ ๊ทผ) ๊ทธ๋ฅ ์ด๋์ค ์ ์ฒด๊ฐ ๋ณด์ฌ(์ ์ฒด ํ์ด์ง). ๊ฐ์ ์ฃผ์์ธ๋ฐ ์ด๋ป๊ฒ ์๋๋์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฒฝํ์ ์ ๊ณตํ๋ ๊ฑฐ์ผ."
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋์ ์ ๋ง ๋ฅ์คํธ ๋ผ์ฐํ
์ ๋ํ์์ด๋ผ ๋ถ๋ฆฌ๋ 'Parallel & Intercepting Routes' ๋ฅผ ๋ฐฐ์ฐ๋ฉด์ ๋จธ๋ฆฌ๊ฐ ์ด์ง์ด์งํ์ด. (.) ์ด๋ (..) ๊ฐ์ ์์ํ ๋ฌธ๋ฒ๋ค์ ๋ณด๋ฉด์ "์ด๊ฒ ๋์ฒด ๋ญ์ผ?" ์ถ์๋๋ฐ, ์ธ์คํ๊ทธ๋จ ๊ฐ์ ๋ณต์กํ ๋ชจ๋ฌ ๊ตฌ์กฐ๋ฅผ ์ด๋ ๊ฒ ์ฐ์ํ๊ฒ ํ ์ ์๋ค๋ ์ ๋ง ๋๋ผ์ ์ด.
๐ก ์ค๋์ ๊ตํ: "๋ณต์กํ UI ์ํ ๊ด๋ฆฌ์ ๋งค๋ชฐ๋์ง ๋ง์. Parallel & Intercepting Routes ๋ฅผ ํ์ฉํด URL๊ณผ UI๋ฅผ ์ผ์น์ํค๋ฉด, ์๋ก๊ณ ์นจํด๋ ๊นจ์ง์ง ์๋ ๊ฒฌ๊ณ ํ ์๋น์ค๋ฅผ ๋ง๋ค ์ ์๋ค!"
์ํธ ๋ฆฌ๋ ๋์ด ๋์๊ด ์๋ฆฌ๋ฒ ์ดํฐ ๋น์ ๋ฅผ ๋ค์ด ์ค๋ช ํด ์ฃผ์ค ๋, ์ธํฐ์ ํ ๋ผ์ฐํธ๊ฐ ์ '๊ฐ๋ก์ฑ๊ธฐ' ์ธ์ง ๋จ๋ฒ์ ์ดํด๊ฐ ๊ฐ๋๋ผ. ๋จ์ํ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฑธ ๋์ด, ์ฌ์ฉ์๊ฐ ์ด๋์ ์ ์ํ๋ ์ผ๊ด๋ ๊ฒฝํ์ ์ฃผ๋ ๊ฒ ์ผ๋ง๋ ์ค์ํ์ง ๊นจ๋ฌ์์ด. ์ค๋ ๋๋ฌด ๊ณ ์ํ ๋ ์์ ์๊ฒ ์์ํ ์์ด์ค ์๋ฉ๋ฆฌ์นด๋ ธ ํ ์ ์ฌ์ค์ผ์ง! ๋ด์ผ์ ๋ '์ฐ์ํ' ๋ผ์ฐํ ์ ์ค๊ณํ๋ ๊ฐ๋ฐ์๊ฐ ๋ ๊ฑฐ์ผ! ๐ฃ