Next.js App Routerとは?最適なディレクトリ構成と移行完全ガイド
コセケン
テクラル合同会社

Next.js App Routerの導入でプロジェクトが失敗しないための最大のポイントは、サーバーとクライアントの境界設計(Client Boundary)を初期段階で明確にすることです。本記事では、Next.js App Routerとは何かという基本概念から、ディレクトリ構成の最適化、データフェッチの実践的なノウハウまでを具体的に解説します。
従来のPages Routerからの移行を検討している方や、新規事業でモダンな技術スタックを採用したい開発責任者に向けて、現場で直面する課題とその解決策をコード例を交えて提供します。
Next.js App Routerとは?RSCの基本概念

Next.js App Routerとは、React 18から導入されたReact Server Components(RSC)を前提として設計された、新しいルーティングシステムおよびレンダリングアーキテクチャです。
従来のアーキテクチャでは、コンポーネントを描画するためのロジックや依存ライブラリがすべてブラウザに送信されていました。しかし、App Routerではデフォルトですべてのコンポーネントがサーバーコンポーネントとして扱われます。サーバー側でHTMLを生成し、必要な結果だけをクライアントに返すことで、クライアント側に送信されるJavaScriptのバンドルサイズを大幅に削減できます。
これにより、初期ロード時間の短縮や、Core Web Vitalsのスコア向上が期待できます。特に、SEO(検索エンジン最適化)と初期表示速度がビジネス成果に直結する大規模なBtoBのSaaSやメディアプラットフォームにおいて、その恩恵は絶大です。
Pages Routerとの比較と移行のポイント
Next.js App Routerの導入を検討する際、従来のPages Routerとの違いを正確に把握することが重要です。以下の表に、主要な機能の比較をまとめました。
| 比較項目 | Pages Router | App Router |
|---|---|---|
| レンダリングの基本 | クライアントコンポーネント中心 | サーバーコンポーネント中心 (RSC) |
| ルーティング方式 | ファイルシステムベース (pages/ ディレクトリ) |
ディレクトリベース (app/ ディレクトリ) |
| データフェッチ | getServerSideProps などの専用関数を使用 |
拡張された fetch APIと非同期コンポーネント |
| レイアウト管理 | _app.js などで全体に一律適用 |
ディレクトリごとのネスト可能なレイアウト (layout.tsx) |
| キャッシュ制御 | ページ単位でのISR | リクエスト単位のきめ細やかなキャッシュ制御 |
具体的なユースケースでの違い(ECサイトの例)
例えば、頻繁に在庫や価格が変動するECサイトの商品詳細ページを構築する場合を考えてみましょう。
Pages Routerでは、ページ全体に対して getServerSideProps で毎回データを取得するか、getStaticProps と ISR を使って一定時間ごとの更新を待つ必要がありました。このため、変更の必要がない静的なヘッダーやフッターまで巻き込んで再レンダリング処理が行われていました。
一方、App Routerでは、ヘッダーなどの共通レイアウト(layout.tsx)は静的にキャッシュしたまま、商品在庫や価格など頻繁に変わる部分だけを個別のサーバーコンポーネントとして切り出し、動的にフェッチすることが可能です。これにより、サーバーの負荷を抑えつつ、ユーザーには常に最新の情報を高速に届けることができます。
新規事業の立ち上げ期においては、新しい技術の学習コストが開発スピードのボトルネックになるリスクがあります。App Routerは強力ですが、サーバーとクライアントの境界設計など、キャッチアップすべき概念が少なくありません。まずは素早く仮説検証を行いたいフェーズであれば、使い慣れた技術で市場に投入することも一つの正解です。このような事業の初期段階における方針決定については、MVP開発の進め方 や 新規事業立ち上げのプロセス も参考にしながら、技術選定とビジネススピードのバランスを見極めることが重要です。
既存のPages Routerからの移行を検討する場合、段階的な移行が可能です。pages/ と app/ は共存できるため、影響の少ない管理画面の一部や静的ページから徐々に移行していくアプローチが推奨されます。
Next.js App Routerのディレクトリ構成の最適化

App Routerでは、app ディレクトリ配下のフォルダ名がそのままURLのパスとなり、その中の page.tsx や layout.tsx が特別な役割を持ちます。この仕組みを活かしたNext.js App Routerのディレクトリ構成の最適化が、保守性の高いアプリケーション開発の鍵となります。
推奨されるアプローチは、ルーティングに関係のないコンポーネントやテストファイル、スタイルシートを同じディレクトリに配置する「コロケーション(Colocation)」です。
app/
├── layout.tsx
├── page.tsx
└── dashboard/
├── layout.tsx
├── page.tsx
├── components/
│ ├── button.tsx
│ └── chart.tsx
└── utils/
└── format-date.ts
このように、特定のルートでしか使用しないコンポーネントやユーティリティ関数を、そのルートのディレクトリ内に閉じ込めることで、影響範囲が明確になり、コードの可読性が向上します。ルールを決めずにファイルを配置すると、ディレクトリのネストが深くなりすぎるため、開発チーム内で明確なディレクトリ設計の規約を設けることが不可欠です。
データフェッチとキャッシュ戦略の実践ノウハウ

従来の getServerSideProps や getStaticProps といった関数は廃止され、標準のWeb APIである fetch を拡張したキャッシュ機構へと移行しました。これにより、コンポーネント単位で柔軟なデータ取得が可能になりました。
fetch APIを活用したキャッシュ制御
App Routerの fetch は、デフォルトでリクエスト結果をキャッシュします。データの更新頻度に合わせて、キャッシュの生存期間(Revalidation)を適切に設計することが重要です。
// 1時間(3600秒)ごとにキャッシュを再検証する例
async function getData() {
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 }
});
if (!res.ok) throw new Error('Failed to fetch data');
return res.json();
}
export default async function Page() {
const data = await getData();
return <main>{data.title}</main>;
}
ウォーターフォール問題の回避
複数の非同期処理を直列で実行すると、全体のレスポンスタイムが遅延する「ウォーターフォール問題」が発生します。関連性のないデータ取得は Promise.all を活用して並列でフェッチすることで、サーバーサイドでの処理時間を大幅に短縮できます。
async function Page() {
// 並列でデータを取得
const [userData, postsData] = await Promise.all([
getUser(),
getPosts()
]);
return (
<div>
<UserProfile user={userData} />
<PostList posts={postsData} />
</div>
);
}
現場で失敗しないための境界設計
実際にApp Routerを運用するにあたり、最も注意すべき点がサーバーコンポーネントとクライアントコンポーネントの境界設計(Client Boundary)です。
ユーザーのクリックイベントや状態管理(useState)が必要な部分にのみ、ファイルの先頭で "use client" を宣言してクライアントコンポーネントに切り替えます。この境界を誤り、ルートレイアウト(app/layout.tsx)の直下で安易に "use client" を宣言してしまうと、そこにネストされるすべての子コンポーネントがクライアント側に巻き込まれ、結果的にバンドルサイズが増大してしまいます。
クライアントコンポーネントは、コンポーネントツリーの末端(葉)のノードに配置するよう心がけてください。インタラクティブなボタンやフォームなど、必要最小限のUIパーツのみを切り出し、レイアウトやデータ取得を担う親コンポーネントはサーバーコンポーネントのまま維持する設計が理想的です。
よくある質問
Next.js App Routerへの移行は必須ですか?
必須ではありません。Next.jsはPages RouterとApp Routerの共存をサポートしており、公式も段階的な移行を推奨しています。新規プロジェクトであればApp Routerの採用が推奨されますが、既存プロジェクトの場合は費用対効果を見極めて判断してください。
クライアントコンポーネント内でサーバーコンポーネントをインポートできますか?
直接インポートすることはできません。クライアントコンポーネント内でサーバーコンポーネントを使用したい場合は、children プロパティ(Props)として渡す設計パターンを採用する必要があります。
まとめ
Next.js App Routerは、React Server Componentsを基盤とした次世代のアーキテクチャであり、モダンなWebアプリケーション開発に大きな変革をもたらします。本記事では、RSCによるサーバーとクライアントの役割分離、柔軟なレンダリングモデル、そして効率的なディレクトリ構成のベストプラクティスを解説しました。
Next.js App Routerを最大限に活用するには、キャッシュ戦略の深い理解と、コンポーネントの適切な使い分けが不可欠です。これらのポイントを深く理解し、プロダクトの要件に合わせて導入することで、スケーラブルでパフォーマンスに優れたアプリケーション開発を実現できるでしょう。技術的な移行だけでなく、開発チーム全体の設計思想や運用体制の見直しも成功の鍵となります。
この記事を書いた人

コセケン
テクラル合同会社
スタートアップでのCTO経験を経て、現在はテクラル合同会社にてシステム開発全般を牽引しています。アプリおよびWebの開発から、バックエンド、インフラ構築に至るまで幅広い技術領域に対応可能です。スピード感を持った品質の高いシステム開発を得意としており、新規プロダクトの立ち上げを一気通貫で支援します。本ブログでは実践的な開発ノウハウを発信していきます。


