FSDとアプリケーション全体の設計 ── client applicationの設計思想をどう位置づけるか
Published on 2026年3月2日
設計はじめに
この記事は、自分がMarkdown形式で思考を整理しながらAIと壁打ちした結果のアウトプットだ。誰かに正解を提示するものではなく、自分の考えを言語化・整理するために書いている。最終的な文章の作成はAIに依頼した。
FSD(Feature-Sliced Design)はフロントエンドの設計手法として注目されている。機能(feature)単位でUI・ロジック・APIの責務をまとめるコンポジション的なアプローチは、フロントエンドが肥大化する現代の開発において非常に合理的だ。
しかし、アプリケーション全体の設計として見た時に、FSDだけで考えると違和感が出てくる。この記事では、FSDの強みを認めた上で、なぜFSDだけではアプリケーション全体の設計として不十分なのかを、client/server分離の観点から言語化していく。
FSDの核心的な強み
まずFSDが何を解決しているのかを整理する。
ビジネスロジックの凝集性
Atomic Designが「UIの粒度」(atoms/molecules/organisms)で分割するのに対し、FSDは「ビジネスドメイン(機能)」で分割する。「ブログに関するもの」が1箇所にまとまるので、変更時の影響範囲が明確になる。
依存方向の厳密なルール
app → pages → widgets → features → entities → shared
上位は下位に依存できるが、逆は不可。このレイヤー間の一方向依存が、暗黙の循環依存を防ぐ。Atomic Designにはこのルールがないため、規模が大きくなると依存が混沌としやすい。
スケーラビリティ
機能が増えても「新しいslice(機能単位)を追加するだけ」。既存コードへの影響が最小限に抑えられる。
チーム開発での分業
「この機能はAさん」と機能単位で担当を分けやすい。Atomic Designだと「このatomsを誰が管理するか」が曖昧になりがちだ。
FSDの根本思想:UIとロジックの分離
FSDでは各slice(機能単位)の中でsegmentsという層に分ける設計になっている。
features/
└── blog/
├── ui/ # 表示だけに責任を持つ
├── model/ # ビジネスロジック・状態管理
├── api/ # データ取得
├── lib/ # ユーティリティ
└── index.ts # Public API(外部に何を公開するか)
なぜこの分離が効果的か
変更理由が異なるものを分ける(単一責任)。 UIの見た目を変えたければ ui/ だけ触る。API仕様が変わったら api/ だけ触る。ビジネスルールが変わったら model/ だけ触る。
テスタビリティ。 model/ はUIに依存しないので、純粋な関数としてテストできる。UIはモックデータを渡すだけでテストできる。
再利用性。 ロジック(model/)は別のUI(モバイル、管理画面)でもそのまま使える。UIコンポーネントは別のデータソースに差し替えられる。
Atomic Designとの本質的な違い
Atomic Designは「UIをどう構造化するか」の手法であって、ロジックの置き場所について何も言わない。だからロジックがコンポーネントに混入したり、utils/ に雑多に溜まったりする問題が起きやすい。
FSDはこの問題に対して、機能単位 × 関心事の分離という二軸で構造を与えている。フロントエンドが肥大化する中で感じるpainを正確に捉えた設計だと言える。
では何が問題なのか
ここからが本題だ。FSDの構造をもう一度見る。
features/blog/
├── ui/
├── model/
├── api/ ← こいつが何者かで全てが決まる
└── index.ts
問題は api/ セグメントの役割にある。
api/ の正体で設計の評価が変わる
BFFとしての api/ ── これは正しい
Frontend Backend
┌─────────────────────┐ ┌──────────────┐
│ features/blog/ │ │ │
│ api/ ─────────────│────→ │ Core API │
│ 「core APIを叩いて │ │ (独立) │
│ UIに都合よく整形」 │ │ │
└─────────────────────┘ └──────────────┘
api/ がBFF(Backend for Frontend)の役割、つまりcore APIを叩いてUIに都合よくデータを整形する薄い層であれば、FSDの構造は完全に理にかなっている。api/ はフロントの関心事だから、sliceの中にあって正しい。
コアAPIとしての api/ ── ここに問題がある
Frontend
┌─────────────────────────────────────┐
│ features/blog/ │
│ api/ ← ドメインロジック+データ取得 │
│ 「記事の取得、バリデーション、 │
│ ソート、カテゴリ集計...全部ここ」 │
│ │
│ ui/ ← これに依存 │
└─────────────────────────────────────┘
api/ がコアAPIの実体そのものになっている場合、以下が起きる。
切り出せない。 api/ がslice内部のmodel/uiと暗黙に結合する。
肥大化する。 ビジネスロジックが増えるほどsliceが膨張する。
共有できない。 別のクライアント(管理画面、モバイル)が同じロジックを使いたくても、フロントのsliceに閉じ込められている。
つまりフロントの構造の中にバックエンドの責務を埋め込んでしまうことになる。
判断基準はシンプル
api/ の中身が fetch("/api/blogs") ならBFF。FSD内で正しい。
api/ の中身が fs.read + parse + sort ならコアAPI。FSDの外に出すべき。
「将来分離する時が来る」という現実
スケーリングや保守運用を考えると、client applicationとserver applicationを疎結合にしておきたいという要求は必ず出てくる。その動機は明確だ。
ライフサイクルの違い。 APIは安定していてほしい。UIは頻繁に変わる。この2つが同じデプロイ単位に入っていると、UIの変更がAPI側に意図しない影響を与えるリスクが常にある。
デプロイの独立性。 UIだけリリースしたい、API側だけスケールしたい。これは規模が大きくなれば当然の要求だ。
マルチクライアント。 Web以外のクライアント(モバイルアプリ、管理画面、外部連携)が出てきた時、コアAPIがフロントのslice内に閉じ込められていたら共有できない。
FSDはこの問題に対して何も言わない
ここが核心だ。FSDのslice構造を見ると、ui/model/apiは一見分離されているように見える。しかし同じslice内に同居している。
将来コアAPIを切り離したい時に何が起きるか。
切り離したい境界線
↓
features/blog/
├── ui/ ← フロント側に残したい
├── model/ ← どっちに属する?
├── api/ ← コア側に持っていきたい
└── index.ts
model/ の所属が曖昧になる。ソートやフィルタやバリデーションといったビジネスロジックはコアAPI側の責務だが、UIの状態管理(モーダルの開閉、フォーム入力値)はフロント側の責務だ。FSDの model/ はこの2つを同じ場所に置くことを許容してしまう。
FSDの分割軸:
横軸: レイヤー(app → pages → features → entities → shared)
縦軸: segments(ui / model / api / lib)
┌───────────────────────────────┐
│ features/blog │
│ ui | model | api │ ← 1つのデプロイ単位に同居
└───────────────────────────────┘
FSDが想定していないもの:
┌──────────────┐ ┌──────────────┐
│ Frontend │ │ Core API │
│ ui │ │ domain │
│ ui-state │ │ repository │
│ │←──│ service │
└──────────────┘ └──────────────┘
デプロイ境界を跨ぐ分離
FSDはモノリスなフロントエンドアプリケーションの内部構造を整理する設計であって、「将来サービスを分割する」という関心事に対しては中立だ。segmentsでui/model/apiを分けているのは、あくまで同一プロセス内での見通しを良くするためであり、物理的な分離を前提としていない。
FSDの適用範囲を正しく限定する
ここまでの議論をまとめると、FSDに対する評価は以下のようになる。
FSDが効果的な範囲: フロントエンド単体の内部構造を規律あるものにすること。フロントが肥大化していくpainに対して、コロケーション的な考え方でfeature内にUI・ロジック・APIの責務をまとめるアプローチは合理的だ。
FSDが解決しない問題: UIとコアロジックのデプロイ境界を跨いだ疎結合。application全体で考えた時にserver applicationの設計観点が漏れている。
FSDはフロントエンドエンジニアの視点から生まれた設計であって、システム全体のアーキテクチャではない。それを認識せずにFSD「だけ」でアプリケーション全体を設計すると、server側の関心事がfeatureのapiセグメントに溶け込み、分離不可能になる。
ではどう設計するか
FSDを否定しているのではない。FSDの適用範囲を正しく限定した上で、アプリケーション全体の設計を別のレイヤーで考える必要がある。
┌─────────────────────────────────────────┐
│ アプリケーション全体のアーキテクチャ │
│ │
│ core-api ←── contract ──→ client │
│ (Clean Architecture等) (FSD) │
│ │
│ FSDはclient側の内部構造を整理する道具 │
│ アプリケーション全体の設計思想ではない │
└─────────────────────────────────────────┘
具体的には、最初からモノレポで物理的に分けるか、モノリスで始めるが境界だけは守るかの選択肢がある。
どちらを選んでも守るべきルールは1つ。coreはclientを知らない。
client → core ✅(clientがcoreを使う)
core → client ❌(coreがclientに依存してはならない)
これさえ守れていれば、分離のタイミングは自由に選べる。逆にこれが崩れていると、物理的にモノレポにしていても分離できない。
おわりに
FSDは優れた設計手法だ。フロントエンドの肥大化に対する解として、機能単位の凝集性と依存方向の規律を持ち込んだことは大きな価値がある。
しかし、FSDはclient applicationの設計であって、application全体の設計ではない。スケーリングや保守運用の観点でclient/server applicationを疎結合にしておきたいなら、FSDの上位にあるアーキテクチャ判断──モノレポ設計、パッケージ分割、Clean Architecture等──が必要になる。
FSDが効果的かどうかは、設計思想の良し悪しではなく、api/ に何を置くかという運用の規律に依存する。そしてその規律が明文化されていないと、チームが大きくなるにつれてコアロジックがsliceに混入していく。
設計を選ぶ時に大事なのは「何を解決するか」だけでなく「何を解決しないか」を知ることだ。FSDが解決しない問題を認識した上で、全体のアーキテクチャの中でFSDを正しく位置づけること。それが、将来の分離を見据えた設計の第一歩になる。