Feature-Sliced Designとは何かを説明します — 技術層ではなくビジネス機能によってプロジェクトを分割することに基づくフロントエンドモジュラーアーキテクチャ方法論です。従来の層状アーキテクチャ(コントローラー、サービス、リポジトリ)とは異なり、FSDはアプリケーションの機能的能力によってコードをグループ化します。各機能には独自のロジック、UI、データが含まれます。State of Frontend 2024の調査によると、React開発者の23%が主要なアーキテクチャ方法論としてFSDを使用しており、純粋なFeature-based構造に次いで2番目に人気があります。
重要なポイント
Feature-Sliced Design (FSD)は、2021年にfeature-sliced.designコミュニティによって初めて提案されたフロントエンドアプリケーションアーキテクチャ方法論です。FSDの核となるアイデアは、コードをビジネス機能(スライス)ごとにグループ化することで、各スライスは自己完結型のユニットであり、独自のビジネスロジック、ユーザーインターフェース、API連携、データモデル、テストを含みます。これによりFSDは、コードが技術的基準(controller、service、repository)で分割される従来の層状アーキテクチャとは異なります。
この方法論は、Domain-Driven Design(DDD)とBounded Contextの概念を借用しています。アプリケーションの各機能は、明確な境界を持つ独立したbounded contextです。スライスのパブリックAPIのみを使用している限り、ある機能内の変更は他の機能を壊してはいけません。State of Frontend 2024の調査によると、FSDはReactアーキテクチャの中で人気第2位(23%)であり、非公式のFeature-based構造(31%)に次いでいます。
モバイル開発では、FSDはAndroidモジュールとiOSフレームワークの特性に適応します。IT Sectrでは、10画面以上、3チーム以上のプロジェクトにFSDを使用しています。この方法論により、機能を独立して開発でき、スライス境界のないモノレポと比較してgitの競合が40%減少します。
FSDは7つの階層層を定義し、各層には特定の抽象化レベルのコードが含まれます。主要なアーキテクチャルールは、層は下位層からのみコードをインポートできることです。このルールに違反する(entitiesにfeatures層をインポートする)ことはアーキテクチャエラーと見なされ、リンターによってブロックされます。
| 層 | 目的 | インポート先 |
|---|---|---|
| app | アプリケーションの初期化、プロバイダー、グローバルスタイル、ルーティング | 任意の層 |
| processes | 複数の機能を組み合わせるビジネスプロセス(オンボーディング、支払い) | pages、features、entities、shared |
| pages | ページ上の機能構成、ページルーティング | features、entities、shared |
| features | ユーザーシナリオ:ログインフォーム、お気に入りリスト、検索フィルター | entities、shared |
| entities | ビジネスエンティティ:User、Product、Order、Cart | shared |
| widgets | 複合UIコンポーネント:Header、Sidebar、ArticleCard | shared、entities |
| shared | ユーティリティ、UI-kit、APIクライアント、設定 — ビジネスロジックから独立 | 外部ライブラリのみ |
FSDプロジェクトのディレクトリ構造例:
src/
├── app/ // アプリケーション層
│ ├── providers/
│ ├── router/
│ └── styles/
├── pages/ // ページ — 機能構成
│ └── main/
├── features/ // 機能 — ユーザーシナリオ
│ ├── auth/ // スライス「認証」
│ │ ├── ui/
│ │ ├── model/
│ │ └── api/
│ └── productList/ // スライス「商品一覧」
│ ├── ui/
│ └── model/
├── entities/ // ビジネスエンティティ
│ ├── user/
│ └── product/
├── widgets/ // 複合コンポーネント
│ └── header/
└── shared/ // 共有ユーティリティとUI-kit
└── ui/「層は下方向のみを見る」ルールはFSDの基盤です。feature authがentity userをインポートするのは正しいです。entity userがfeature authをインポートし始めると、それは循環依存と分離違反です。このルールを強制するために、ESLintプラグイン(eslint-plugin-fsd)やスライスのパブリックAPIのカスタムリンターが使用されます。
スライス(Slice) — FSDにおけるグループ化の主要単位で、1つのビジネス機能またはエンティティに対応します。各スライスは7層(features、entities、widgets、pages)のいずれかに存在し、特定の機能を実装するための完全なコードセット(UIコンポーネント、データモデル、APIクライアント、定数、テスト)を含みます。
スライス境界はビジネスドメインによって定義されます。feature authは認証に関するすべて(ログインフォーム、登録フォーム、パスワードリセット)を含みます。entity userはUserモデル、UserRepository、シリアライゼーションを含みます。境界は重複すべきではありません。feature authがユーザーデータを必要とする場合、ロジックを複製する代わりにentity userをインポートします。モバイル開発では、FSDスライスはAndroidのGradleモジュールやiOSのSwiftパッケージに対応することがよくあります。
スライスは厳密に分離されています。あるスライスの内部構造は他のスライスから見えません。スライス間の相互作用には、パブリックAPI(外部使用が許可されたもののみをエクスポートするindex.ts/index.jsファイル)が使用されます。それ以外はすべてプライベートモジュールです。このアプローチは偶発的な依存関係を防ぎ、リファクタリングを容易にします。あるスライスのプライベート実装を変更しても他のスライスに影響しません。
各FSDスライス内では、コードはさらにセグメントによって整理されます。これはすべてのスライスで繰り返される技術的カテゴリです。標準セグメントセットには、ui(インターフェースコンポーネント)、model(ビジネスロジック、Store、Actions、Reducer)、api(サーバーリクエスト、ミューテーション)、lib(ユーティリティとヘルパー)、config(機能設定)が含まれます。
| セグメント | 内容 | 例 |
|---|---|---|
| ui/ | React/Vue/SwiftUIコンポーネント、スタイル、Storybook | LoginForm.tsx、login.module.css |
| model/ | Store、Reducer、Actions、型、コントラクト | LoginStore.ts、authReducer.ts |
| api/ | HTTPクライアント、ミューテーション、RPC呼び出し | authApi.ts、loginMutation.ts |
| lib/ | 補助関数、バリデーター | validateEmail.ts、formatPhone.ts |
| config/ | 定数、機能設定 | authConfig.ts、endpoints.ts |
セグメントは推奨事項であり、厳格なルールではありません。スライスが小さい場合、セグメントは統合できます。大きなスライス(10ファイル以上の機能)の場合、セグメンテーションは必須です。それがないと、内部構造はすぐに50ファイルの「かご」と化し、必要なコンポーネントを見つけるのに数分かかります。モバイル開発では、セグメントはタイプ別のファイル構造に置き換えられることがよくあります。各機能は内部型を持つ独立したSwiftファイルまたはKotlinクラスです。
モバイル開発では、FSDはプラットフォーム固有の特性(Androidのモジュール構造(Gradleモジュール)とSwift Package Manager)に適応します。Android適応では、各スライスが独自のbuild.gradleを持つ独立したGradleモジュールであると想定します。モジュールfeature-auth、feature-profile、entity-user、shared-uiはビルドレベルで相互に分離されています。feature-authは、dependenciesで指定されていない限り、feature-profileをインポートできません。
iOS適応はSwift Package Managerに基づいています。各スライスはパブリックAPIを持つSwiftパッケージです。TCAプロジェクトでは、feature.authスライスに独自のReducer、Store、View、APIクライアントが含まれます。Swift Community Survey 2024によると、TCAを使用するiOSプロジェクトの28%がFSDに近いスライスアーキテクチャを使用しています。
モバイルFSD適応の主な問題は、shared層の重複です。モバイル開発では、UIコンポーネント(shared/ui)はプラットフォーム(Android Views vs Jetpack Compose vs SwiftUI)に依存することが多く、各テクノロジーに個別のsharedモジュールが必要です。FSDでは、shared層は通常プラットフォームに依存しません(ユーティリティ、設定)が、UI-kitは別のモジュールまたはコンポーネントライブラリに移動されます。
利点 FSDは10名以上の開発者がいる大規模プロジェクトで顕著になります。各開発者またはチームは、他のコードに触れることなく自分のスライスで作業します。gitの競合は40〜60%減少します(feature-sliced.designのケーススタディからのデータ)。新しい機能は、スライスのパブリックAPIのみを使用する限り、既存の機能を壊すリスクなく追加できます。1つの機能のリファクタリングは他に変更を必要としません。パブリックAPIを維持しながら、1つのスライス内のui/model/apiを書き換えるだけで済みます。
| 側面 | FSD | Feature-based(FSDなし) | 層状アーキテクチャ |
|---|---|---|---|
| 機能の分離 | 厳格 | 中程度 | 低い |
| 並行開発 | 10+チーム | 3〜5チーム | 1〜2チーム |
| プロジェクト間の再利用 | はい(スライスパッケージ) | コピーペーストのみ | sharedモジュール経由 |
| 参入障壁 | 高い | 低い | 中程度 |
| Gradle分離(Android) | ネイティブ(モジュール) | ネイティブ(モジュール) | 弱い |
欠点 FSDの — 小規模プロジェクトには過剰なネスト。アプリケーションが3〜5画面で構成されている場合、7層と各スライス内のセグメンテーションは、アプリケーション自体よりも多くの組織コードを生成します。参入障壁は高く、新しい開発者は方法論の習得に2〜4週間かかります。また、FSDは迅速なプロトタイピングとの互換性が低いです。プロトタイピングでは頻繁なクロス層インポートが必要ですが、FSDでは禁止されており、反復が遅くなります。
より単純なFeature-based構造から始め、画面数が20を超え、チームが5名を超えたらFSDに移行することをお勧めします。
よくある質問
Feature-basedアーキテクチャは、厳格なインポートルールなしでコードを機能ごとにグループ化します。feature Authは制限なく別のfeature Profileをインポートできます。FSDは層の階層と「層は下方向のみを見る」ルールを追加します。Feature-basedでは、entityとfeatureは同じレベルにあり、相互にインポートできます。FSDでは、entityはfeatureの下にあり、featureはentityをインポートし、その逆はありません。Feature-basedは小規模プロジェクトに適し、FSDは大規模プロジェクトに適しています。
スライスの分離により、ユニットテストが容易になります。各スライスは、下位層の依存関係をモックすることで独立してテストされます。feature authの場合、entity userをモックするだけで十分です。統合テストはスライスのパブリックAPIを検証します。Androidでは、機能のGradleモジュールにReducer、APIクライアント、UI(Compose Test経由)のテスト用の独自のテストディレクトリがあります。iOSでは、スライスパッケージにすべてのセグメントのテストが含まれます。
はい、FSDはJetpack Composeと特に対応しており、特にマルチモジュールのAndroidプロジェクトで有効です。各スライスは、exportedディレクティブを介してパブリックAPIを持つ独立したGradleモジュールです。features層にはComposable機能(LoginFeature、ProductListFeature)が含まれ、entities層にはデータクラスとRepositoryが含まれ、sharedにはUI-kit(MaterialTheme-wrapper、カスタムコンポーネント)が含まれます。FSDは5名以上の開発者がいる大規模なComposeプロジェクトに推奨されます。
必須層はapp、shared、entities、featuresです。残り(processes、pages、widgets)はオプションで、必要に応じて追加されます。モバイル開発では、pages層はナビゲーションルーティングと統合されることが多く、widgetsはshared/ui-kitに置き換えられます。プロセス(processes)は通常モバイルプロジェクトでは使用されません。その役割はドメイン層またはViewModelのビジネスロジックが果たします。重要なのはインポート階層ルールに従うことです。
FSDはDDDからBounded ContextとUbiquitous Languageの概念を借用しています。各スライスはbounded contextに対応します。これは用語が明確な意味を持つ境界です。スライス内では、開発者とビジネスアナリストの両方が理解できる統一言語(ubiquitous language)が使用されます。たとえば、authスライスでは、「ログイン」「パスワード」「トークン」という用語はチームメンバー全員にとって同じ意味を持ち、アナリストと開発者間の誤解を30〜50%削減します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。