TECH PLAY

Redis

イベント

該当するコンテンツが見つかりませんでした

マガジン

技術ブログ

.entry .entry-content .table-of-contents > li > ul { display: none; } はじめに こんにちは、カート決済部カート決済基盤ブロックの林です。普段はZOZOTOWN内のカート機能や決済機能の開発、保守運用、リプレイスを担当しています。 ZOZOTOWNの購入フローは、セッションに強く依存したロジックが長年の改修により肥大化し、機能改善や保守の際の調査・改修コストが増大していました。この課題を解決するため、私たちのチームは2024年5月から約2年にわたる段階的なリプレイスプロジェクトを進めています。 ミッションクリティカルな購入フローを無停止で移行するため、私たちは3つのフェーズに分けた段階的なアプローチを採用しました。本記事では、その実践的な進め方と、実際に直面した課題について紹介します。 なお、同じチームの多田と三浦が、このリプレイスにおけるアーキテクチャ選択(モジュラモノリス)の背景と設計について別の記事で紹介していますので、併せてご覧ください。 techblog.zozo.com 目次 はじめに 目次 背景・課題 セッションに依存したロジックの肥大化 サービス無停止でのリプレイス要件 新システムの構成とセッション問題の解決 既存システムの問題点 新システムの構成 Shopping BFF + Redisによる解決 リプレイス戦略の全体像 なぜ段階的なアプローチを選んだか 3つのフェーズに分けたアプローチ フェーズの関係性 現在の進捗状況 フェーズ1:一部機能の比較フェーズ 比較対象の選定 並行稼働の仕組み 比較・検証方法 フェーズ1で得られた知見 フェーズ2:段階的な入れ替えフェーズ 入れ替え順序の工夫 切り替えの仕組み 二重開発の最小化 フェーズ2の成果 フェーズ3:全体リプレイス n%リリースによる段階的な移行 n%リリースの設計方針 各段階での検証項目 全体リプレイスにおける課題 課題への対応策 今回の課題と今後の改善点 今後の展望 まとめ 背景・課題 セッションに依存したロジックの肥大化 ZOZOTOWNの購入フローは、Classic ASP(以下、ASP)で実装されており、長年の改修によりセッション情報がいたるところで更新される構造になっていました。この結果、ロジック間の依存関係が複雑化し、機能改善や保守の際の調査コストが増大するとともに、部分的な入れ替えも困難な状態でした。 サービス無停止でのリプレイス要件 ZOZOTOWNの購入フローは、ECサイトの中核をなすミッションクリティカルな領域のため、サービスを停止できません。さらに、リプレイス期間中であっても、新規機能の追加や運用改善は継続的に発生し、それらは既存ロジック側とリプレイス側のどちらにも反映する必要がありました。 その結果、移行にあたっては以下の制約を考慮する必要がありました。 ビッグバン切替の回避 :一括での全面切り替えはリスクが高すぎる 二重開発の不可避 :新旧両システムを並走する以上、修正は両方に入れる必要がある 段階的検証の必須化 :各段階で十分に検証しながら、慎重に移行を進める必要がある これらの課題に対し、私たちは新システムの構築と段階的な移行戦略により解決を図りました。 新システムの構成とセッション問題の解決 既存システムの問題点 既存のASPシステムでは、購入フロー内のいたるところでセッション情報が更新される構造になっており、以下の問題がありました。 1. セッション更新の分散 どのタイミングで何が更新されるか追跡困難 機能改善時の影響範囲を特定しづらい デバッグやトラブルシューティングに時間がかかる 2. 部分的な入れ替えの困難さ セッション情報と密結合しているため、機能単位での切り出しが難しい 段階的なリプレイスを阻害する要因 3. 保守性の低下 新規メンバーがシステムを理解するのに時間がかかる セッション構造の変更が困難 新システムの構成 これらの問題を解決するため、責務を明確に分離した構成を採用しました。 既存システム(リプレイス前) ASP すべてのロジックとセッション管理が密結合 新システム(リプレイス後) 画面層(以下、Shopping BFF) ユーザーの入力値や購入フロー内の一時的な状態を管理 セッションで管理していた情報を専用のRedisで管理(購入フローに閉じた情報のみ) Java/Spring Boot ビジネスロジック層(以下、Shopping API) ビジネスロジックの中核を担う カート、注文、決済などのドメインロジックを実装 Java/Spring Boot、モジュラモノリス構成 Shopping BFF + Redisによる解決 新システムでは、Shopping BFFで状態管理を集約する構成にしました。 設計方針 購入フローに閉じた情報のみをBFFで管理 他のサービスと共有する必要のないデータ 注文プロセス中のみ必要な一時的な状態 Redisでの永続化 ZOZOTOWN共通のセッションではなく専用のRedisで管理 TTL(Time To Live)を設定し、不要なデータは自動削除 メリット 管理箇所の集約 :BFFに状態管理を集中させた結果、見通しが向上 独立性の確保 :各ドメイン(カート、注文、決済)の状態が明確に分離 状態管理をShopping BFFに集約し、ビジネスロジックをShopping APIに分離したことで、状態とロジックの責務を明確に切り分けました。これにより、セッション依存による密結合は解消され、機能単位での段階的な入れ替えが可能になりました。あわせて、システム全体の見通しと保守性が向上しました。 リプレイス戦略の全体像 なぜ段階的なアプローチを選んだか 段階的なアプローチを採用した理由は以下の通りです。 リスクの分散 :機能を小さく区切って検証し、問題発生時の影響範囲を限定する 二重開発の最小化 :新実装へ移行した範囲は旧実装への改修を減らせるため、早期リリースで並行開発の期間を短縮する 継続的なフィードバック :各フェーズで得られた知見を次のフェーズへ反映する チームのモチベーション維持 :小さな成功体験を積み重ね、長期プロジェクトでも前進感を保つ 3つのフェーズに分けたアプローチ これらの理由から、私たちは以下の3つのフェーズに分けてリプレイスを進めてきました。 フェーズ1:一部機能の比較フェーズ 既存ロジック(ASP)と新ロジックを並行稼働 結果を比較・検証し、差分を解消 フェーズ2:段階的な入れ替えフェーズ 比較で問題ないことを確認した機能から順次切り替え 二重開発の負担を最小化 フェーズ3:全体リプレイス 画面を含めた購入フロー全体を新システムに移行 n%リリースで段階的にトラフィックを切り替え フェーズ1とフェーズ2を機能単位で繰り返し、重要機能の切り替えが完了した段階でフェーズ3を実施します。 フェーズの関係性 フェーズ1・2ではビジネスロジック層のリプレイスを先行して進め、フェーズ3では画面層のリプレイスを実施する計画です。ビジネスロジック層を先に安定化させることで、画面リプレイス時には既に検証済みのAPIを使用できる体制を整えています。 現在の進捗状況 2026年2月時点で、フェーズ1・2は既にリリースが完了しており、本番環境で稼働しています。フェーズ3については開発が完了し、現在はリリースに向けた最終準備を進めている段階です。 次の章から、各フェーズの詳細について説明します。 フェーズ1:一部機能の比較フェーズ 比較対象の選定 リスクを最小限に抑えるため、 読み取り系の機能 を比較対象としました。具体的には以下の機能です。 お届け先一覧の取得 支払い方法一覧の取得 配送日時の指定一覧の取得 これらの機能を選んだ理由は以下の通りです。 読み取り専用 :データの更新を伴わないため、万が一の不具合でもユーザーへの影響が限定的 検証が容易 :結果の比較が容易で、差分の原因を特定しやすい 段階的な複雑化 :条件が少ないお届け先一覧から始め、徐々にロジックが複雑な機能へと比較対象を拡大 即時停止が可能 :比較モードを停止するだけで対応可能 並行稼働の仕組み 既存のASPから新しいShopping APIを呼び出す形で並行稼働を実現しました。以下がその仕組みです。 この仕組みの重要なポイントは以下の通りです。 フラグによる制御 :対象機能を柔軟に切り替えられ、トラフィックの切り替えも即座に実施できる ASP側での比較 :両方の結果をASP側で受け取り、差分をチェックする ユーザーへの影響なし :ユーザーには常にASPの結果を返すため、体験に影響を与えない 比較情報の保存 :各種情報をJSONで保存し、集計・分析できる 負荷の考慮 :比較は一部サーバーに限定して実施する 比較・検証方法 保存した比較情報を定期的にチェックし、以下の観点で検証しました。 一致率の確認 :どの程度の割合で結果が一致しているか 差分の原因分析 :不一致の場合、どのようなケースで発生しているか 優先度の判断 :ビジネスへの影響度から修正の優先順位を決定 特に重要だったのは、差分が発生した際の 根本原因の特定 です。多くの場合、以下のような原因がありました。 ASP側のロジックの暗黙的な仕様(ドキュメント化されていない挙動) データベースの参照タイミングによる差異 購入フローはミッションクリティカルな領域のため、これらの差分を1つずつ解消し、 100%一致するまで比較を継続 しました。 フェーズ1で得られた知見 比較フェーズを経て、以下の知見が得られました。 暗黙知の可視化 :長年のシステムに埋もれていた仕様が明らかになった テストケースの充実 :差分から得られた知見をテストケースに反映できた 段階的移行の有効性 :小さく始めるアプローチが、リスク管理に有効であることが明らかになった 次のフェーズでは、この比較で問題ないことを確認した機能から、実際に切り替えを進めていきます。 フェーズ2:段階的な入れ替えフェーズ 入れ替え順序の工夫 比較フェーズで十分に検証した機能から、段階的に切り替えを進めました。具体的な順序の例と、その選定理由をいくつか紹介します。 順序 機能 特徴 1 お届け先一覧の取得 条件が少なく、ロジックがシンプル 2 支払い方法一覧の取得 決済方法の選択可否の判定ロジックが複雑 3 配送日時の指定一覧の取得 在庫や配送条件との連携が必要 この順序で進めた理由は以下の通りです。 リスクの段階的な増加 :シンプルな機能から複雑な機能へ段階的に広げる 経験の蓄積 :各段階で得られた知見を次に活かす 影響範囲の管理 :問題発生時にトラフィックの切り替えをしやすい順序にする 切り替えの仕組み 比較フェーズで差分がないことを確認した機能については、以下のように切り替えました。 重要な変更点は以下の通りです。 比較処理を廃止 :検証済みのため、比較情報の保存は不要 API結果を直接返す :Shopping APIの結果をそのままユーザーに返す 旧ロジックの保守を停止 :切り替え済み機能はASP側を保守対象から除外 二重開発の最小化 このフェーズでは、 二重開発を最小化 できたことが大きな効果でした。 段階的リプレイスのメリット: 切り替え済みの機能に対する新規追加や修正は、新ロジック(Shopping API)のみに実施する 旧ロジック(ASP)への反映が不要になり、開発工数を削減できる ビッグバンリリースとの比較: ビッグバンの場合、切り替え完了まで旧ロジックにも改修が必要になる 開発期間中は変更を二重に実装する必要がある 一方、段階的リプレイスでは、切り替え済み範囲が増えるたびにこの期間を短縮できる 例えば、新しい決済方法の追加が必要になった場合の修正範囲は以下の通りになります。 段階的リプレイス(API層移行済み) :Shopping APIのみ修正 ビッグバンでのリプレイス :ASPとShopping APIの両方を修正 このように、切り替え済みの機能については旧ロジックへの反映が不要になり、長期プロジェクトにおける開発負担を大きく軽減できました。 フェーズ2の成果 フェーズ2を通じて以下の成果を得ました。 対象機能の完全移行 :読み取り系の主要機能をすべて新システムに移行 開発工数の削減 :二重開発の期間を最小化し、チームの生産性が向上 品質の向上 :段階的な検証により、問題を早期に発見・修正 次のフェーズでは、画面を含めた購入フロー全体を新システムに移行します。 フェーズ3:全体リプレイス フェーズ3では、画面を含めた購入フロー全体を新システムに移行する計画で進めています。 n%リリースによる段階的な移行 全体リプレイスでは、トラフィックを段階的に切り替える n%リリース を採用する計画です。同一ユーザーが途中で旧フロー・新フローを行き来しないよう、ユーザー単位で一度割り当てた割合を保持する形でルーティングする設計としています。 n%リリースの設計方針 段階的な切り替えにおいて、以下の方針で進める計画です。 段階 目的 検証期間 備考 1% 本番環境での動作確認と想定外の問題の早期発見 長期 注文から発送完了まで問題なく処理されることを検証 20% 1%で得られた知見を反映し、より大きなトラフィックでの検証 短期 問題がなければ次の段階へ 50% 本番に近い負荷での最終検証 中期 大規模なトラフィックでの安定性を確認 100% すべてのトラフィックを新システムに移行 - 万が一の問題に備え、即座にロールバックできる体制を維持 各段階での検証項目 各n%段階で、以下の項目を重点的に監視する計画です。 機能的な正常性 注文完了率 決済成功率 エラーログの監視 パフォーマンス レスポンスタイム スループット データベースの負荷 問題が発見された場合は、即座に前の割合に戻す体制を整えています。 全体リプレイスにおける課題 フェーズ3では、フェーズ1・2とは異なる課題に直面しています。 1. 機能改修とのコンフリクト 画面を含む全面リプレイスのため、リリースまで約1年半の開発期間が必要になる その間、既存システム(ASP)にも新規機能や改善が継続的に追加される 新旧両方のシステムに同じ変更を反映する 二重開発 が発生する 具体例としては以下が挙げられます。 新しい決済方法の追加 ユーザーインタフェースの改善 バグ修正や運用改善 これらをASPとShopping BFF/Shopping APIのすべてに実装する必要があり、工数が増加しています。 2. モチベーションの維持 長期にわたる開発により、チームのモチベーション維持が課題 「いつ終わるのか」という不安感 同じ機能を二重に実装する徒労感 課題への対応策 これらの課題に対し、以下のように対応しました。 1. フェーズ2の成果を活用 API層はフェーズ2で既に移行済みのため、Shopping APIへの修正のみで対応できる範囲が拡大 BFF層のみの修正で済むケースも多く、完全な二重開発を避けられた 2. 優先度の明確化 新規機能の開発は、極力リプレイスのリリース後に行う 緊急性の高い修正のみ二重開発で対応 今回の課題と今後の改善点 長期にわたるリプレイスプロジェクトにおいて、チームのモチベーション維持が課題として浮上しました。約1年半の開発期間中、同じ機能を二重に実装する必要があり、「いつ終わるのか」という不安感や徒労感がチームに蓄積しやすい状況でした。 今回の経験を踏まえると、次に同様のプロジェクトに取り組む際には、以下の点をあらかじめ検討しておくべきだと感じました。 プロジェクト初期段階でのマイルストーン設計 :長期プロジェクトでも前進感を保てるよう、細かいマイルストーンを設定 定期的な成果の可視化 :各段階での成果を可視化し、チーム全体で進捗を共有する仕組みの構築 チームメンバーのケア体制 :長期プロジェクトにおけるメンバーの心理的負担に配慮した体制づくり 今後の展望 リプレイスプロジェクトの完了後も、以下のような継続的な改善と発展を計画しています。 新システムでの運用安定化と監視体制の強化 リリース完了後は、新システムの安定稼働を最優先とし、監視体制の強化に取り組みます。具体的には、パフォーマンスメトリクスの継続的な収集・分析や、エラー検知の精度向上、アラート体制の整備などを進めていきます。また、運用ノウハウの蓄積と共有により、障害発生時の迅速な対応体制を構築します。 モジュラモノリスからマイクロサービスへの段階的な移行検討 現在のモジュラモノリス構成は、開発効率とシステムの見通しの良さを両立できていますが、将来的にはマイクロサービスへの移行も視野に入れています。ただし、マイクロサービス化はトレードオフを伴うため、ビジネス要件やチーム体制、技術的な成熟度を考慮しながら、慎重に検討を進める方針です。 さらなるパフォーマンス改善と開発体験の向上 新システムへの移行により開発効率は向上しましたが、さらなる改善の余地があります。レスポンスタイムの最適化やデータベースクエリのチューニング、開発ツールの整備など、継続的な改善を通じて、より快適な開発体験とユーザー体験を実現していきます。 得られた知見を他のシステムのリプレイスにも適用 本プロジェクトで得られた段階的リプレイスの手法や、並行稼働による検証のノウハウ、長期プロジェクトにおけるチーム運営の知見は、社内の他システムのリプレイスにも適用可能です。これらの知見を共有し、組織全体の技術力向上に貢献していきます。 まとめ 本記事では、ZOZOTOWNの購入フローにおける段階的リプレイスの実践について紹介しました。 セッションに強く依存した既存システムを、3つのフェーズに分けて段階的にリプレイスしています。 一部機能の比較フェーズ :並行稼働により、リスクを抑えながら新旧ロジックの差分を解消 段階的な入れ替えフェーズ :検証済みの機能から順次切り替え、二重開発の期間を最小化 全体リプレイス (進行中):n%リリースにより、画面を含む購入フロー全体を安全に移行する計画 また、Shopping BFF + Redisの構成により、セッション依存の問題を解消し、システムの見通しと保守性の向上を実現しています。 大規模ECにおける段階的リプレイスを検討している方や、ミッションクリティカルなシステムの無停止移行に取り組んでいる方の参考になれば幸いです。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
この記事は、合併前の旧ブログに掲載していた記事(初出:2023年9月5日)を、現在のブログへ移管したものです。現時点の情報に合わせ、表記やリンクの調整を行っています。Overview30万を超える同時...
テキストベースの図、もっと表現力が欲しい ども! PlantUML × VS Codeの記事 を書いた龍ちゃんです。 Claude Codeを使って爆速でPlantUMLを書けるようになりました。でも!実際に設計書やブログに貼るとなると「もうちょっと見た目をなんとかしたい」ってなるんですよね。図の横に設計ポイントを添えたり、色を揃えて見やすくしたり。 そこで今回は、PlantUMLの図にTailwind CSSの装飾を組み合わせます。1つのHTMLファイルにPlantUML図 + 注釈パネルをまとめて、PNGに変換する仕組みです。 「なんでPlantUML?」理由はシンプルで、Mermaidではカバーできない図があるからです。 コンポーネント図 — database "PostgreSQL" と書くだけであのドラム型DBアイコンが出る アクティビティ図 — ワークフローの分岐・マージを if/else/endif で描ける ユースケース図 — actor "ユーザー" で棒人間アイコンが出る Mermaidはフロー図やシーケンス図が得意ですけど、この3つは守備範囲外なんですよね。PlantUMLならテキストベースのまま作れます。 Mermaid × Tailwind CSSの組み合わせも同時に記事にしてます。フロー図やシーケンス図を作りたい人は「 Mermaid × Tailwind CSS — ハイブリッド図解の作り方 」をどうぞ。 今回の内容です。 コピペ用テンプレート2種(右サイド注釈型 / 左右均等型) PNG変換の手段3つ 関連記事 : 仕様書の図にソースコードと設計意図を添える方法については「 仕様書の図はAIに読ませるな — 軽量コードを添える設計パターン 」で詳しく書いてます。AIに図の構造を正確に伝えたい人はこちらもどうぞ。 テンプレートA: 右サイド注釈型 コピペして使えるHTMLテンプレートを2種類用意しました。 仕組みはシンプルで、plantuml-encoderというライブラリでPlantUML構文をエンコードしてplantuml.comに投げるだけです。Tailwind CDNとの共存も問題なし。テンプレートをコピペすればそのまま動きます。plantuml.comへの通信が発生するのでネット接続は必要ですが、大抵の開発環境では問題にならないです。 まずはテンプレートA。左にPlantUMLで描画したコンポーネント図、右にTailwind CSSで装飾した注釈パネルを並べるレイアウトです。ドラム型のDB記号やキュー記号が見えるのがPlantUMLならではのポイントですね。 向いてる場面 : 横に広がる図(コンポーネント図、シーケンス図)に設計ポイントを3-4個添えたいとき キャンバスサイズ : 1280x720px <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>コンポーネント図: 3層アーキテクチャ</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.jsdelivr.net/npm/plantuml-encoder@1.4.0/dist/plantuml-encoder.min.js"></script> <style> body { width: 1280px; height: 720px; margin: 0; padding: 0; background: white; overflow: hidden; } </style> </head> <body class="p-8"> <div class="h-full flex flex-col"> <!-- タイトル --> <h1 class="text-2xl font-bold mb-6 text-gray-800">コンポーネント図: 3層アーキテクチャ</h1> <!-- メインコンテンツ: 2カラム --> <div class="flex gap-6 flex-1"> <!-- 左: PlantUML図 --> <div class="flex-1 flex flex-col"> <div class="bg-blue-50 border-2 border-blue-300 rounded-lg p-4 flex-1 flex items-center justify-center"> <div id="diagram-container" class="flex items-center justify-center"> <p class="text-gray-500">Loading diagram...</p> </div> </div> </div> <!-- 右: 注釈パネル --> <div class="w-72 flex flex-col gap-4"> <div class="bg-yellow-50 border border-yellow-300 rounded-lg p-4"> <h3 class="font-bold text-yellow-800 mb-2">フロントエンド層</h3> <p class="text-sm text-yellow-900">Web・モバイルの2系統。APIゲートウェイを経由して統一的にアクセス</p> </div> <div class="bg-blue-50 border border-blue-300 rounded-lg p-4"> <h3 class="font-bold text-blue-800 mb-2">バックエンド層</h3> <p class="text-sm text-blue-900">認証・記事・通知をマイクロサービスに分離。ゲートウェイでルーティング</p> </div> <div class="bg-green-50 border border-green-300 rounded-lg p-4"> <h3 class="font-bold text-green-800 mb-2">データ層</h3> <p class="text-sm text-green-900">PostgreSQL + Redis + メッセージキューの3点セット。非同期処理はキュー経由</p> </div> </div> </div> </div> <script> window.addEventListener('DOMContentLoaded', function() { const umlSource = `@startuml skinparam style strictuml skinparam backgroundColor transparent package "フロントエンド" { [Webアプリ] as Web [モバイルアプリ] as Mobile } package "バックエンド" { [APIゲートウェイ] as GW [認証サービス] as Auth [記事サービス] as Article [通知サービス] as Notify } package "データ層" { database "PostgreSQL" as DB database "Redis" as Cache queue "メッセージキュー" as MQ } Web --> GW Mobile --> GW GW --> Auth GW --> Article Article --> DB Article --> Cache Article --> MQ MQ --> Notify Auth --> DB @enduml`; try { const encoded = plantumlEncoder.encode(umlSource); const imgUrl = `https://www.plantuml.com/plantuml/svg/${encoded}`; const container = document.getElementById('diagram-container'); container.innerHTML = `<img src="${imgUrl}" alt="コンポーネント図" class="max-w-full max-h-full" />`; } catch (error) { console.error('Error encoding PlantUML:', error); document.getElementById('diagram-container').innerHTML = `<p class="text-red-500">Failed to load diagram: ${error.message}</p>`; } }); </script> </body> </html> 差し替えは3箇所だけです。 PlantUML構文 ( const umlSource の中身)を自分の図に差し替える 注釈パネルの内容 (右側の3つのパネル)を自分の設計ポイントに差し替える タイトル を差し替える 注釈パネルは増減しても大丈夫です。3個が収まりいいですけど、2個でも4個でもレイアウトは崩れません。 skinparamについて Mermaid編では themeVariables で図の配色をTailwindのカラーパレットに合わせましたね。PlantUMLでは skinparam が同じ役割です。 skinparam style strictuml skinparam backgroundColor transparent backgroundColor transparent で背景を透明にするだけで、Tailwind側の bg-blue-50 と自然に馴染みます。追加で色をカスタマイズしたい場合はこんな設定もあります。 skinparam packageBackgroundColor #f0f9ff skinparam ArrowColor #3b82f6 skinparam ParticipantBackgroundColor #dbeafe Mermaidの themeVariables ほど細かい制御はできないですけど、背景透明にするだけで大抵は十分です。もっと細かく調整したい人は PlantUML公式のskinparamリファレンス を参照してください。 PlantUML固有の記法 テンプレートのコードで使ってる記法と、他の図で使える記法をまとめておきます。 テンプレートAで使用 : 記法 表示 database "名前" ドラム型DB記号 queue "名前" キュー型記号 package "名前" { ... } パッケージでグループ化 他の図で使える記法 : 記法 用途 == フェーズ名 == シーケンス図のフェーズ分割 alt / else / end 条件分岐ブロック ref over A, B 外部参照 left to right direction ユースケース図の横向きレイアウト テンプレートB: 左右均等型 テンプレートAだと、縦長の図のときに左側のスペースが余ります。アクティビティ図やユースケース図は縦に伸びるんで、横幅を半々にして右側に説明を置くほうが収まりがいいです。 向いてる場面 : 縦長の図(アクティビティ図、ユースケース図)に説明を横に並べたいとき キャンバスサイズ : 1280x720px <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>アクティビティ図: ユーザー登録フロー</title> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.jsdelivr.net/npm/plantuml-encoder@1.4.0/dist/plantuml-encoder.min.js"></script> <style> body { width: 1280px; height: 720px; margin: 0; padding: 0; background-color: white; overflow: hidden; } </style> </head> <body class="flex"> <!-- 左: PlantUML図 --> <div class="w-1/2 flex items-center justify-center p-8"> <div id="diagram-container"></div> </div> <!-- 右: 注釈パネル --> <div class="w-1/2 flex flex-col justify-center p-8 space-y-6"> <h1 class="text-3xl font-bold text-gray-800 mb-4">ユーザー登録フロー</h1> <div class="bg-yellow-100 border-l-4 border-yellow-500 p-4"> <p class="text-gray-800 font-semibold">バリデーション</p> <p class="text-sm text-gray-600 mt-1">フォーム入力後、サーバー側でバリデーション。失敗時はエラーメッセージを表示してフォームに戻す</p> </div> <div class="bg-blue-100 border-l-4 border-blue-500 p-4"> <p class="text-gray-800 font-semibold">DB保存とリトライ</p> <p class="text-sm text-gray-600 mt-1">保存失敗時はエラーログを記録してリトライ画面を表示。ユーザーに再試行の機会を与える</p> </div> <div class="bg-green-100 border-l-4 border-green-500 p-4"> <p class="text-gray-800 font-semibold">完了通知</p> <p class="text-sm text-gray-600 mt-1">保存成功時は完了メールを送信してから完了画面を表示。メール送信は非同期でもOK</p> </div> </div> <script> window.addEventListener('DOMContentLoaded', () => { const plantUmlSource = `@startuml start :ユーザーがフォームを入力; if (バリデーション?) then (成功) :データベースに保存; if (保存成功?) then (はい) :完了メールを送信; :完了画面を表示; else (いいえ) :エラーログを記録; :リトライ画面を表示; endif else (失敗) :エラーメッセージを表示; :フォームに戻る; endif stop @enduml`; const encoded = plantumlEncoder.encode(plantUmlSource); const img = document.createElement('img'); img.src = `https://www.plantuml.com/plantuml/svg/${encoded}`; img.alt = 'アクティビティ図: ユーザー登録フロー'; img.className = 'max-w-full max-h-full'; document.getElementById('diagram-container').appendChild(img); }); </script> </body> </html> 差し替えポイントはテンプレートAと同じ3箇所です。PlantUML構文、注釈パネル、タイトル。実例はアクティビティ図ですけど、ユースケース図を作りたい場合も const plantUmlSource の中身を差し替えるだけです。 テンプレートAとの違いは2つです。 レイアウトが左右均等 ( w-1/2 + w-1/2 )。図と注釈が50:50で並ぶんで、縦長の図に余裕ができます 注釈のスタイルが border-l-4 (左ボーダーアクセント)。テンプレートAのカード型とは雰囲気が変わります Mermaid編のテンプレートBは縦拡張(1280x1080px)でしたけど、PlantUML編は標準の1280x720pxです。PlantUMLはサーバー側で描画するんで、Mermaidの自動縮小問題がない。CSS transformも不要です。 テンプレート使い分け 条件 テンプレート 横に広がる図(コンポーネント図、シーケンス図) A: 右サイド注釈型 縦長の図(アクティビティ図、ユースケース図) B: 左右均等型 注釈が少ない(2-3個) A 注釈にテキストが多い B 迷ったらテンプレートAで試して、図が窮屈ならBに切り替えてください。 PNG変換 — 3つの手段 手段は3つあります。好みと環境に合わせて選んでください。 手段 自動化 セットアップ 向いてる用途 CLIツール(html-screenshot) できる Python + Playwright 量産やCI/CD Playwright MCP できる MCP設定 Claude Code連携 ブラウザで直接開く 手動 なし 手軽に確認 CLIツール uv run html-screenshot --file template-a.html --output template-a.png 以前の記事 で紹介したhtml-screenshotツールがそのまま使えます。Playwrightの wait_until="networkidle" がplantuml.comからのSVG取得完了を待ってくれるんで、PlantUML図の描画が終わってからスクリーンショットを撮ってくれます。 Playwright MCP Claude CodeからPlaywrightのブラウザ操作を直接呼び出す方法もあります。HTMLファイルを開いてスクリーンショットを撮る操作がMCPのツールで完結します。 Playwright MCPの記事 で詳しく書いてるんで、Claude Code使ってる人はこっちが楽です。 ブラウザで直接開く 一番手軽なのはHTMLファイルをブラウザで直接開くことですね。Tailwind CDNとplantuml-encoder CDNが読み込まれて、PlantUML図がそのまま描画されます。PNG変換は手動(DevToolsやOS標準のスクリーンショット)になりますけど、「ちょっと確認したい」くらいならこれで十分です。 まとめ Mermaid編のテンプレート2種 + 今回のPlantUML編テンプレート2種で、計4種類が揃いました。 テンプレート 図の描画 向いてる図 Mermaid A: 右サイド注釈型 Mermaid フロー、シーケンス、状態遷移 Mermaid B: 下部グリッド注釈型 Mermaid 複雑なシーケンス PlantUML A: 右サイド注釈型 PlantUML コンポーネント、シーケンス PlantUML B: 左右均等型 PlantUML アクティビティ、ユースケース フロー図、シーケンス図、状態遷移図に加えて、アクティビティ図、ユースケース図、コンポーネント図もカバーできるようになりました。特にコンポーネント図の database でドラム型DBアイコンが出せるのは、アーキテクチャ図を書く人にはかなり便利です。 おまけとして、Mermaid編でも触れましたがこのテンプレートで作った図はAI連携にも使えます。PlantUMLもMermaidと同じく宣言的記法なんで、AIが構造を正確に読み取れます。注釈パネルに設計意図を書いておけば、人間が見ても、AIが読んでもどっちにも伝わる。この辺の話は 仕様書の図にソースコードを添える設計パターン で詳しく書いてます。 もう1つ。このテンプレートを毎回コピペするのも手ですけど、Claude Codeの SKILL機能 にreference(参考例)として登録しておくと、「シーケンス図作って」と言うだけでテンプレートに沿った図が出てきます。テンプレートのクオリティがそのままSKILLのクオリティになるんで、良いテンプレートを貯める = 図解の品質を底上げする、という流れができます。コピペ用テンプレートとSKILL化、好きなほうで使ってください。 ほなまた〜 関連ブログ 今回の記事はシリーズの一部です。 Mermaid × Tailwind CSS — ハイブリッド図解の作り方 — 今回の前編。Mermaid + Tailwind CSSのテンプレート2種を紹介してます。まだ読んでない人はこちらから。 ClaudeでMermaid図作成を自動化!プロンプトテンプレート集も公開 — シリーズの出発点。Mermaid記法をAIで生成するところから始めたい人はここから。 図解作成、AIに丸投げしたら「たまに自分より上手い」件 — HTML+Tailwind CSSで図解を丸ごとAIに作らせる方法。フロー図以外の図解(比較図、アーキテクチャ図とか)はこっちが向いてます。 仕様書の図はAIに読ませるな — 軽量コードを添える設計パターン — 仕様書をAIと共有してるチーム向け。図にソースコードと設計意図を添えて、AIの「推測」をなくす方法です。 Claude CodeでPlantUML × VS Code Preview — PlantUMLの基礎とVS Codeでのプレビュー設定。PlantUML自体が初めての人はこちらが入門になります。 Playwright MCPで始めるブラウザ自動化 — PNG変換の手段の1つとして紹介したPlaywright MCP。Claude Codeからブラウザ操作を直接呼び出せます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post PlantUMLの表現力をTailwind CSSで設計書品質に仕上げる first appeared on SIOS Tech Lab .

動画

書籍