はじめに
GMOコネクトの永田です。
提案や要件整理の場で、AWSの構成図を描くことが度々あります。ただ、都度ていねいに手で描くと時間がかかります。それなら構成案から自動で生成できればと思い、既存のAWS公式スキルなども試しました。ところが出てくるのは細部まで描き込んだ実装寄りの図で、提案や要件整理の段階でほしい「まず全体像をつかんでもらう概要図(俯瞰図)」としては、どうも合いませんでした。
何が悪いのかを腰を据えて分解してみたら、原因は絵の上手い下手ではなく「色と線の使い方」でした。そしてこの整理を一度言語化したら、同じ品質の俯瞰図を量産できるようになりました。
この記事は、その「俯瞰説明に振り切ったAWS構成図」を、見やすさを機械チェックしながら量産できるようにした自作スキルの記録です。Claude Code から呼ぶ前提で作っていますが、肝は構成図そのものの設計の話なので、ツールを問わず使える考え方だと思います。
先にまとめ
構成図は「何のために描くか」で必要な粒度が変わります。今回ほしかったのは、提案や全体共有でまず全体像をつかんでもらう"俯瞰図"でした。詳細図と俯瞰図はどちらが上というものではなく、用途で選ぶものです。
| 場面 | ほしい図 | 重視すること |
|---|---|---|
| 実装・レビュー・棚卸し | 詳細図 | 細部まで正確・網羅的(サブネット/SG/依存まで) |
| 提案・要件整理・全体共有 | 俯瞰図(今回つくったもの) | 全体像が一目で入る・視線が流れる |
今回自動生成した俯瞰図の例(after・自作HTML+SVGスキル)
- 提案・全体共有という用途に合わせて、粒度を俯瞰に振る(詳細図と優劣ではなく使い分け)
- 色と線は「サービス分類」ではなく「データの流れ」に使う。分類は配置と注釈に逃がす
- 「線の重なり」「凡例との被り」「無関係なノード/枠の貫通」を機械チェックして見やすさを担保する
「どこを見ればいいか分からない図」問題
構成図に求めるものは、場面によって違います。設計レビューや実装では細部まで正確な図が要りますが、提案や全体共有の場では「まず全体像をつかんでもらう」ことが先です。
ところが、要素をひとつ残らずきちんと描き込むと、密度が上がるほど初見では流れを追えなくなります。線が交差し、どのサービスが主役で、データがどっちに流れているのかが一目で分からない。「正確さ」と「俯瞰での伝わりやすさ」は、別の指標でした。
これは私の感覚だけの話ではありません。AWS の Security Reference Architecture(公式)でも、構成図の粒度は目的で決める、という立場が示されています。要旨はこうです ──「ほとんどの構成図はWeb・アプリ・データ層を深掘りするが、読みやすさのためにセキュリティ統制は省くことが多い。この図はその強調を反転し、セキュリティを可能な限り見せ、アプリ層とデータ層は意味が通る範囲で必要十分なだけ単純化している」。唯一正しい粒度があるのではなく、目的に応じて何を強調し何を省くかを決める、というわけです(出典: AWS Security Reference Architecture)。
原因は「色と線が"分類"を表していたこと」
「正確だけど俯瞰図としては見づらい図」とは、たとえばこういう図です。今度は"なぜ見づらいのか"という目で分解してみます。
整然と描けているのに頭に入ってこない。いちばん目立つ色が「サービスの分類」を表していて、俯瞰図を求める読者が本当に追いたい「データの流れ」とは無関係でした。色という強い手がかりが、流れと違う方向を指していたわけです。
考え方はシンプルです。before が悪いのではなく、俯瞰という用途に合わせて「細部は割り切り、色と線を"流れの意味"だけに使う」と決めます。
- 線は意味で色分けする(5系統)。inbound/内部=青の実線、外向き(egress)=橙、認証=紫の点線、バックアップ=赤の破線、運用=灰の破線
- 枠や背景は分類色で塗らない(中立にする)。アイコンは公式アイコンをそのまま置く
- 監視・IAM・セキュリティのような横断サービスは、線を引かず上部の帯に並べるだけにする。これだけで線が10本以上減ります
- 設計上の判断(「NAT経由でegress」「Multi-AZ」など)は線でなく注釈で書く。線の本数を増やさずに情報量を足せます
色と線が「流れ」だけを指すようになると、視線が番号付きの主フロー(①②…)に自然に乗ります。
規模の上限の目安もあります。だいたい30ノードまでは「単一のメイン図+周辺の帯+注釈」で1枚に収まります。それを超えるなら、重い関心事(セキュリティ集約など)だけをドリルダウンのタブに逃がします。
既存ツールとの使い分けと、自作した理由
念のためですが、既存ツールがダメという話ではありません。今回の用途 ── 提案用の俯瞰図を、読みやすさを担保しながら出す ── に最短で当たるものが手元になかった、という使い分けの話です。
実際に足りなかったのは、次の2点でした。
- 何を最適化して生成するか(粒度): 既存の自動生成は実装・棚卸し向けの詳細な粒度に最適化されていて、提案用の俯瞰(主要素+流れだけ)にはそのまま向きません。レイアウトもアイコンをカテゴリ色の箱に詰める方向で、前述の「色=分類」と相性がよくありません
- 読みやすさを機械で確認できるか: 俯瞰図は読みやすさが命ですが、線の重なりや無関係なノードの貫通を機械チェックする仕組みは、どのツールにもありませんでした(Mermaid や Python diagrams もレイアウトは自動ですが、俯瞰向けの最適化やこの種のチェックは持っていません)
この2点に最短で当たるものが無かったので、自作しました。
フォーマットは単一HTML(SVG)にしました。SVG が優れているからではなく、後述のレイアウト計算と読みやすさチェックを1ファイルに同梱でき、そのまま配れて Chrome headless で PNG 化もできるからです。ファイルの中身は2つに分かれています ── 案件ごとに書き換える「データ」(どこに何を置き、どこからどこへ線を引くか)と、それを描く固定の「エンジン」(座標計算・直交配線・読みやすさチェックを担う素のJavaScript 約100行)です。書き手が触るのはデータの側だけです。
// NODES: アイコンを「どこに置くか」。icon は AWS 公式アイコンの slug
const NODES = [
{id:'alb-ext', x:760, y:560, icon:'application-load-balancer', nm:'外部公開 ALB', sx:'internet-facing / HTTPS'},
{id:'ec2-web', x:760, y:798, icon:'ec2', nm:'Web層 EC2', sx:'Nginx + React.js'},
// ...
];
// WIRES: 「どこからどこへ」線を引くか。col=線の意味色, mk=矢じり
const WIRES = {
main: [
{f:'alb-ext', fs:'bottom', t:'ec2-web', ts:'top', col:I, mk:'ar-in', lab:'振り分け'}, // I=青(inbound)
{f:'ec2-app', fs:'top', t:'nat', ts:'bottom', col:E, mk:'ar-eg', lab:'外部更新'}, // E=橙(egress)
],
};
このように、書き手が宣言するのは「置き場所(NODES)」と「流れ(WIRES)」だけです。座標や直交配線の細かい計算は、上で触れたエンジンが引き受けます。
見やすさを機械チェックする
ここが今回いちばん効いた部分です。コードは lint できるのに、図の「見やすさ」を直す基準はありません。そこで、描画のたびに次の4観点を自動チェックするようにしました。
- overlaps: 別々の線が同じ直線上で重なって、1本に潰れて見える
- legend-hits: 線が凡例に被って、凡例が線を隠す/誤読させる
- node-cross: 始点でも終点でもないノードを線が横切る(そのサービスに繋がっていると誤読される)
- group-cross: 関係のない VPC/サブネット枠を線が貫通する
どれも「見やすさ」を壊す典型で、人の目だと見落とします。描画のたびに hidden なレポートへ出力し、headless で grep できるようにしました。
// 描画時に集めた直交セグメント _segs から、
// 別ワイヤ同士が同一直線上で重なって「1本に潰れて見える」箇所を検出する
function checkWires(){
const EPS = 2.5, MIN = 12, overlaps = [];
for (let i = 0; i < _segs.length; i++) for (let j = i+1; j < _segs.length; j++){
const s = _segs[i], t = _segs[j];
if (s.wi === t.wi || s.axis !== t.axis || Math.abs(s.c - t.c) > EPS) continue; // 別線・同じ向き・ほぼ同一線上
const ov = Math.min(s.hi, t.hi) - Math.max(s.lo, t.lo); // 重なっている長さ
if (ov > MIN) overlaps.push({s, t});
}
// legend-hits / node-cross / group-cross も「線分 × 矩形」の交差判定で同様に検出(略)
report.textContent =
`WIRECHECK view=${CUR} overlaps=${overlaps.length} legend-hits=... node-cross=... group-cross=...`;
}
chrome --headless --dump-dom "file://.../図.html" | grep WIRECHECK
# => WIRECHECK view=main overlaps=0 legend-hits=0 node-cross=0 group-cross=0
URLハッシュに check を付けると、画面上でも色分けして可視化します(overlaps=ピンク/legend-hits=橙/node-cross=青/group-cross=紫)。下の図は、同じ範囲を拡大して、わざと線を崩した例(上)と、それを直して0件にした状態(下)を並べたものです。
この自己点検を入れてから、自分では問題ないと思っていた図にも線の被りが残っていたことに気づけるようになりました。「4観点すべて 0」を通すまで直す、を作図の締めにしています。
ただし機械チェックで分かるのは「見やすさ」だけです。「設計書にある線を描き漏れていないか/無い線を憶測で描いていないか」は別問題で、元の設計書のフローと1本ずつ突き合わせる手動レビューは残ります。
まとめ
- 構成図の粒度は目的で決める。詳細図と俯瞰図は優劣でなく使い分け
- 整然なのに頭に入らない図は、色と線が「分類」を指しているのが原因。色と線は「流れ」に寄せ、分類は配置と注釈に逃がす
- 横断サービスは線を引かず帯に。設計判断は線でなく注釈に
- 「見やすさ」は機械チェックできる(線の重なり/凡例被り/無関係ノード・枠の貫通の4観点)
- 描き漏れ・描き過ぎは機械では拾えない。設計書との突き合わせは手で残す
補足: 再現するときの小さなハマり
- SVGの矢じり(marker)は
markerUnitsを省くと既定で線幅ぶん拡大され、太い線だと終端の折れ角を巻き込んで「壊れた矢印」に見えます。markerUnits="userSpaceOnUse"で固定サイズにすると直ります - 横方向の線は「アイコンの縦中心」、縦方向の線は「ノードの下端/上端」でアンカーすると、副題のあるノードとないノードで高さが変わってもZ字にならず一直線に揃います
最後に、GMOコネクトではサービス開発支援や技術支援をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。



