•17 min read

Next.js App Routerのフォルダ構造: ベストプラクティスとエンタープライズアーキテクチャ (2026)

Next.js App Routerのフォルダ構造: ベストプラクティスとエンタープライズアーキテクチャ (2026)
Next.js App Router Scalable Folder Structure Architecture
Audio Briefing
0:00 / 0:00
Part of a Series

Modern Next.js Architecture Series

Part 2 of 3

Reactアプリケーションがスケールするにつれて、フォルダ構造は個人的な美学の問題から、基礎的なアーキテクチャの決定へと移行します。Next.js App Routerの導入により、古いメンタルモデルは崩壊しました。私たちは、レガシーなpages/ディレクトリ(ルーティングとUIコンポーネントの両方のゴミ捨て場になりがちでした)から、app/内の意見が明確で規約に基づいたルーティングシステムへと移行しました。

しかし、App Routerの柔軟性、特にコロケーション(colocation)のサポートは、諸刃の剣です。明確な構造的ガードレールがなければ、app/ディレクトリはすぐに何百もの混在ファイル、循環依存、サーバー/クライアント境界の漏洩で膨れ上がってしまいます。

このガイドでは、Next.js App Routerアプリケーション向けに本番環境でテストされたフォルダ構造を、基本的なコロケーションからエンタープライズアプリケーション向けの**Feature-Sliced Design (FSD)**まで、詳しく解説します。


App Routerのパラダイムシフト:ルーティング vs ドメインロジック

App Routerは、app/ディレクトリをHTTPルーターおよびページコンポジターとして厳密に扱います。公開アクセス可能なのは、特別な規約ファイルのみです。

  • page.tsx: URL経由でアクセス可能な、ルート固有のUI。
  • layout.tsx: 子要素をラップし、ナビゲーション間で状態を保持する共有UI。
  • loading.tsx: React Suspenseによって提供されるストリーミングフォールバック。
  • error.tsx: ルートサブツリー内のランタイムエラーを捕捉するクライアントサイドのエラー境界。
  • not-found.tsx: 404状態のUI。
  • route.ts: サーバーサイドAPIエンドポイント(GET、POST、PUT、DELETE)。

ルートフォルダ内のその他すべてのものは、技術的にはコロケーション可能です。

app/
└── dashboard/
    ├── page.tsx
    ├── layout.tsx
    ├── DashboardGraph.tsx       # Colocated component
    ├── dashboard.module.css     # Colocated styling
    └── dashboard.test.tsx       # Colocated unit test

純粋なコロケーションの落とし穴

app/内にすべてをコロケーションする方法はMVP(Minimum Viable Product)には適していますが、中規模から大規模のプロジェクトでは破綻します。

  1. 再利用性のボトルネック: 別のルート(例: app/reports/page.tsx)がDashboardGraphを必要とする場合、それはどこに置かれるべきでしょうか?上に移動すると、予測不能なインポートパスが生成されます。
  2. 汚染されたファイルツリー: 30のルートと200のコロケーションされたファイルを持つapp/フォルダでは、オンコールインシデント中にルートを見つけるのが非常に困難になります。
  3. 曖昧な境界: 開発者が誤って'use client'を親ラッパーに追加し、Server Componentのストリーミングを最適化できなくしてしまいます。

Advertisement

3つのアーキテクチャモデル:あなたの規模に合うのはどれ?

ModelBest ForStrengthsTrade-offs
1. Colocated App
MVPs & 小規模サイト (<10ルート)
高速なセットアップ、メンタルオーバーヘッドなし
ルート間でコードを共有する際にスパゲッティインポートが発生
2. Layered Flat
スタートアップ & 中規模アプリ (10-40ルート)
標準的なReactチームには馴染み深い
巨大なcomponents/およびhooks/フォルダがジャンクドロワーになる
3. Feature-Sliced (FSD)
エンタープライズ & 大規模 (40+ルート、複数チーム)
厳格な単方向境界、疎結合な機能
ジュニア開発者にとっては初期学習曲線がある

ルートグループ vs プライベートフォルダ

Next.jsは、ルーティングを内部ロジックからきれいに分離するための2つの重要なフォルダ規約を提供します。

1. ルートグループ (folder)

フォルダ名を括弧で囲むと、公開URLを変更せずにルートを論理的に整理できます。

app/
├── (marketing)/
│   ├── layout.tsx       # Marketing layout (Navigation bar + Footer)
│   ├── page.tsx         # Served at: /
│   └── pricing/
│       └── page.tsx     # Served at: /pricing
└── (dashboard)/
    ├── layout.tsx       # Dashboard layout (Sidebar + Account switcher)
    ├── settings/
    │   └── page.tsx     # Served at: /settings
    └── analytics/
        └── page.tsx     # Served at: /analytics

ルートグループを使用する理由

  • 複数のルートレイアウトを作成する(例:公開ランディングページ vs 保護された認証済みダッシュボード)。
  • SEOに影響するURLを変更せずに、チームの所有権ごとにルートをグループ化する。
  • セクションごとにローディング状態とエラー状態を分離する。

2. プライベートフォルダ _folder

フォルダ名の前にアンダースコアを付けると、Next.jsにそのフォルダをルーティングから完全に除外するように指示します。

app/
├── (dashboard)/
│   └── analytics/
│       ├── _components/   # OPTED OUT of routing (/analytics/_components is 404)
│       │   ├── Chart.tsx
│       │   └── MetricCard.tsx
│       ├── _lib/
│       │   └── calculations.ts
│       └── page.tsx       # Served at: /analytics

_componentsまたは_libは、単一のルートに厳密にプライベートであり、他の場所で再利用されることのないコードをコロケーションしたい場合に使用します。


推奨されるエンタープライズアーキテクチャ:Feature-Sliced Design

ミッションクリティカルな本番アプリケーションでは、Next.jsのルーティングをドメインビジネスロジックから分離するために、4層アーキテクチャを使用します。

src/
├── app/          # Layer 1: Next.js routing, layouts, and page composition
├── features/     # Layer 2: Business actions and user workflows
├── entities/     # Layer 3: Domain data models and business entities
└── shared/       # Layer 4: Foundation (UI primitives, API clients, helpers)

依存関係グラフの可視化

Feature-Sliced Designで最も重要なルールは、単方向の依存関係です。コードは、厳密に下位のレイヤーからのみインポートできます。

各レイヤーの動作

1. app/レイヤー:純粋なコンポジション

app/ディレクトリにはビジネスロジックが一切含まれていません。以下のことのみを行います。

  • ルートとネストされたレイアウトを宣言する。
  • Server Components内でデータをフェッチする。
  • 機能とエンティティをページテンプレートに構成する。
// src/app/(dashboard)/analytics/page.tsx
import { Suspense } from 'react';
import { AnalyticsMetrics } from '@/features/usage-metrics';
import { getCurrentUser } from '@/entities/user';
import { SkeletonLoader } from '@/shared/ui';

export default async function AnalyticsPage() {
  const user = await getCurrentUser();

  return (
    <main className="container mx-auto p-6 space-y-6">
      <header>
        <h1 className="text-3xl font-bold tracking-tight">Analytics</h1>
        <p className="text-muted-foreground">Welcome back, {user.name}</p>
      </header>

      <Suspense fallback={<SkeletonLoader count={4} />}>
        <AnalyticsMetrics organizationId={user.orgId} />
      </Suspense>
    </main>
  );
}

2. features/レイヤー:ユーザーワークフロー

機能には、測定可能なビジネス価値を提供するインタラクティブなユーザーフローが含まれます(例: auth-flow、checkout、team-invitation)。

src/features/auth-flow/
├── ui/                 # React client/server components
│   ├── LoginForm.tsx
│   └── SocialButtons.tsx
├── api/                # Colocated Server Actions
│   └── authenticate.ts
├── model/              # Local state, validation schemas
│   └── schema.ts
└── index.ts            # STRICT Public API export

内部をプライベートに保つために、常にindex.tsを介してエクスポートしてください。

// src/features/auth-flow/index.ts
export { LoginForm } from './ui/LoginForm';
export { authenticateWithOAuth } from './api/authenticate';

3. entities/レイヤー:コアビジネスエンティティ

エンティティは、ドメイン内の現実世界の概念を表します(例: User、Workspace、Invoice)。これらには以下が含まれます。

  • データベースクエリ関数またはAPIエンドポイント。
  • TypeScriptインターフェースとZodスキーマ。
  • 特定のエンティティに結びついたUI要素(例: <UserAvatar />、<PlanBadge />)。

4. shared/レイヤー:再利用可能な基盤

shared/ディレクトリには、理論的には内部npmパッケージとして公開できる、ドメインに依存しないコードが格納されます。

  • shared/ui: Button、Modal、Input、Dropdownなどのプリミティブ(多くの場合、Shadcn / Radixラッパー)。
  • shared/lib: 日付フォーマッター、数学ユーティリティ、ネットワーククライアント。
  • shared/config: 環境変数検証(Zod)とサイトメタデータ。

Advertisement

フォルダツリーにおけるサーバーコンポーネントとクライアントコンポーネントの境界

Next.jsアプリの速度低下の最も一般的な原因の1つは、「クライアントコンポーネント汚染」です。これは、ページの先頭に'use client'を追加すると、すべての子コンポーネントがクライアントJavaScriptバンドルで実行されてしまう現象です。

これを避けるには、フォルダ構造で**「リーフのみのクライアントコンポーネント」**ルールに従ってください。

app/(dashboard)/dashboard/page.tsx   # [Server Component] Fetches data
├── DashboardSummary.tsx             # [Server Component] Pure HTML rendering
└── _components/
    └── InteractiveFilter.tsx        # ['use client'] ONLY interactive button/state

親ページをServer Componentのままにし、Client Componentをリーフの位置にインポートすることで、クライアントJavaScriptバンドルを最小限に抑え、Next.jsのハイドレーションミスマッチエラーを解消できます。


本番環境対応テンプレート(コピー&ペースト)

以下は、エンタープライズNext.js App Routerアプリケーション向けに実証済みのディレクトリ構造です。

my-app/
├── public/
│   └── static/
├── src/
│   ├── app/
│   │   ├── (auth)/
│   │   │   ├── login/page.tsx
│   │   │   ├── signup/page.tsx
│   │   │   └── layout.tsx
│   │   ├── (dashboard)/
│   │   │   ├── layout.tsx
│   │   │   ├── overview/page.tsx
│   │   │   └── settings/
│   │   │       ├── page.tsx
│   │   │       └── _components/
│   │   ├── api/
│   │   │   └── webhooks/stripe/route.ts
│   │   ├── favicon.ico
│   │   ├── global-error.tsx
│   │   ├── layout.tsx
│   │   └── not-found.tsx
│   │
│   ├── features/
│   │   ├── auth/
│   │   │   ├── ui/
│   │   │   ├── api/
│   │   │   └── index.ts
│   │   └── billing/
│   │       ├── ui/
│   │       ├── api/
│   │       └── index.ts
│   │
│   ├── entities/
│   │   ├── user/
│   │   │   ├── ui/UserAvatar.tsx
│   │   │   ├── model/types.ts
│   │   │   └── index.ts
│   │   └── organization/
│   │
│   └── shared/
│       ├── ui/             # Reusable design system components
│       ├── lib/            # Utilities (cn, formatters)
│       └── hooks/          # Domain-agnostic React hooks
│
├── middleware.ts           # Edge routing & auth guards
├── next.config.mjs
└── tsconfig.json

知識を試す:App Routerアーキテクチャ


こちらもおすすめ

よくある質問

(folder)は、URLパスにセグメントを追加せずにルートをグループ化し、複数のルートレイアウトを可能にするルートグループです。_folderは、ルーティングシステムから完全に除外され、子ファイルが公開エンドポイントになるのを防ぐプライベートフォルダです。

汎用的でドメインに依存しないUIコンポーネント(ボタン、モーダル、入力など)は、src/shared/ui/またはsrc/components/ui/に配置します。ドメイン固有のコンポーネントは、src/features/[feature-name]/ui/またはルート内のプライベートな_componentsフォルダに配置すべきです。

はい、できます。Feature-Sliced Designでは、'use server'アクションファイルをfeatures/[feature-name]/api/actions.ts内にコロケーションすることをお勧めします。これにより、ミューテーションをトリガーするUIフォームの近くに保ちながら、クリーンな境界を維持できます。

並列ルートは@name規約を使用して、同じレイアウト内で複数のページを同時にレンダリングします(例: @modal)。インターセプトルートは(.)routeまたは(..)routeを使用して、URLコンテキストを変更せずに現在のビュー内の別のセグメントからルートをロードします。これはフォトギャラリーやログインモーダルに最適です。

Next.jsのapp/は、ルーティング、ストリーミング、HTTPメカニズムに最適化されています。重いドメインロジック、複雑なステートマシン、ビジネスワークフローを直接app/に配置すると、ファイル間の結合が非常に強くなり、単体テストが困難になり、意図しない循環依存が発生します。


関連する詳細解説

本番環境のNext.jsアーキテクチャをさらにレベルアップさせるために、これらの補完的なガイドもご覧ください。

Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement