Next.js の App Router では、app ディレクトリのフォルダ構成がそのまま URL になります。そのため関連するページをフォルダでまとめて整理しようとすると、意図しないパスが URL に増えてしまいがちです。そこで役立つのが Route Groups(ルートグループ)です。フォルダ名を丸括弧で囲むだけで、そのフォルダは URL に影響を与えずにファイルの整理役として使えるようになります。この記事では、Route Groups の基本的な考え方から、グループごとに異なる layout.tsx を適用する方法、複数のルートレイアウトへの分割、そしてパスの衝突といった注意点までを、具体的なフォルダ構成とあわせて解説します。
目次
Route Groups とは何か
App Router では、app の下に作ったフォルダ名がそのまま URL セグメントになります。たとえば app/about/page.tsx は /about に対応します。ところが、フォルダ名を丸括弧で囲んで (marketing) のように書くと、そのフォルダ名は URL パスに一切含まれません。ルーティングには影響を与えず、あくまでファイルを整理するためのグループとして機能します。これが Route Groups です。
たとえば app/(marketing)/about/page.tsx というファイルを置いても、生成される URL は /(marketing)/about ではなく /about になります。(marketing) の部分は URL から消えるので、「マーケティング関連のページ」という意味づけをフォルダに持たせつつ、実際のパスはきれいなまま保てます。
関連するルートをグループにまとめる
まずは一番シンプルな使い方として、役割の近いページを1つのグループにまとめてみます。会社紹介やブログのようなマーケティング系のページと、商品やカートのようなショップ系のページを、それぞれ別のグループに分けて整理します。
app/
├─ (marketing)/
│ ├─ about/
│ │ └─ page.tsx → /about
│ └─ blog/
│ └─ page.tsx → /blog
└─ (shop)/
├─ products/
│ └─ page.tsx → /products
└─ cart/
└─ page.tsx → /cart
この構成では、フォルダ上は (marketing) と (shop) という2つのグループに分かれていますが、生成される URL に括弧付きのフォルダ名は現れません。それぞれのファイルがどの URL に対応するかを整理すると、次のようになります。
| ファイルのパス | 生成される URL |
|---|---|
app/(marketing)/about/page.tsx | /about |
app/(marketing)/blog/page.tsx | /blog |
app/(shop)/products/page.tsx | /products |
app/(shop)/cart/page.tsx | /cart |
ポイントは、フォルダの階層が深くなっても URL は増えないことです。開発者にとってはファイルが目的ごとに分類されて見通しがよくなり、利用者にとっては URL がフラットで分かりやすい、という両方のメリットを同時に得られます。
グループごとに異なる layout.tsx を適用する
Route Groups の一番の利点は、グループ単位でレイアウトを分けられることです。App Router では、あるフォルダに layout.tsx を置くと、その配下のページすべてに共通のレイアウトが適用されます。しかし、URL 階層を増やさずに「一部のページだけ違うレイアウトにしたい」という場面はよくあります。たとえばマーケティングページには広いヘッダーとフッターを付け、ショップページにはサイドバー付きのレイアウトを使いたい、といったケースです。
各グループの中にそれぞれ layout.tsx を置けば、URL に影響を与えずにグループごとの見た目を切り替えられます。次のように、グループのフォルダ直下にレイアウトを用意します。
app/
├─ layout.tsx ← 全ページ共通の root layout
├─ (marketing)/
│ ├─ layout.tsx ← marketing グループ専用のレイアウト
│ └─ page.tsx → /
└─ (shop)/
├─ layout.tsx ← shop グループ専用のレイアウト
└─ cart/
└─ page.tsx → /cart
グループ専用の layout.tsx は、通常のレイアウトと同じく children を受け取ってラップするだけです。マーケティンググループのレイアウトを例に見てみます。
export default function MarketingLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
{/* marketing グループだけに表示するヘッダー */}
<header>マーケティング用ヘッダー</header>
<main>{children}</main>
<footer>マーケティング用フッター</footer>
</div>
);
}
このレイアウトは (marketing) グループ内のページにだけ適用され、(shop) グループのページには影響しません。(shop) 側には app/(shop)/layout.tsx を用意すれば、そちらだけ別の構成にできます。URL は / や /cart のまま変わらないのに、ページのまとまりごとに見た目や共通パーツを切り替えられるわけです。これが Route Groups を使う一番の動機になることが多いです。
複数のルートレイアウトに分割する
もう一歩進んだ使い方として、Route Groups を使ってアプリを複数のルートレイアウト(root layout)に分割することもできます。通常、App Router では app/layout.tsx が唯一の root layout として <html> や <body> を含みます。ここで app 直下に layout.tsx を置かず、代わりに各グループの中にそれぞれ root layout を持たせると、グループごとに完全に独立した <html> 構造を持てます。
app/ ├─ (marketing)/ │ ├─ layout.tsx ← html/body を含む独立した root layout │ └─ page.tsx → / └─ (shop)/ ├─ layout.tsx ← html/body を含む別の root layout └─ page.tsx → /shop など
この場合、各グループの layout.tsx がそれぞれ <html> と <body> タグを出力する必要があります。グループごとにまったく異なる土台(言語設定、フォント、グローバルスタイルなど)を持たせたいときに有効です。ただし、app 直下に共通の layout.tsx がなくなるため、別々の root layout をまたぐ画面遷移は通常のクライアント側遷移ではなくページ全体の再読み込みになる点は覚えておきましょう。用途としては、ランディングページ群と管理画面群のように、性格が大きく異なる領域を1つのプロジェクトで扱う場合などが向いています。
同じ URL になるパスは衝突する
Route Groups を使ううえで一番つまずきやすいのが、パスの衝突です。グループ名は URL に含まれないため、異なるグループであっても、その中に同じパスになるページを作るとルートが重複してビルド時にエラーになります。
app/
├─ (a)/
│ └─ about/
│ └─ page.tsx → /about
└─ (b)/
└─ about/
└─ page.tsx → /about ← どちらも /about になり衝突!
上の例では、(a)/about と (b)/about はグループ名が消えるため、どちらも /about という同じ URL を指します。Next.js はどちらのページを表示すべきか決められないので、「同じルートを解決できない」という趣旨のエラーになります。グループを分けても URL 空間は共有されている、という点を意識して、パスが重ならないように設計してください。
丸括弧と角括弧を混同しない
最後に、フォルダ名の記号について混同しやすい点を補足します。丸括弧の (folder) は今回紹介した Route Group で、URL に影響を与えません。一方、角括弧の [folder] は動的ルート(Dynamic Route)で、こちらは [id] のように URL の可変部分を表し、実際にパスの一部として使われます。見た目が似ているため取り違えやすいですが、役割はまったく逆です。
| 書き方 | 意味 | URL への影響 |
|---|---|---|
(folder) | Route Group(整理用) | URL に含まれない |
[folder] | Dynamic Route(動的ルート) | URL の可変部分になる |
まとめ
Route Groups は、フォルダ名を丸括弧で囲むことで、URL に影響を与えずにルートを整理できる App Router の仕組みです。関連するページをグループにまとめて見通しをよくするだけでなく、グループごとに異なる layout.tsx を適用したり、複数の独立した root layout に分割したりできる点が大きな利点です。特に「URL 階層は増やしたくないが、一部のページだけレイアウトを変えたい」という場面で威力を発揮します。ただし、グループ名は URL から消えるため、異なるグループでも同じパスになるページを作ると衝突する点には注意が必要です。丸括弧の (folder) は整理用の Route Group、角括弧の [folder] は動的ルートである、という違いもあわせて押さえておきましょう。