Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モジュラーモノリス、はじめました

Avatar for Ryuya Ishibashi Ryuya Ishibashi
July 31, 2025
54

 モジュラーモノリス、はじめました

私たちは、3つの大規模プロジェクトが同時進行する中で、開発のカオスを回避するためにモジュラーモノリスを選択しました。packwerkを活用したモジュール分割の実装方法や、AWS環境での独立したECSサービスへの分離など、実践的な導入事例を紹介します。実際に運用してわかった効果と課題、そしてマイクロサービス移行を見据えた段階的な改善アプローチについてお話します。

Avatar for Ryuya Ishibashi

Ryuya Ishibashi

July 31, 2025
Tweet

Transcript

  1. Ryuya Ishibashi X / GitHub ENECHANGE 株式会社で働いています 経歴 2022/04 -

    2023/03 Rails エンジニアとして、電気料金シミュレーションのAPI 開発を中心に お仕事していました 2023/04 - 現在 Rails ・Go ・インフラエンジニアとして、EV 関連の様々なプロダクトに 携わっています 自己紹介 2 / 21
  2. Daichi Sakai Tech Lead https://github.com/daichi1991 全体統括のテックリードとして、モジュラーモノリス化の大部分 を主導しました アーキテクチャ設計の決定 packwerk の導入と設定

    モジュール分割の実装 チーム全体の技術指導 etc. 今回スケジュールの都合で私が発表しますが、実現の大部分はDaichi さ んの貢献によるものです!!! 大変お世話になりました!!! Special Thanks to 3 / 21
  3. 1. 導入背景 - 開発のカオスを回避したい P.7 2. モジュラーモノリスとは P.8 3. なぜモジュラーモノリスを選択したか

    P.9 4. 導入方法と使用したGem P.10 5. ディレクトリ構造の変更 P.11 6. 実装の詳細 - ルーティングの分離 P.12 7. 実装の詳細 - 境界管理の実践状況 P.13 8. インフラ構成 - AWS 環境での実装 P.14 9. インフラレベルでの分離実装 P.15 10. 導入してみた所感 P.16 11. 今後の展望 - 段階的発展のロードマップ P.17 12. Phase 1: 運用体制構築 P.18 13. Phase 2: 真のRails Engine 化 P.19 14. Phase 3: マイクロサービス準備 P.20 15. まとめ P.21 目次 6 / 21
  4. 開発体制 全体統括: テックリード ローミング ( 他社充電器連携) チーム: 5 名体制 高速充電器チーム:

    1 名体制 課題 各プロジェクトの責務が不明確 相互影響による不具合リスク 将来的な開発の複雑化への懸念 1. 導入背景 - 開発のカオスを回避したい 3 つの大規模プロジェクトが同時進行 他社充電器連携*2 社・高速充電器対応 複数チームが同じリポジトリで開発 7 / 21
  5. モノリス 複数サービスが1 つのアプリに同居 課題: 密結合による相互影響 マイクロサービス サービスごとに独立したアプリ 利点: 疎結合、チーム分割が容易 課題:

    設計・運用の難易度が高い モジュラーモノリス 1 つのアプリ内でモジュール分割 利点: 疎結合と運用の簡素さを両立 DB は単一で整合性を保ちやすい 各アーキテクチャの比較 出典: 日経xTECH 「マイクロサービス信仰を打ち破る新技術、 「モジュラーモノリス」の正体」 2. モジュラーモノリスとは モジュラーモノリスは、単一のアプリケーション内でモジュール境界を明確にし、疎結合を実現するアーキテクチャパターンです。 モノリスの運用の簡素さとマイクロサービスの独立性の良いとこ取りを目指し、最近注目を集めています。 8 / 21
  6. プロジェクトの状況 複数の中・大規模プロジェクトが並行で進行 他社充電器連携、高速充電器対応など 各プロジェクトで開発メンバーが異なる チーム間での責務分離が必要 ローミングプロジェクトでは独立したデプロイが必要 ビジネス要件:独立したエンドポイント スケーリング要件:負荷特性が異なる 決定理由 DB

    共通使用 + 疎結合 + 運用の簡素化 各チームが独立して開発を進められる疎結合性と、単一DB による データ整合性、そして複雑な分散システムを避けた運用性を同時に 実現 3. なぜモジュラーモノリスを選択したか 検討した選択肢 アーキテクチャ メリット デメリット 評価 モノリス継続 シンプル 開発がカオス化する懸念 マイクロサービス 完全な疎結合 DB 分離により考慮ポイント増 モジュラーモノリス 疎結合+運用の簡素さ 境界設計が必要 参考: Shopify の導入事例 9 / 21
  7. 使用したGem packwerk Shopify 製のモジュール境界検知ツール 依存関係の静的解析 境界違反の検出 packs-rails packwerk と組み合わせて使用 packs

    ディレクトリ構造の標準化 Rails 向けの便利機能を提供 # Gemfile gem 'packwerk' gem 'packs-rails' 導入ステップ 1. Gem のインストール bundle add packwerk packs-rails 2. 初期設定 # packwerk設定ファイル生成 bundle exec packwerk init 3. モジュール分割 既存コードをpacks ディレクトリに移動 各pack のpackage.yml 設定 4. 境界チェック bundle exec packwerk check 4. 導入方法と使用したGem 10 / 21
  8. 導入前 . ├── app │ ├── controllers │ ├── models

    │ ├── services │ └── views ├── config ├── db ├── lib └── spec 導入後 . ├── packs # モジュール分割の親ディレクトリ │ ├── roaming_server │ │ ├── package.yml # 分割ルール │ │ ├── app/ │ │ ├── config/routes/ │ │ └── spec/ │ └── app_server │ ├── package.yml │ ├── app/ │ ├── config/routes/ │ └── spec/ ├── config ├── db # 共通DB └── packwerk.yml # 設定ファイル 5. ディレクトリ構造の変更 従来のRails アプリケーション構造から、packs ディレクトリを中心としたモジュール分割構造に変更しました。 各機能を独立したpack として分離することで: 開発チーム間の独立性を確保 コードの責務範囲を明確化 将来の拡張性を向上 11 / 21
  9. 各モジュールのルーティング モジュールごとに独立したルーティング app_server: 一般的なEV アプリ向けAPI 充電スポット検索 push 通知 roaming_server: 他社連携専用API

    他社充電器との通信 ローミング認証など ルーティングの設定 # config/routes.rb Rails.application.routes.draw do draw(:app_server_routes) draw(:roaming_server_routes) end # packs/app_server/config/routes/app_server_routes.rb namespace :api do resources :charging_notification resources :locations # アプリサーバー固有のルーティング end # packs/roaming_server/config/routes/roaming_server_routes.rb namespace :roaming_api do resources :chargers resources :charging_transactions # ローミングサーバー固有のルーティング end 6. 実装の詳細 - ルーティングの分離 12 / 21
  10. 技術的基盤の整備 各packs での境界設定が有効 # packs/roaming_server/package.yml enforce_dependencies: true enforce_privacy: true packwerk

    ツールの導入完了 依存関係違反の検出が可能 ディレクトリレベルでのモジュール分割 注意: 技術的設定は整っているが、日常的な運用体制は未構築 今後の課題 CI/CD へのpackwerk 組み込み 自動チェック体制の構築 PR 時の必須チェック化 レビュー体制の構築 境界違反チェックのルール化 依存関係変更時のレビュー ルートレベルの境界管理有効化 # package.yml (ルート) enforce_dependencies: false # → true 現状: 「仕組みはあるが厳密な運用はできていない」 7. 実装の詳細 - 境界管理の実践状況 13 / 21
  11. プロジェクト特有の要件 ビジネス要件: ローミングサーバーとして独立したエンドポイントが必要 スケーリング要件: 負荷特性が異なるため個別のスケーリングが必要 メリット • 独立したスケーリング • エンドポイントの明確な分離

    • デプロイの独立性 実装内容 独立したECS サービス app_server: 一般的なEV アプリ向け roaming_server: 他社充電器連携専用 注意: これは一般的なモジュラーモノリスのプラクティスではありません CloudFront によるルーティング分離 # cloudfront_distribution.tf (抜粋) ordered_cache_behavior { path_pattern = "/roaming/*" target_origin_id = "roaming-server-alb" } ordered_cache_behavior { path_pattern = "/api/*" target_origin_id = "app-server-alb" } 9. インフラレベルでの分離実装 15 / 21
  12. 良かった点 責務が明確に ローミングサーバー側の開発がしやすくなった 他チームの変更による影響を最小限に 将来への段階的発展が可能 Engine 化からマイクロサービス化まで選択可能 ビジネス成長に合わせてアーキテクチャを進化 インフラレベルでの分離効果 独立したスケーリングが実現

    ビジネス要件に応じたエンドポイント分離 課題 運用体制が未整備 CI/CD でのpackwerk 自動チェック未実装 境界違反の日常的なチェック体制なし 真のRails Engine 化は未完了 名前空間の統一が不十分 完全な独立性は達成されていない アプリサーバー側の開発体験 さらなる分割検討が必要 10. 導入してみた所感 16 / 21
  13. 主要目標 「技術的基盤を日常的に活用できる体制作り」 具体的タスク CI/CD へのpackwerk 組み込み PR での自動チェック 違反時のbuild 失敗設定

    レビュープロセスの確立 境界違反チェックのルール化 依存関係変更時の承認フロー 期待効果 境界違反の早期発見 チーム全体の境界意識向上 技術的負債の蓄積防止 課題と対策 学習コストの最小化 packwerk コマンドの使い方研修 違反解消のベストプラクティス共有 成功指標: packwerk 違反ゼロ状態の維持 12. Phase 1: 運用体制構築 18 / 21
  14. 主要目標 「完全に独立したミニアプリケーション化」 具体的タスク Engine 設定ファイルの実装 # packs/roaming_server/lib/roaming_server/engine.rb module RoamingServer class

    Engine < ::Rails::Engine isolate_namespace RoamingServer end end 完全な名前空間分離 # Before: class RoamingUser # After: class RoamingServer::RoamingUser 期待効果 モジュール間の完全分離 将来のマイクロサービス化準備 開発チームの独立性向上 実装の課題 既存コードの大規模リファクタリング テストコードの修正 段階的移行の計画策定 成功指標: 各Engine の独立動作確認 13. Phase 2: 真のRails Engine 化 19 / 21
  15. 主要目標 「必要に応じた切り出し可能な状態」 具体的タスク DB 分離の検討と実装 各Engine 専用のDB 設計 データ整合性の保持方法 API

    境界の明確化 Engine 間通信の標準化 外部API 化の準備 特定モジュールの切り出し ローミングサーバーの独立化検討 長期的価値 スケーラビリティの向上 チーム拡張への対応 技術スタック選択の自由度 最終ゴール 段階的マイクロサービス化の実現 モノリス → モジュラーモノリス → マイクロサービス 成功指標: 1 つ以上のEngine の独立サービス化 14. Phase 3: マイクロサービス準備 20 / 21
  16. モジュラーモノリス導入の成果 複数プロジェクトの並行開発が可能に カオスを回避し、秩序ある開発を実現 モノリスとマイクロサービスの良いとこ取り DB の一貫性を保ちつつ疎結合を実現 段階的な改善が可能 小さく始めて大きく育てる プロジェクト特有のニーズに対応 インフラレベルでの分離によりビジネス要件を満たす

    重要な学び 技術的基盤だけでは不十分 運用体制の構築や真の疎結合化が成功の鍵 今後に向けて Phase 1: CI/CD 組み込み、レビュー体制構築 Phase 2: 真のRails Engine 化 Phase 3: 必要に応じたマイクロサービス化 継続的な改善でアーキテクチャを進化させる 15. まとめ 21 / 21