「アーキテクチャ図はもう要らない」は本当か? ── LLM時代のC4モデル再考
「アーキテクチャ図はもう要らない」は本当か? ── LLM時代のC4モデル再考
前編: アーキテクチャ図、コードで書こう - C4モデル入門
はじめに
LLMに「こういうアプリ作って」と頼めば動くコードが出てくる時代に、アーキテクチャ図を描くのは遠回りに感じるかもしれません。
しかし、LLMがコードを書く時代だからこそ、アーキテクチャ図の価値はむしろ高まっています。
「誰でも作れる時代」に起きていること
LLMの登場で、ソフトウェア開発の敷居は劇的に下がりました。自然言語で要件を伝えるだけで「とりあえず動くもの」が手に入ります。LLMに実装を任せる「バイブコーディング」も珍しくなくなりました。
しかし、チームや組織の現場ではこんな経験はないでしょうか。
- チームの各メンバーがLLMを使って機能を高速に実装していたが、いざ統合すると同じ機能が複数のモジュールに重複していた
「コードを生成する前にLLMにコードベース全体を読ませればいいのでは?」と思うかもしれません。実際、CodexやClaude Codeのようなコーディングエージェントはリポジトリの構造を把握した上でコードを生成します。
しかしコードから読み取れるのは「今どうなっているか」だけで、「なぜそう設計したか」「今後どう発展させたいか」は分かりません。コンテキストウィンドウにも限りがあり、コードベースが大きくなるほど全体の俯瞰は難しくなります。
アーキテクチャ図は「人間とLLMの共通言語」になる
根本にあるのは、人間とLLMの間に「設計意図をやり取りする手段」がないことです。自然言語は曖昧になりがちで、コードは詳細すぎて全体像が見えない。その間をアーキテクチャ図が埋めます。
これは双方向に働きます。
人間 → LLM: 設計意図を伝える
「バックエンドAPIにPDF生成機能を追加して」という指示だけでは、既存の構成要素間の依存関係や責務の境界は伝わりません。アーキテクチャ図を添えれば、システム全体の中での位置づけが明確になり、LLMは適切な箇所に手を入れられます。
LLM → 人間: 設計を確認する
逆に、LLMが生成したコードをアーキテクチャ図に落とし込めば、数千行のコードを読まずとも設計判断の全体像が把握できます。
C4モデルについて
前編の記事で以下のようなアーキテクチャ図にありがちな課題を解決するアプローチとしてC4モデルを紹介しました。
- フォーマットがバラバラ
- PowerPoint、Googleスライド、draw.io、..
- 人によって使うツールが異なり、編集できる人が限られる
- 粒度がバラバラ
- ある人は例1のようなシンプルな図を描き、別の人は例2のような詳細な図を描く
-「どこまで書けばいいの?」といった疑問が生まれる
- ある人は例1のようなシンプルな図を描き、別の人は例2のような詳細な図を描く
- 図が巨大化
- 複数システムの連携が増えると、1枚の図にすべてを詰め込もうとして読めなくなる
C4モデルはアーキテクチャを4つの階層で表現し、抽象度・粒度を統一する技法です。
- コンテキスト図(System Context diagram)
- コンテナ図(Container diagram)
- コンポーネント図(Component diagram)
- コード図(Code diagram)
C4モデルがLLM時代に適している理由
「人間とLLMの共通言語」としてC4モデルが特に適している理由は3つあります。
テキストベースだから、双方向のやり取りが成立する
C4モデルはPlantUMLやStructurizr DSLなどテキストベースの記法で記述できます。
テキストなので、プロンプトに含めてLLMに渡せるし、LLMが生成・修正もできます。Gitでバージョン管理でき、差分のレビューも容易です。
階層構造がLLMに渡すコンテキストを制御する
C4モデルの4階層(コンテキスト → コンテナ → コンポーネント → コード)は、抽象度のズームレベルです。タスクに応じた階層を選べば、必要な粒度の情報だけをLLMに渡せます。
- 新機能の設計方針を相談するならコンテキスト図で全体像を共有
- 特定のコンテナに機能を追加するならコンテナ図で周辺の依存関係を示す
- モジュールの内部設計を議論するならコンポーネント図で詳細を提示
LLMの出力をレビュー可能な形に変換できる
バイブコーディングなどでLLMが大量のコードを生成した場面で特に有効です。
LLMにC4モデルの図を生成させれば、全体構造を俯瞰した上で「ここのセキュリティが危ない」「ここはスケールしない」とピンポイントで指摘できます。「LLMが作ったものを人間がレビューする」というワークフローにそのまま乗ります。
LLMでC4モデルを扱う実践例
ここからは具体的なユースケースを紹介します。前編と同じ帳票出力・メール通知システムを例にします。
ユースケース1: 設計意図を伝えてゼロから生成する
最もシンプルな使い方は、自然言語のシステム概要からC4モデルの図を生成させることです。
あなたはソフトウェアアーキテクトです。
以下のシステム概要をもとに、C4モデルのコンテナ図をPlantUMLで作成してください。
【システム概要】
社内向けの帳票出力・メール通知システム。
ユーザーがWebアプリから帳票を作成すると、
バックエンドAPIがPDFを生成してS3に保存し、
メール通知サービスがSESを使って社内ユーザーに通知する。
データはPostgreSQLに保存される。
このプロンプトに対して、Claude Opus 4.6は以下のようなコンテナ図を生成します。

PlantUMLコード
@startuml C4_Container_Diagram
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
title 社内帳票出力・メール通知システム — コンテナ図
Person(user, "社内ユーザー", "帳票の作成・ダウンロードを行う")
System_Boundary(system, "帳票出力・メール通知システム") {
Container(webapp, "Web アプリケーション", "Vue.js", "帳票の作成フォームや\nダウンロード画面を提供する")
Container(api, "バックエンド API", "Rust", "帳票作成リクエストを受け付け、\nPDF 生成・保存を行い、\n通知イベントを発行する")
Container(mail_service, "メール通知サービス", "Rust / Lambda", "帳票作成イベントを受信し、\n社内ユーザーへ\nメール通知を送信する")
ContainerDb(db, "データベース", "PostgreSQL", "帳票メタデータ、\nユーザー情報、\n通知履歴を保存する")
Container(s3, "PDF ストレージ", "Amazon S3", "生成された帳票 PDF\nファイルを保存する")
}
System_Ext(ses, "Amazon SES", "メール配信サービス")
Rel(user, webapp, "帳票を作成・ダウンロード", "HTTPS")
Rel(webapp, api, "API リクエスト", "HTTPS / JSON")
Rel(api, db, "読み書き", "TCP / SQL")
Rel(api, s3, "PDF をアップロード", "HTTPS / AWS SDK")
Rel(api, mail_service, "通知イベントを発行", "非同期メッセージ")
Rel(mail_service, ses, "メール送信を依頼", "HTTPS / AWS SDK")
Rel(mail_service, db, "通知履歴を記録", "TCP / SQL")
Rel_Back(user, ses, "通知メールを受信", "SMTP")
@enduml
ユースケース2: 既存の図に変更意図を伝えて更新する
C4モデルが真価を発揮するのは、既存の図がある場面です。変更内容を自然言語で指示するだけで、LLMは図の文脈を理解した上で更新できます。
以下のPlantUMLで記述されたコンテナ図を修正してください。
変更内容:
- バックエンドAPIのPDF生成部分をAWS Lambdaに切り出す
- Lambda関数はSQSキュー経由でバックエンドAPIから呼び出される
【現在のコンテナ図】
(PlantUMLコードを貼り付け)
ユースケース1で生成した図にこの変更指示を渡すと、以下のように更新されます。
コンテナの変更
System_Boundary(system, "帳票出力・メール通知システム") {
Container(webapp, "Web アプリケーション", "Vue.js", "帳票の作成フォームや\nダウンロード画面を提供する")
- Container(api, "バックエンド API", "Rust", "帳票作成リクエストを受け付け、\nPDF 生成・保存を行い、\n通知イベントを発行する")
+ Container(api, "バックエンド API", "Rust", "帳票作成リクエストを受け付け、\nPDF 生成ジョブをキューへ投入し、\n通知イベントを発行する")
+ ContainerQueue(sqs_pdf, "PDF 生成キュー", "Amazon SQS", "PDF 生成ジョブを\n非同期で受け渡す")
+ Container(pdf_lambda, "PDF 生成 Lambda", "Rust / Lambda", "キューからジョブを受信し、\nPDF を生成して\nS3 へ保存する")
Container(mail_service, "メール通知サービス", "Rust / Lambda", "帳票作成イベントを受信し、\n社内ユーザーへ\nメール通知を送信する")
ContainerDb(db, "データベース", "PostgreSQL", "帳票メタデータ、\nユーザー情報、\n通知履歴を保存する")
Container(s3, "PDF ストレージ", "Amazon S3", "生成された帳票 PDF\nファイルを保存する")
}
リレーションの変更
Rel(api, db, "読み書き", "TCP / SQL")
- Rel(api, s3, "PDF をアップロード", "HTTPS / AWS SDK")
+ Rel(api, sqs_pdf, "PDF 生成ジョブを投入", "HTTPS / AWS SDK")
+ Rel(sqs_pdf, pdf_lambda, "ジョブをトリガー", "SQS イベント")
+ Rel(pdf_lambda, s3, "PDF をアップロード", "HTTPS / AWS SDK")
+ Rel(pdf_lambda, db, "生成ステータスを更新", "TCP / SQL")
Rel(api, mail_service, "通知イベントを発行", "非同期メッセージ")

PlantUMLコード
@startuml C4_Container_Diagram
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
title 社内帳票出力・メール通知システム — コンテナ図
Person(user, "社内ユーザー", "帳票の作成・ダウンロードを行う")
System_Boundary(system, "帳票出力・メール通知システム") {
Container(webapp, "Web アプリケーション", "Vue.js", "帳票の作成フォームや\nダウンロード画面を提供する")
Container(api, "バックエンド API", "Rust", "帳票作成リクエストを受け付け、\nPDF 生成ジョブをキューへ投入し、\n通知イベントを発行する")
ContainerQueue(sqs_pdf, "PDF 生成キュー", "Amazon SQS", "PDF 生成ジョブを\n非同期で受け渡す")
Container(pdf_lambda, "PDF 生成 Lambda", "Rust / Lambda", "キューからジョブを受信し、\nPDF を生成して\nS3 へ保存する")
Container(mail_service, "メール通知サービス", "Rust / Lambda", "帳票作成イベントを受信し、\n社内ユーザーへ\nメール通知を送信する")
ContainerDb(db, "データベース", "PostgreSQL", "帳票メタデータ、\nユーザー情報、\n通知履歴を保存する")
Container(s3, "PDF ストレージ", "Amazon S3", "生成された帳票 PDF\nファイルを保存する")
}
System_Ext(ses, "Amazon SES", "メール配信サービス")
Rel(user, webapp, "帳票を作成・ダウンロード", "HTTPS")
Rel(webapp, api, "API リクエスト", "HTTPS / JSON")
Rel(api, db, "読み書き", "TCP / SQL")
Rel(api, sqs_pdf, "PDF 生成ジョブを投入", "HTTPS / AWS SDK")
Rel(sqs_pdf, pdf_lambda, "ジョブをトリガー", "SQS イベント")
Rel(pdf_lambda, s3, "PDF をアップロード", "HTTPS / AWS SDK")
Rel(pdf_lambda, db, "生成ステータスを更新", "TCP / SQL")
Rel(api, mail_service, "通知イベントを発行", "非同期メッセージ")
Rel(mail_service, ses, "メール送信を依頼", "HTTPS / AWS SDK")
Rel(mail_service, db, "通知履歴を記録", "TCP / SQL")
Rel_Back(user, ses, "通知メールを受信", "SMTP")
@enduml
PDF生成の責務が バックエンドAPI から PDF生成Lambda に移り、間に PDF生成キュー が追加されたことが図から一目で分かります。
ユースケース3: LLMの知見を引き出してレビュー・改善する
既存のC4モデルの図をLLMに読ませて、不整合や改善点を指摘させる使い方です。
以下のPlantUMLで記述されたC4モデルのコンテナ図をレビューしてください。
確認ポイント:
- コンテナ間の依存関係に循環がないか
- 単一障害点がないか
- 責務が適切に分割されているか
- C4モデルの記法として適切か
【コンテナ図】
(PlantUMLコードを貼り付け)
単一のLLMにレビューさせるだけでも有用ですが、「生成」と「レビュー」を別のエージェントに分担させて反復的にフィードバックを回せば、見逃しがちな不整合も検出できます。
RAGを組み合わせて社内のアーキテクチャ規約を参照させれば、組織固有のルールに沿ったレビューも可能です。
MCPサーバーの利用
手動でプロンプトを書く以外に、MCPサーバーによる自動化も進んでいます。C4Diagrammerは既存のコードベースからC4モデルの図(Mermaid形式)を自動生成するツールです。C4モデルベースのソフトウェアアーキテクチャ可視化・ドキュメントツールであるIcePanelもMCP Serverを公開しています。プロンプトエンジニアリングに頼らず、LLMワークフローにC4モデルの図の生成を組み込める環境が整いつつあります。
ただし、LLMは予算制約やデプロイ手順といった現実の文脈を把握しきれないこともあります。生成結果はあくまで叩き台として、人間がレビュー・修正する前提で使いましょう。
まとめ
C4モデルは、テキストベースで階層構造を持ち、LLMが読み書きできる。だからこそ、人間とLLMの間の「設計の共通言語」として機能します。
「アーキテクチャ図はもう要らない」のではなく、「人間とLLMの共通言語として進化した」——それがLLM時代の答えではないでしょうか。
C4モデルの基本や詳細な実践方法に興味がある方は、ぜひ前編もご覧ください。
Discussion