LASSIC Media らしくメディア
モノレポ導入・移行を外注で進める進め方と設計
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- モノレポは複数リポジトリ(ポリレポ)を1つのリポジトリに集約する構成で、コード共有と横断的な変更のしやすさが利点です。
- Nx・Turborepo・Bazelなどのツールは、依存グラフとキャッシュを使って影響範囲だけを再ビルド・再テストする仕組みを提供します。
- 外注で移行を進める場合は、段階的な集約とCODEOWNERSによる権限設計を自社主導で決め、実装とCI整備を委託範囲にすることが大切です。
目次
モノレポとポリレポ、リポジトリ構成の違い
モノレポとは、複数の個別プロジェクトを1つのリポジトリにまとめ、プロジェクト間に明確な依存関係を持たせるリポジトリ構成です*1。単にコードを1か所に集めただけの状態はモノレポではなく、プロジェクト同士の関係性が整理されていることが条件になります。
対になる概念がポリレポです。ポリレポは、チームやアプリケーションごとに個別のリポジトリを持つ構成を指します。各リポジトリは独立してCIやパッケージ公開の仕組みを持つため、自律的に開発を進めやすい一方、リポジトリをまたぐ変更のたびに複数のプルリクエストを順序立てて進める必要があります*1。
本稿で扱うモノレポは、マイクロサービスへの分割方針やモバイルアプリ内部のビルド単位分割とは別の話です。あくまで「複数リポジトリをどう1つの構成にまとめるか」というリポジトリ構成そのものを対象にします。
コード共有とアトミックな変更 — モノレポの利点
Google傘下でモノレポ関連ツールを開発するコミュニティがまとめた解説では、モノレポの利点として「コード共有のしやすさ」「アトミックなコミット」「組織全体でのルール統一」の3点が整理されています*1。
ポリレポでは、共通コードを他プロジェクトで使うために専用リポジトリを作り、パッケージとして公開する手間が発生します。モノレポでは、フォルダを作成するだけで他プロジェクトからコードを参照できるため、公開の手間がなくなります*1。
横断的な変更のしやすさも大きな利点です。フロントエンドとバックエンドの両方に影響する変更を、ポリレポでは複数のリポジトリで別々のプルリクエストとして管理し、マージの順序を調整する必要があります。モノレポでは、関連する変更を1つのコミットにまとめて記録できます*1。
組織のルール適用も統一しやすくなります。リンタの設定やコーディング規約、依存パッケージのバージョンといった取り決めを、リポジトリごとに個別管理するのではなく、組織全体で一元的に実装できます*1。ポリレポでは、破壊的な変更の影響が開発サイクルの後半で見つかりやすく、調整コストが高くなる傾向がある点も、同解説で指摘されています*1。
ビルド時間と権限管理 — モノレポの課題
モノレポには課題も存在します。第一に、リポジトリの規模が大きくなるほど依存関係の連鎖が深くなり、単純なビルド対象でも数万規模のビルドターゲットに依存することがあると、Googleの内部ビルドシステムを一般公開したBazelの公式解説で説明されています*2。全体を毎回ビルドし直す運用では、コードベースの成長に比例してビルド時間が伸びていきます。
第二に、権限管理の設計が必要になります。1つのリポジトリに複数チームのコードが集まるため、誰がどのディレクトリの変更に責任を持ち、どのプルリクエストで承認が必要かを明示する仕組みがなければ、レビュー体制が曖昧になりやすいです。
第三に、スケールの問題です。開発者数やプロジェクト数が増えるほど、依存関係グラフの解析・キャッシュ管理・分散ビルドの仕組みが求められます。これらの課題に対応するために生まれたのが、Nx・Turborepo・Bazelといったモノレポ専用のビルドツールです。
Nx・Turborepo・Bazel — モノレポを支えるツールの種類
モノレポを支えるツールには、いくつかの系統があります。優劣を一概に決めるものではなく、対象言語・規模・既存の技術スタックによって選択が変わります。
Nx — プロジェクトグラフとタスクグラフによる管理
Nxは、ファイルシステムを解析してプロジェクトを検出し、package.jsonやproject.jsonの情報からプロジェクト間の依存関係を自動で把握するツールです*3。検出した依存関係は「プロジェクトグラフ」として表現されます。
Nxはプロジェクトグラフから「タスクグラフ」を生成します。プロジェクトが依存関係を持っていても、テストなど一部のタスクは独立して並列実行できる点が特徴です*3。加えて、ソースファイル・設定・依存関係からハッシュ値を計算し、同じ入力であればキャッシュされた結果を再利用する仕組みを備えています*3。
Turborepo — JavaScript/TypeScript向けの高性能ビルドシステム
Turborepoは、JavaScriptおよびTypeScriptのコードベース向けに設計された高性能ビルドシステムです*4。公式ドキュメントでは、モノレポの規模が大きくなるほど各ワークスペースが個別にテスト・リント・ビルドを実行するため、1回のCIで数千のタスクを処理する必要が生じる課題を挙げています*4。
この課題に対し、Turborepoはリモートキャッシュによってタスク結果を保存し、CIが同じ作業を繰り返さない仕組みと、利用可能な全コアを使ってタスクを並列スケジューリングする仕組みを提供しています*4。既存のpackage.jsonのスクリプトと依存関係を活用しながら段階的に導入できる点も特徴です*4。
Bazel — Googleが公開した大規模ビルドシステム
Bazelは、Googleの内部ビルドシステムをもとに公開されたオープンソースのビルドツールです。処理単位を細かく分割し、任意の台数のマシンに処理を分散できる「アーティファクトベースのビルドシステム」として設計されています*2。ビルドの再現性(同じ入力から常に同じ出力が得られること)を前提にリモートキャッシュを機能させる点が特徴です*2。言語やエコシステムを問わず適用できる汎用性がある一方、導入・運用にはビルドルールの設計スキルが求められます。
このほか、Rust製の高速な処理を特徴とするツールや、モノレポ内のリポジトリを実際には統合せずに依存グラフだけを接続する「シンセティックモノレポ」という手法も紹介されています*1。既存リポジトリを移動せずに段階的な可視化から始められる選択肢です。
依存グラフとキャッシュで影響範囲だけを再ビルドする仕組み
モノレポ専用ツールに共通する中核の仕組みは、依存グラフとキャッシュの組み合わせです。まずツールがリポジトリ内のプロジェクトとその依存関係を解析し、依存グラフを構築します。次に、変更されたファイルからグラフをたどり、影響を受けるプロジェクトだけを特定します。
Nxはこの処理を「Affected Detection(影響検出)」と呼び、プルリクエスト内で変更されたファイルの性質を分析して、影響を受ける最小限のプロジェクトセットを特定します*3。影響のないプロジェクトのタスクはすべてスキップできるため、変更内容に対して必要な分だけビルド・テストを実行できます*3。
キャッシュの仕組みには、同一マシン内で再利用するローカルキャッシュと、組織全体で計算結果を共有するリモートキャッシュの2種類があります*1。リモートキャッシュを使うと、あるチームメンバーが既にビルド済みの成果物を、別のメンバーやCI環境が再度ビルドせずに取得できます*1。
Bazelの解説では、開発者のマシンとCIシステムが共通のリモートキャッシュサービスを参照し、アーティファクトが既に存在すればビルド時間を節約できると説明されています*2。ただし、このキャッシュが有効に機能するための前提条件は、ビルドが完全に再現可能であることです*2。同じ入力から異なる出力が生まれる設定になっていると、キャッシュが信頼できず効果が薄れます。
段階的集約とCIの整備 — 移行の進め方
ポリレポからモノレポへの移行は、既存プロジェクトを一度に統合するのではなく、段階的に進めるのが実務上の一般的な進め方です。最初に依存関係が少なく影響範囲を見積もりやすいプロジェクトから移行し、CIとキャッシュの動作を確認しながら対象を広げていく流れになります。
移行の初期段階でまず必要なのは、既存の各リポジトリがどのようなコードを共有しているか、どのプロジェクトがどのプロジェクトに依存しているかを整理する作業です。この依存関係の把握が曖昧なままツールを導入すると、依存グラフが実態と合わず、影響検出の精度が下がります。
次に、選定したモノレポツール(Nx・Turborepo・Bazelなど)の設定ファイルを整備し、既存のビルド・テストスクリプトを段階的に組み込みます。同時に、CIパイプラインをリポジトリ単位の実行からタスク単位の実行に切り替える改修が必要になります。移行の途中でも既存の開発を止めずに進められるよう、統合済みプロジェクトと未統合プロジェクトが共存できる設計にしておくことが大切です。
最後に、リモートキャッシュの導入とチーム全体への運用ルールの共有を行います。キャッシュが機能するには前述のとおりビルドの再現性が前提となるため、環境依存の設定(絶対パスの埋め込みやタイムスタンプ依存の処理など)が残っていないかを移行時に点検しておく必要があります。
CODEOWNERSによるコード所有者の設計
複数チームのコードが1つのリポジトリに集まるモノレポでは、誰がどの範囲のコードに責任を持つかを明示する仕組みが欠かせません。GitHubの公式ドキュメントによると、CODEOWNERSファイルは「リポジトリ中のコードに対して責任を負う個人あるいはTeamを指定」する仕組みで、他者が所有するコードを変更するプルリクエストが作成されると、該当するコードオーナーへ自動的にレビューが依頼されます*5。
CODEOWNERSファイルはリポジトリのルート・.github/・docs/ディレクトリのいずれかに配置し、最初に見つかったファイルが使用されます*5。パターンとオーナーを1行ずつ記述する形式で、ディレクトリ単位・拡張子単位のいずれでも指定できます*5。コードオーナーに指定する対象は、そのリポジトリへの書き込み権限を持つ個人またはチームである必要があります*5。
モノレポ移行のタイミングでCODEOWNERSを整備しておくと、プロジェクトの境界が曖昧なまま運用が始まる事態を避けられます。ディレクトリ構成の設計とCODEOWNERSの設計は連動するため、移行の設計フェーズでまとめて検討することをお勧めします。
外注の委託範囲と発注準備
モノレポ移行を外注する際は、意思決定が必要な部分と実装作業を分けて考える必要があります。どのプロジェクトをどの順序で統合するか、ディレクトリ構成をどう設計するか、CODEOWNERSの割り当てをどうするかは、事業とチーム編成を理解している自社側が主導すべき判断です。外注先に丸ごと委ねると、後から組織の実情に合わないディレクトリ構成やレビュー体制になりやすくなります。
一方、モノレポツールの導入設定・依存グラフの構築・CIパイプラインの改修・既存スクリプトの移行作業・リモートキャッシュ環境の構築といった実装作業は、外注先に委託しやすい領域です。特定のツール(Nx・Turborepo・Bazelなど)の設定経験を持つ外注先であれば、設定の初期構築を効率的に進められます。
発注準備として、RFP(提案依頼書)には次の項目を含めておくと提案の比較がしやすくなります。
- 現状のリポジトリ構成:対象リポジトリ数・主要な依存関係・使用言語やフレームワーク
- 移行の目標範囲:全リポジトリの統合か、一部プロジェクトのみの統合か
- 候補ツールの希望:Nx・Turborepo・Bazel等の指定有無、または外注先からの提案を受けるか
- CI/CD環境の現状:利用中のCIサービスと、タスク単位の実行への改修を依頼範囲に含めるか
- 移行スケジュールの制約:段階的移行の希望フェーズ数、既存開発を止めない条件
移行規模が大きいプロジェクトほど、依存関係の調査・設計フェーズに時間を要します。複数の外注先から同一要件で見積もりを取得し、依存グラフの整理方法やキャッシュ設計の提案内容を比較することが、発注後の手戻りを防ぐうえで大切です。
まとめ:モノレポ移行を外注する前に決めておくべきこと
モノレポは、複数リポジトリを1つに集約し、コード共有とアトミックな横断変更を可能にするリポジトリ構成です。一方でビルド時間・権限管理・スケールという課題が伴うため、Nx・Turborepo・Bazelといったツールが依存グラフとキャッシュを使って影響範囲だけを再ビルド・再テストする仕組みを提供しています。
移行を外注で進める場合は、どのプロジェクトから統合するか、ディレクトリ構成とCODEOWNERSをどう設計するかを自社主導で決めることが前提になります。ツールの導入設定・CI改修・既存スクリプトの移行といった実装作業を委託範囲とし、RFPに現状構成と目標範囲を明記することで、外注先からの提案を適切に比較できます。
よくある質問
モノレポとマイクロサービス分割は同じ考え方ですか?
異なる考え方です。モノレポはリポジトリの構成(コードをどう格納・管理するか)を指し、マイクロサービスはアプリケーションの実行単位の分割(サービスをどう分けて動かすか)を指します。モノレポの中に複数のマイクロサービスを格納することも、単一のモノリシックなアプリケーションをモノレポで管理することも可能です。両者は独立した設計判断であり、混同せずに検討することをお勧めします。
Nx・Turborepo・Bazelはどれを選べばよいですか?
対象とする言語やエコシステム、既存の技術スタックによって適したツールが変わるため、一概に優劣を決められません。Turborepoは公式ドキュメントでJavaScript・TypeScriptのコードベース向けに設計されていると説明されています。NxはJavaScript・TypeScriptに加えて複数言語を扱うワークスペースにも対応します。Bazelは言語を問わない汎用性がある一方、ビルドルールの設計スキルが求められます。自社の技術スタックと運用体制を踏まえ、外注先と相談しながら選定することが大切です。
既存のポリレポを一度に統合する必要がありますか?
一度に統合する必要はありません。依存関係が少なく影響範囲を見積もりやすいプロジェクトから段階的に移行し、CIとキャッシュの動作を確認しながら対象を広げる進め方が実務では一般的です。すべてのリポジトリを物理的に統合せず、依存グラフだけを接続する「シンセティックモノレポ」という選択肢も紹介されています。移行の目標範囲は、外注先への発注前に自社で方針を決めておく必要があります。
CODEOWNERSはモノレポ移行のどの段階で設計しますか?
ディレクトリ構成の設計と同時に検討することをお勧めします。CODEOWNERSはリポジトリ中のコードに責任を持つ個人・チームを指定し、該当コードへの変更時に自動でレビューを依頼する仕組みです。ディレクトリ構成が固まった後に権限設計を後付けすると、チームの担当範囲とディレクトリの区切りが一致せず、レビュー体制が曖昧になりやすくなります。移行の設計フェーズでまとめて決めておくことが大切です。
モノレポ移行の外注ではどこまで委託できますか?
意思決定と実装作業を分けて考える必要があります。統合するプロジェクトの選定・ディレクトリ構成・CODEOWNERSの割り当てといった判断は、事業とチーム編成を理解する自社側が主導すべき領域です。一方、モノレポツールの導入設定・依存グラフの構築・CIパイプラインの改修・既存スクリプトの移行作業は、外注先に委託しやすい実装領域です。RFPで委託範囲を明記し、複数の外注先から提案を比較することをお勧めします。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:Monorepo.tools「What is a monorepo?」
- *2 出典:Bazel「Distributed Builds」(Bazel公式ドキュメント)
- *3 出典:Nx「Mental Model」(Nx公式ドキュメント)
- *4 出典:Turborepo「Turborepo Documentation」(Vercel、Turborepo公式ドキュメント)
- *5 出典:GitHub「コードオーナーについて」(GitHub Docs)