Parallel Routes
λ³λ ¬ κ²½λ‘(Parallel Routes)λ₯Ό μ¬μ©νλ©΄ λμΌν λ μ΄μμ λ΄μμ νλ μ΄μμ νμ΄μ§λ₯Ό λμμ λλ 쑰건λΆλ‘ λ λλ§ν μ μμ΅λλ€.
λμ보λλ μμ
μ¬μ΄νΈμ νΌλμ κ°μ΄ μ±μ λ§€μ° λμ μΈ μΉμ
μ μ μ©ν©λλ€.
μλ₯Ό λ€μ΄, λμ보λλ₯Ό κ³ λ €ν λ, λ³λ ¬ κ²½λ‘λ₯Ό μ¬μ©νμ¬ team νμ΄μ§μ analytics νμ΄μ§λ₯Ό λμμ λ λλ§ν μ μμ΅λλ€:

1. Slots(μ¬λ‘―; μ리)
λ³λ ¬ κ²½λ‘λ λͺ
λͺ
λ Slotsμ μ¬μ©νμ¬ λ§λ€μ΄μ§λλ€. Slotsμ @folder κ·μΉμΌλ‘ μ μλ©λλ€.
μλ₯Ό λ€μ΄, λ€μ νμΌ κ΅¬μ‘°λ λ κ°μ Slotsμ μ μν©λλ€: @analyticsκ³Ό @team:

Slotsμ 곡μ λΆλͺ¨ λ μ΄μμμ propsμΌλ‘ μ λ¬λ©λλ€.
μμ μμ μμ, app/layout.jsμ μ»΄ν¬λνΈλ μ΄μ @analytics λ° @team μ¬λ‘― propsμ νμ©νλ©°,
νμ propsκ³Ό ν¨κ» λ³λ ¬λ‘ λ λλ§ν μ μμ΅λλ€:
1export default function Layout({2children,3team,4analytics,5}: {6children: React.ReactNode7analytics: React.ReactNode8team: React.ReactNode9}) {10return (11<>12{children}13{team}14{analytics}15</>16)17}
κ·Έλ¬λ Slotsμ κ²½λ‘ μΈκ·Έλ¨ΌνΈκ° μλλ©° URL ꡬ쑰μ μν₯μ λ―ΈμΉμ§ μμ΅λλ€.
μλ₯Ό λ€μ΄, /dashboard/@analytics/viewsμ κ²½μ°, @analyticsκ° Slotsμ΄λ―λ‘ URLμ /dashboard/viewsκ° λ©λλ€.
μμλλ©΄ μ μ©ν©λλ€:
μμ νλ‘νΌν°λ ν΄λμ λ§€νν νμκ° μλ μμμ Slotsμ λλ€. μ¦,
app/page.jsλapp/@children/page.jsμ λμΌν©λλ€.
2. Active state and navigation
κΈ°λ³Έμ μΌλ‘, Next.jsλ κ° slotμ νμ± μν(λλ νμ νμ΄μ§)λ₯Ό μΆμ ν©λλ€. κ·Έλ¬λ, μ¬λ‘― λ΄μμ λ λλ§λλ μ½ν μΈ λ νμ μ νμ λ°λΌ λ¬λΌμ§λλ€:
μννΈ νμ(soft navigation):- ν΄λΌμ΄μΈνΈ μΈ‘ νμ μ€μ Next.jsλ λΆλΆ λ λλ§μ μννμ¬ μ¬λ‘― λ΄μ νμ νμ΄μ§λ₯Ό λ³κ²½νλ λμμ,
- λ€λ₯Έ μ¬λ‘―μ νμ± νμ νμ΄μ§λ νμ¬ URLκ³Ό μΌμΉνμ§ μλλΌλ μ μ§ν©λλ€.
νλ νμ(hard navigation):- μ 체 νμ΄μ§ λ‘λ(λΈλΌμ°μ μλ‘ κ³ μΉ¨) ν Next.jsλ νμ¬ URLκ³Ό μΌμΉνμ§ μλ μ¬λ‘―μ νμ± μνλ₯Ό νμΈν μ μμ΅λλ€.
- λμ μΌμΉνμ§ μλ μ¬λ‘―μ λν΄
default.jsνμΌμ λ λλ§νκ±°λ,default.jsκ° μ‘΄μ¬νμ§ μλ κ²½μ°, 404λ₯Ό λ λλ§ν©λλ€.
μμλλ©΄ μ μ©ν©λλ€:
μΌμΉνμ§ μλ κ²½λ‘μ λν 404λ μλνμ§ μμ νμ΄μ§μ μ€μλ‘ λ³λ ¬ κ²½λ‘κ° λ λλ§λλ κ²μ λ°©μ§νλ λ° λμμ΄ λ©λλ€.
2.1 default.js
μ΄κΈ° λ‘λ λλ μ 체 νμ΄μ§ λ€μ λ‘λ μ€μ μΌμΉνμ§ μλ slotμ λν ν΄λ°±μΌλ‘ λ λλ§ν default.js νμΌμ μ μν μ μμ΅λλ€.
λ€μ ν΄λ ꡬ쑰λ₯Ό κ³ λ €νμΈμ. @team μ¬λ‘―μλ /settings νμ΄μ§κ° μμ§λ§, @analyticsμλ μ€μ νμ΄μ§κ° μμ΅λλ€.

/dashboard/settingsμΌλ‘ μ΄λν λ, @team slotμ @analytics slotμ νμ¬ νμ± νμ΄μ§λ₯Ό μ μ§νλ©΄μ, /settings νμ΄μ§λ₯Ό λ λλ§ν©λλ€.
μλ‘ κ³ μΉ¨ μ, Next.jsλ @analyticsμ λν default.jsλ₯Ό λ λλ§ν©λλ€. default.jsκ° μ‘΄μ¬νμ§ μμΌλ©΄ 404κ° λμ λ λλ§λ©λλ€.
λν childrenλ μμμ slotμ΄λ―λ‘, Next.jsκ° μμ νμ΄μ§μ νμ± μνλ₯Ό 볡ꡬν μ μλ κ²½μ°,
νμ νμ΄μ§μ λν ν΄λ°±μ λ λλ§νλ default.js νμΌλ λ§λ€μ΄μΌ ν©λλ€.
2.2 useSelectedLayoutSegment(s)
useSelectedLayoutSegment μ useSelectedLayoutSegments λ λͺ¨λ μ¬λ‘― λ΄μμ νμ± κ²½λ‘ μΈκ·Έλ¨ΌνΈλ₯Ό μ½μ μ μλ parallelRoutesKey λ§€κ°λ³μλ₯Ό νμ©ν©λλ€.
1'use client'23import { useSelectedLayoutSegment } from 'next/navigation'45export default function Layout({ auth }: { auth: React.ReactNode }) {6const loginSegments = useSelectedLayoutSegment('auth')7// ...8}
μ¬μ©μκ° app/@auth/login(λλ URL νμμ€μ /login)μΌλ‘ μ΄λνλ©΄ loginSegmentsλ "login" λ¬Έμμ΄κ³Ό λμΌν©λλ€.
3. μμ
3.1 Conditional(쑰건λΆ) Routes
λ³λ ¬ κ²½λ‘λ₯Ό μ¬μ©νμ¬ μ¬μ©μ μν κ³Ό κ°μ νΉμ 쑰건μ λ°λΌ 쑰건λΆλ‘ κ²½λ‘λ₯Ό λ λλ§ν μ μμ΅λλ€.
μλ₯Ό λ€μ΄, /admin λλ /user μν μ λν΄ λ€λ₯Έ λμ보λ νμ΄μ§λ₯Ό λ λλ§ν μ μμ΅λλ€:

1import { checkUserRole } from '@/lib/auth'23export default function Layout({ user, admin }: { user: React.ReactNode; admin: React.ReactNode }) {4const role = checkUserRole()5return <>{role === 'admin' ? admin : user}</>6}
3.2 Tab Groups
μ¬λ‘― μμ layoutμ μΆκ°νμ¬, μ¬μ©μκ° μ¬λ‘―μ λ
립μ μΌλ‘ νμν μ μλλ‘ ν μ μμ΅λλ€. μ΄ κΈ°λ₯μ νμ λ§λ€ λ μ μ©ν©λλ€.
μλ₯Ό λ€μ΄, @analytics μ¬λ‘―μλ λ κ°μ νμ νμ΄μ§κ° μμ΅λλ€: /page-views λ° /visitors.

@analytics λ΄μμ, layout νμΌμ λ§λ€μ΄ λ νμ΄μ§ κ°μ νμ 곡μ ν©λλ€:
1import Link from 'next/link'23export default function Layout({ children }: { children: React.ReactNode }) {4return (5<>6<nav>7<Link href="/dashboard/page-views">Page Views</Link>8<Link href="/dashboard/visitors">Visitors</Link>9</nav>10<div>{children}</div>11</>12)13}
3.3 Modal
λ³λ ¬ κ²½λ‘λ₯Ό μΈν°μ ν κ²½λ‘μ ν¨κ» μ¬μ©νμ¬ λͺ¨λ¬μ λ§λ€ μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λͺ¨λ¬μ λ§λ€ λ λ€μκ³Ό κ°μ μΌλ°μ μΈ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€:
- URLμ ν΅ν΄ λͺ¨λ¬ μ½ν μΈ λ₯Ό 곡μ ν μ μλλ‘ μ€μ ν©λλ€.
- νμ΄μ§λ₯Ό μλ‘ κ³ μΉ λ λͺ¨λ¬μ λ«λ λμ 컨ν μ€νΈλ₯Ό μ μ§ν©λλ€.
- μ΄μ κ²½λ‘λ‘ μ΄λνμ§ μκ³ λ€λ‘ νμν λ λͺ¨λ¬μ λ«μ΅λλ€.
- μμΌλ‘ νμμμ λͺ¨λ¬μ λ€μ μ½λλ€.
μ¬μ©μκ° ν΄λΌμ΄μΈνΈ μΈ‘ νμμ μ¬μ©νμ¬ λ μ΄μμμμ λ‘κ·ΈμΈ λͺ¨λ¬μ μ΄κ±°λ λ³λμ /login νμ΄μ§μ μ‘μΈμ€ν μ μλ, λ€μ UI ν¨ν΄μ κ³ λ €νμΈμ:

μ΄ ν¨ν΄μ ꡬννλ €λ©΄, λ¨Όμ κΈ°λ³Έ λ‘κ·ΈμΈ νμ΄μ§λ₯Ό λ λλ§νλ /login κ²½λ‘λ₯Ό μμ±ν©λλ€.

1import { Login } from '@/app/ui/login'23export default function Page() {4return <Login />5}
κ·Έλ° λ€μ @auth μ¬λ‘―μ, nullμ λ°ννλ default.js νμΌμ μΆκ°ν©λλ€.
μ΄λ κ² νλ©΄ λͺ¨λ¬μ΄ νμ±νλμ΄ μμ§ μμ λ λ λλ§λμ§ μμ΅λλ€.
1export default function Default() {2return null3}
@auth μ¬λ‘― λ΄μμ /(.)login ν΄λλ₯Ό μ
λ°μ΄νΈνμ¬ /login κ²½λ‘λ₯Ό κ°λ‘μ±μΈμ.
<Modal> μ»΄ν¬λνΈμ κ·Έ νμ μ»΄ν¬λνΈλ₯Ό /(.)login/page.tsx νμΌλ‘ κ°μ Έμ΅λλ€:
1import { Modal } from '@/app/ui/modal'2import { Login } from '@/app/ui/login'34export default function Page() {5return (6<Modal>7<Login />8</Modal>9)10}
μμλλ©΄ μ μ©ν©λλ€:
- κ²½λ‘λ₯Ό κ°λ‘μ±λ λ° μ¬μ©λλ κ·μΉ(e.g.:
(.))μ νμΌ μμ€ν ꡬ쑰μ λ°λΌ λ€λ¦ λλ€. κ²½λ‘ μΈν°μ νΈ κ·μΉμ μ°Έμ‘°νμμμ€.<Modal>κΈ°λ₯μ λͺ¨λ¬ μ½ν μΈ (<Login>)μ λΆλ¦¬νλ©΄ λͺ¨λ¬ λ΄λΆμ λͺ¨λ μ½ν μΈ (μ:forms)κ° μλ² μ»΄ν¬λνΈμΈμ§ νμΈν μ μμ΅λλ€.
- μμΈν λ΄μ©μ ν΄λΌμ΄μΈνΈ λ° μλ² μ»΄ν¬λνΈ μΈν°λ¦¬λΉμ μ°Έμ‘°νμΈμ.
3.3.1 λͺ¨λ¬ μ΄κΈ°
μ΄μ Next.js λΌμ°ν°λ₯Ό νμ©νμ¬ λͺ¨λ¬μ μ΄κ³ λ«μ μ μμ΅λλ€. μ΄λ κ² νλ©΄ λͺ¨λ¬μ΄ μ΄λ € μμ λμ μλ€λ‘ νμν λ URLμ΄ μ¬λ°λ₯΄κ² μ λ°μ΄νΈλ©λλ€.
λͺ¨λ¬μ μ΄λ €λ©΄, @auth μ¬λ‘―μ λΆλͺ¨ λ μ΄μμμ νλ‘νΌν°λ‘ μ λ¬νκ³ , children νλ‘νΌν°μ ν¨κ» λ λλ§ν©λλ€.
1import Link from 'next/link'23export default function Layout({ auth, children }: { auth: React.ReactNode; children: React.ReactNode }) {4return (5<>6<nav>7<Link href="/login">Open modal</Link>8</nav>9<div>{auth}</div>10<div>{children}</div>11</>12)13}
μ¬μ©μκ° <Link>λ₯Ό ν΄λ¦νλ©΄, /login νμ΄μ§λ‘ μ΄λνλ λμ λͺ¨λ¬μ΄ μ΄λ¦½λλ€.
κ·Έλ¬λ, μλ‘ κ³ μΉ¨ λλ μ΅μ΄ λ‘λ μμλ /loginμΌλ‘ μ΄λνλ©΄, κΈ°λ³Έ λ‘κ·ΈμΈ νμ΄μ§λ‘ μ΄λν©λλ€.
3.3.2 λͺ¨λ¬ λ«κΈ°
router.back()μ νΈμΆνκ±°λ, Link μ»΄ν¬λνΈλ₯Ό μ¬μ©νμ¬ λͺ¨λ¬μ λ«μ μ μμ΅λλ€.
1'use client'23import { useRouter } from 'next/navigation'45export function Modal({ children }: { children: React.ReactNode }) {6const router = useRouter()78return (9<>10<button11onClick={() => {12router.back()13}}14>15Close modal16</button>17<div>{children}</div>18</>19)20}
Link μ»΄ν¬λνΈλ₯Ό μ¬μ©νμ¬ λ μ΄μ @auth μ¬λ‘―μ λ λλ§ν΄μλ μ λλ νμ΄μ§μμ λ€λ₯Έ νμ΄μ§λ‘ μ΄λνλ κ²½μ°,
nullλ₯Ό λ°ννλ catch-all κ²½λ‘λ₯Ό μ¬μ©ν©λλ€.
1import Link from 'next/link'23export function Modal({ children }: { children: React.ReactNode }) {4return (5<>6<Link href="/">Close modal</Link>7<div>{children}</div>8</>9)10}
1export default function CatchAll() {2return null3}
μμλλ©΄ μ μ©ν©λλ€:
- νμ± μν λ° νμμ μ€λͺ λ λμ λλ¬Έμ λͺ¨λ¬μ λ«μ λ,
@authμ¬λ‘―μ ν¬κ΄μ μΈ κ²½λ‘λ₯Ό μ¬μ©ν©λλ€.
- λ μ΄μ μ¬λ‘―κ³Ό μΌμΉνμ§ μλ κ²½λ‘μ λν ν΄λΌμ΄μΈνΈ μΈ‘ νμμ΄ κ³μ νμλλ―λ‘,
- λͺ¨λ¬μ λ«μΌλ €λ©΄ μ¬λ‘―μ nullμ λ°ννλ κ²½λ‘μ μΌμΉμμΌμΌ ν©λλ€.
- λ€λ₯Έ μλ‘λ κ°€λ¬λ¦¬μμ μ¬μ§ λͺ¨λ¬μ μ΄λ©΄μ μ μ©
/photo/[id]νμ΄μ§λ ν¨κ» μ΄κ±°λ, μ¬μ΄λ λͺ¨λ¬μμ μΌν μΉ΄νΈλ₯Ό μ¬λ κ² λ±μ΄ μμ΅λλ€.- κ°λ‘μ±κΈ° λ° λ³λ ¬ κ²½λ‘κ° μλ λͺ¨λ¬μ μμλ₯Ό νμΈνμΈμ.
3.4 λ‘λ© λ° μ€λ₯ UI
λ³λ ¬ κ²½λ‘(Parallel Routes)λ₯Ό λ
립μ μΌλ‘ μ€νΈλ¦¬λ°ν μ μμΌλ―λ‘, κ° κ²½λ‘μ λν΄ λ
립μ μΈ μ€λ₯ λ° λ‘λ© μνλ₯Ό μ μν μ μμ΅λλ€:

μμΈν λ΄μ©μ λ‘λ© UI λ° μ€λ₯ μ²λ¦¬ λ¬Έμλ₯Ό μ°Έμ‘°νμΈμ.