9. 경로 가로채기(Intercepting Routes)
✅ Intercepting Routes란?
Intercepting Routes는 Next.js에서 특정 경로를 가로채서 현재 페이지 위에 새로운 UI(예: 모달, 슬라이드 패널 등)를 표시하는 기능이다.
➡️ 즉, 새로운 페이지로 완전히 이동하지 않고, 현재 페이지 위에 겹쳐서 특정 UI를 보여줄 수 있도록 해준다.
✅ 왜 필요한가?
보통 모달을 구현할 때 사용된다.
예를 들어, 사용자가 /products
페이지에서 상품 목록을 보고 있다가, 특정 상품을 클릭하면 상품 상세 페이지를 모달로 표시하고 싶을 때 유용하다.
기존 방식
- 상품 목록
/products
→ 상품 상세/products/1
로 이동하면 페이지가 새로고침됨
Intercepting Routes 사용 시
/products
위에/products/1
을 모달로 겹쳐서 표시할 수 있음- 뒤로 가기 버튼을 누르면 모달만 닫히고
/products
페이지는 그대로 유지됨
✅ 규칙(Convention)
경로 가로채기는 (..)
규칙을 사용하여 정의할 수 있으며, 이는 파일 시스템의 상대 경로(../
)와 유사하지만, 라우트 세그먼트(segment) 단위로 동작한다.
사용할 수 있는 규칙은 다음과 같다.
(.)
→ 같은 수준의 세그먼트를 일치시킴(..)
→ 한 단계 위의 세그먼트를 일치시킴(..)(..)
→ 두 단계 위의 세그먼트를 일치시킴(...)
→ 애플리케이션의 루트(app 디렉토리)부터 세그먼트를 일치시킴
풀어서 이해하기
여기서 "일치시킨다(match)" 는 말은 특정 경로(라우트)가 기존 경로 대신 특정 경로를 가로채서(인터셉트해서) 렌더링된다는 의미이다.
(..)
규칙은 파일 시스템에서 ../
로 한 단계 위의 디렉토리로 이동하는 것과 비슷한 방식으로 경로를 가로채는 기능을 한다. 다만, 여기서는 디렉토리 대신 Next.js의 라우트 세그먼트(segment) 단위로 동작한다.
예제 📝
📂 디렉토리 구조

/photo
경로로 접근하면 기본적으로app/photo/page.tsx
가 렌더링됨- 하지만
/feed
내부에서/photo
경로로 이동하면,app/photo/page.tsx
대신app/feed/(..)photo/page.tsx
가 렌더링됨
→ 즉, 기존/photo
경로를 가로채서(Intercept
),feed/(..)photo/page.tsx
의 내용을 보여줌
📌 (..) 규칙 정리
규칙 | 설명 |
(.) |
현재 경로(같은 세그먼트)에서 가로채기 |
(..) |
한 단계 위 세그먼트에서 가로채기 |
(..)(..) |
두 단계 위 세그먼트에서 가로채기 |
(...) |
애플리케이션 루트부터 가로채기 |
➡ 쉽게 말해, (..)
를 사용하면 특정 경로의 내용을 기존 페이지가 아니라 다른 페이지로 바꿀 수 있다는 뜻!
✅ Intercepting Routes 사용 예제 (모달)
1️⃣ 기본 설정
📁 폴더 구조
/app ├── layout.tsx ├── page.tsx # 기본 페이지 ├── products │ ├── page.tsx # 상품 목록 페이지 (/products) │ ├── [id] │ │ ├── page.tsx # 상품 상세 페이지 (/products/1) │ │ ├── @modal │ │ │ ├── page.tsx # 상품 상세 모달 (/products/1 - 모달)
2️⃣ 상품 목록 페이지 (/products
)
// app/products/page.tsx "use client"; import Link from "next/link"; export default function Products() { const products = [ { id: 1, name: "상품 A" }, { id: 2, name: "상품 B" }, ]; return ( <div> <h1>상품 목록</h1> {products.map((product) => ( <Link key={product.id} href={`/products/${product.id}`} as={`/products/${product.id}`} scroll={false}> <div className="border p-2 cursor-pointer"> {product.name} </div> </Link> ))} </div> ); }
✔️ scroll={false}
: 모달을 열 때 페이지 스크롤 위치 유지
3️⃣ 상품 상세 페이지 (/products/1
)
// app/products/[id]/page.tsx export default function ProductDetail({ params }: { params: { id: string } }) { return ( <div> <h1>상품 상세 페이지</h1> <p>상품 ID: {params.id}</p> </div> ); }
✔️ /products/1
에 들어가면 일반적인 페이지 이동이 발생
4️⃣ 모달을 위한 Intercepting Route (/products/1
을 모달로 표시)
// app/products/[id]/@modal/page.tsx "use client"; import { useRouter } from "next/navigation"; export default function ProductModal({ params }: { params: { id: string } }) { const router = useRouter(); return ( <div className="fixed inset-0 bg-black/50 flex justify-center items-center"> <div className="bg-white p-4 rounded shadow-lg"> <h1>상품 상세 모달</h1> <p>상품 ID: {params.id}</p> <button onClick={() => router.back()} className="mt-2 bg-gray-200 p-2"> 닫기 </button> </div> </div> ); }
✔️ router.back()
을 사용하면 뒤로 가기 버튼을 눌렀을 때 모달만 닫히고 /products
페이지는 그대로 유지됨
✔️ @modal
을 사용하면 현재 페이지 위에 모달 형태로 겹쳐서 표시 가능
✅ Intercepting Routes 정리
- 일반적인 페이지 이동 없이 특정 UI(모달 등)를 현재 페이지 위에 겹쳐서 표시할 수 있음.
- 뒤로 가기(History API)를 사용하여 모달만 닫고 현재 페이지를 유지할 수 있음
- 페이지 전체를 다시 로드하지 않고 부드러운 UX를 제공 가능
추가 : Intercepting Routes의 Soft Navigation vs. Hard Navigation
🔹 Soft Navigation (부드러운 네비게이션)
✔️ 현재 페이지(백그라운드)를 유지하면서 새로운 UI를 오버레이
✔️ 페이지 전체가 새로고침되지 않고, 상태(state)가 유지됨
✔️ Next.js에서 Intercepting Routes를 활용하면 모달 같은 UI를 Soft Navigation으로 구현 가능
✔️ URL이 변경되지만, 기존 페이지 콘텐츠는 그대로 남아 있음
📌 예제: 모달을 Soft Navigation으로 띄우기
// app/feed/`(..)`photo/page.tsx "use client"; import { useRouter } from "next/navigation"; export default function PhotoModal() { const router = useRouter(); return ( <div className="fixed inset-0 bg-black/50 flex justify-center items-center"> <div className="bg-white p-4 rounded"> <h1>사진 상세 모달</h1> <button onClick={() => router.back()}>닫기</button> </div> </div> ); }
✅ /feed/photo
방문 시 모달이 뜨고, 기존 feed
페이지는 그대로 있음
✅ 뒤로 가기(router.back()
) 시 모달만 닫힘, 기존 feed
페이지 유지됨
🔹 Hard Navigation (완전한 네비게이션)
✔️ 기존 UI를 제거하고 새 페이지로 완전히 이동
✔️ 브라우저가 전체 페이지를 다시 로드할 수도 있음
✔️ 페이지 전환 시 상태(state)가 초기화됨
✔️ 백그라운드 UI 없음, 브라우저 새로고침과 비슷
✔️ 일반적인 페이지 전환 방식과 동일
📌 예제: Hard Navigation
// 특정 버튼 클릭 시 Hard Navigation 실행 "use client"; import { useRouter } from "next/navigation"; export default function GoToPhotoPage() { const router = useRouter(); return ( <button onClick={() => router.push("/feed/photo")}> 사진 페이지로 이동 </button> ); }
✅ /feed/photo
이동 시 기존 feed
페이지가 사라지고 완전히 새로운 페이지로 로드됨
✅ 새로고침한 것처럼 동작하여 기존 상태(state)가 사라질 수 있음
🔹 Soft vs. Hard 네비게이션 차이 정리
Soft Navigation | Hard Navigation | |
기존 페이지 유지 | 유지됨 | 제거됨 |
백그라운드 UI | 있음 (예: 모달) | 없음 |
네비게이션 속도 | 빠름 (클라이언트 사이드) | 느림 (완전한 페이지 로드) |
사용 예시 | 모달, 사이드바 | 일반적인 페이지 전환 |
✅ 정리
- Soft Navigation → 기존 페이지 유지하면서 새로운 UI 추가 (모달, 사이드바)
- Hard Navigation → 기존 페이지를 제거하고 완전히 새로운 페이지로 이동
Intercepting Routes 활용하면 Soft Navigation으로 부드러운 UX 구현 가능
https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes
Routing: Intercepting Routes | Next.js
Use intercepting routes to load a new route within the current layout while masking the browser URL, useful for advanced routing patterns such as modals.
nextjs.org
'웹 프로그래밍 > Next.js' 카테고리의 다른 글
[Next.js 공식문서 정리] Routing : 08. Parallel Routes (1) | 2025.03.29 |
---|---|
[Next.js 공식문서 정리] Routing : 07. Dynamic Routes.md (0) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 06. Route Groups (0) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 05. Redirecting (0) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 04. Loading UI and Streaming (2) | 2025.03.29 |
[Next.js 공식문서 정리] Routing : 03. Error Handling (0) | 2025.03.29 |