本記事では、モノリシック(単一システム)からマイクロサービスへ移行する際に、クリーンアーキテクチャをどのように適用するかを整理します。
実務でよく直面する以下の課題を中心に解説します。
- アダプタ層の設計(DBアクセス・外部API連携)
- マスターデータの扱い
- コード重複の問題
- テーブル結合ができないことによるパフォーマンス上の工夫
- モノリシックから段階的に移行するためのパターン
読み進めながら、随所に参考となる図解のアイデアを挿入しています。画像ファイル自体は用意不要ですが、設計をイメージするうえで役立つと思います。
1. クリーンアーキテクチャ × マイクロサービス概説
1.1 クリーンアーキテクチャとは
クリーンアーキテクチャは、ビジネスロジックを中心に据え、外部要素(DB、UI、外部APIなど)を分離して設計する手法です。
- アプリケーションコア(ユースケース・エンティティ)
- アダプタ層(外部I/OやAPIとの接合部)
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
1.2 マイクロサービスアーキテクチャとは
機能単位で独立したサービスを構築し、サービス間はネットワーク越しに連携します。各サービスは独自のDBを持つことも多く、変更やデプロイの自由度が高い反面、データの整合性管理や運用負荷が課題になりやすい構造です。
https://martinfowler.com/articles/microservices.html
1.3 併用メリット
- クリーンアーキテクチャ: マイクロサービス内のドメインロジックを強固に保ち、変更に強い設計が可能。
- マイクロサービス: サービス単位での独立開発・デプロイやスケーリングが容易。
両者を組み合わせることで、疎結合 かつ ビジネスロジック中心の拡張性高いシステムを作ることが狙えます。
2. アダプタ層の役割 — DBアクセス & 外部API連携
2.1 アダプタ層とは
クリーンアーキテクチャでは、外部システムへの依存を内側のコアに直接持ち込まないようにし、外部とのやり取りを担う部分をアダプタ層として分離します。
- DBアダプタ: CRUD操作(ORMやSQL実行など)
- 外部APIアダプタ: RESTやGraphQL、gRPCなどの通信クライアント
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
2.2 DBアクセスアダプタ
- マイクロサービスごとに独自のDBを持つ場合、そのDBへのアクセスはサービス内部のアダプタが担当します。
- コア層とは**インターフェイス(ポート)**を通じて連携し、具体的なデータアクセスロジックを隠蔽。
2.3 外部API連携アダプタ
- 他サービスのAPIを呼び出す場合も、HTTP通信やリクエスト/レスポンス形式の差異をアダプタで吸収。
- リトライやサーキットブレーカー、認証情報の管理などもアダプタ層に集約することで、コア層の複雑化を防ぐ。
3. マスターデータの扱い — 共通データをサービス化する
3.1 マスターデータサービスとは
複数サービスが参照するデータ(例: 都道府県リスト、カテゴリ情報など)を専用のサービスとして切り出し、一元管理するパターンがあります。
- データの一貫性確保
- 集中管理によるメンテナンスの容易化
3.2 メリットとデメリット
-
メリット
- 不整合のリスクを下げる
- 変更作業が集中的に行える
-
デメリット
- 単一障害点になりうる
- API呼び出しが集中し、レイテンシが増加する可能性あり
対策
- キャッシュを各サービスで導入し、マスターデータ取得の回数を減らす
- 回線不通時のフェールセーフ(リトライ、サーキットブレーカー)を実装する
4. コード重複の問題 — どこまで共有するか?
4.1 DRY原則とマイクロサービスの独立性
- 原則としてコード重複は避け、**共通ロジックはライブラリ化(SDK化)**して管理するのが保守的に望ましい。
- しかし、マイクロサービスでは意図的に重複を許容することで、各サービスのバージョン管理やデプロイサイクルを独立させることもある。
4.2 重複を最小化する方法
-
共通ライブラリの作成
- APIクライアントやデータ変換ロジックをまとめて配布
-
API Gatewayやサービスメッシュ
- 共通認証やルーティングロジックを一元化し、実装重複を削減
-
キャッシュ戦略の共通化
- キャッシュの仕組みをテンプレ化し、各サービスで使える形にする
表のアイデア:
手法 メリット デメリット 共通ライブラリ DRYを実現しやすい バージョン管理が複雑になる API Gateway活用 認証や監視を集約し、実装重複が減る Gatewayが単一障害点になるリスク 意図的な重複許容 サービスの独立性維持 同じ修正が複数箇所に必要になる
5. テーブル結合が困難になる問題とパフォーマンス対策
5.1 モノリシック時代とのギャップ
モノリシックでは1つのDB内のテーブル結合で高度なクエリを容易に実行できましたが、マイクロサービス化するとDBが分かれているため、そのままの結合はできません。
5.2 データ連携パターン
-
CQRS (Command Query Responsibility Segregation)
- 更新系と参照系を分離し、参照に特化した集約ビューを保持する
- イベントやバッチで更新データを集約ビューに反映
-
データ集約サービス
- 複数サービスのデータをまとめて取得し、結合した上でレスポンスを返す専用APIを設ける
- フロントエンドからは**「1つのAPIを呼べばすむ」**形にできる
-
キャッシュ活用
- 頻繁に参照するデータをキャッシュ層(Redisなど)に置き、結合済みデータを高速で提供
https://martinfowler.com/bliki/CQRS.html
6. モノリシックからの段階的移行
6.1 Strangler Fig パターン
既存モノリシックシステムの機能を少しずつ別のマイクロサービスに置き換え、最終的にモノリシックを解体する方法。
- 移行リスクを段階的に抑えられる
- レガシー機能を動かしながら、新機能をマイクロサービス化
https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig
6.2 具体的ステップ
-
モノリシック内の機能をAPI化
- 直接DBにアクセスしていた部分を、まずはモノリシック内APIに置き換える
-
新マイクロサービスにリダイレクト
- モノリシックのAPIが受けたリクエストを、新アーキテクチャへ少しずつ移行
-
切り替え & 廃止
- 最終的にモノリシック側のコードを段階的に削除
7. まとめ・ポイントの再確認
-
クリーンアーキテクチャの適用
- アダプタ層を明確に分けることで、ビジネスロジックからDBアクセスや外部API連携を切り離す
-
マスターデータのサービス化
- データを一元管理する専用サービスを用意し、キャッシュやフェールセーフ設計を加味
-
コード重複と独立性のバランス
- SDKやGatewayを用いて重複を最小化しつつ、サービス単位のバージョン管理を考慮して意図的に重複を許容する場面もある
-
JOINができない課題への対策
- CQRSやデータ集約サービス、キャッシュ戦略でテーブル結合相当を実現
-
移行は段階的に
- Strangler Figパターンで大きなリスクを避け、テストしながら少しずつマイクロサービスへ
これらのポイントを押さえることで、マイクロサービスとクリーンアーキテクチャを組み合わせた柔軟で保守しやすいシステムを構築できます。モノリシックのテーブル結合による利便性を失う代わりに、可用性や拡張性を飛躍的に高めるチャンスでもあります。移行を段階的に進め、適切なアーキテクチャを設計することで、長期的にスケーラブルなシステムを手に入れましょう。
参考リンク
-
The Clean Architecture (by Uncle Bob)
https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html -
Microservices Patterns (by Chris Richardson)
https://microservices.io/patterns/index.html -
Strangler Fig Pattern (Martin Fowler)
https://martinfowler.com/bliki/StranglerFigApplication.html -
CQRS (Command Query Responsibility Segregation) 解説 (Martin Fowler)
https://martinfowler.com/bliki/CQRS.html