なぜなぜ分析ツールの技術スタック
なぜなぜ分析ツールの技術スタック
なぜなぜ分析ツール を公開した。従来のなぜなぜ分析は一本道になりがちで、複数の原因の並列管理や優先順位づけが難しい。このツールでは「原因をツリーで記録する」「因果チェーンを逆順にたどって検証する」の2点を軸に設計した。
機能概要
編集モード
- ツリー構造で原因を管理 — 1つの事象・原因に対して複数の「なぜ」を追加できる
- 重みづけ(高/中/低) — 原因の主因度を色で可視化(赤/黄/緑)し、どこを深掘りするか判断しやすくする
- 深掘りスキップ — 「これ以上掘らない」と判断した原因をマーク(根本原因として扱う)
- メモ欄 — 根拠データや補足情報を添付
因果検証モード
一本道に見えるなぜなぜ分析の論理的飛躍を検出するための機能。根本原因(葉ノード)から事象に向かって逆順にたどり、「〇〇だったから、△△となった。」という因果文を1ステップずつ確認する。各ステップで「成立する」「飛躍あり」をマークし、論理の穴を可視化する。
データ管理
データはブラウザの localStorage に保存。サーバー送信なしなので、障害情報など機微なデータを安全に扱える。
技術スタック
| 用途 | ライブラリ |
|---|---|
| UI フレームワーク | React 19 + TypeScript |
| ツリー描画 | @xyflow/react (React Flow v12) |
| 自動レイアウト | @dagrejs/dagre |
| スタイリング | Tailwind CSS v4 |
| ビルドツール | Vite |
| 永続化 | localStorage |
設計の要点
React Flow でインタラクティブなツリーを実現
ツリー描画には @xyflow/react を採用した。ノードとエッジをデータとして管理し、カスタムノードコンポーネント(WhyNode.tsx)で重みの色や操作ボタンを自由にレンダリングできる。
ただし React Flow はデフォルトで自動レイアウト機能を持たないため、ノードを追加するたびに座標を自分で計算して渡す必要がある。
dagre で自動レイアウト
@dagrejs/dagre で有向グラフの自動レイアウトを実装している(src/lib/layout.ts)。dagre はノードサイズとエッジ情報を受け取り、トップダウンの階層レイアウト座標を返す。ノードを追加するたびにこのレイアウト計算を走らせ、React Flow に座標を注入している。
事象
│
├── なぜ1(高)
│ └── なぜ1-1(中)
└── なぜ2(低)
└── なぜ2-1(スキップ)
手動配置なしでツリーが綺麗に整列するのはこの仕組みによる。
ルーティングは App.tsx で完結
外部ルーターを使わず App.tsx で「ホーム画面 ↔ エディタ画面」を単純な state で切り替えている。分析数が増えても SPA として動くことが前提で、URL をブックマークする用途を想定していないためこれで十分と判断した。
localStorage による永続化
src/lib/storage.ts が localStorage の CRUD を担当する。サーバーなしで完結する設計にした理由は「障害情報を外部送信したくない」という要件から。GitHub Pages への静的デプロイとも相性がよく、インフラコストゼロで運用できる。
ディレクトリ構成
src/
├── types.ts # 型定義
├── App.tsx # ルーティング(ホーム ↔ エディタ)
├── lib/
│ ├── storage.ts # localStorage CRUD
│ ├── layout.ts # dagre 自動レイアウト
│ └── treeUtils.ts # ツリー操作ユーティリティ
└── components/
├── HomeScreen.tsx # 分析一覧・新規作成
├── AnalysisEditor.tsx # メインエディタ(編集/検証モード)
├── WhyNode.tsx # React Flow カスタムノード
├── NodeModal.tsx # ノード追加・編集モーダル
└── VerificationPanel.tsx # 因果検証パネル # なぜなぜ分析ツールの技術スタック
[なぜなぜ分析ツール](https://h-kono-it.github.io/naze-naze/) を公開した。従来のなぜなぜ分析は一本道になりがちで、複数の原因の並列管理や優先順位づけが難しい。このツールでは「原因をツリーで記録する」「因果チェーンを逆順にたどって検証する」の2点を軸に設計した。
<figure>
<img src="/memos/naze-naze_image.png" alt="なぜなぜ分析ツールのサンプル画像 NullPointerException発生の分析をしている">
<figcaption>なぜなぜ分析ツールのサンプル画像 NullPointerException発生の分析をしている</figcaption>
</figure>
## 機能概要
### 編集モード
- **ツリー構造で原因を管理** — 1つの事象・原因に対して複数の「なぜ」を追加できる
- **重みづけ(高/中/低)** — 原因の主因度を色で可視化(赤/黄/緑)し、どこを深掘りするか判断しやすくする
- **深掘りスキップ** — 「これ以上掘らない」と判断した原因をマーク(根本原因として扱う)
- **メモ欄** — 根拠データや補足情報を添付
### 因果検証モード
一本道に見えるなぜなぜ分析の論理的飛躍を検出するための機能。根本原因(葉ノード)から事象に向かって逆順にたどり、「**〇〇だったから、△△となった。**」という因果文を1ステップずつ確認する。各ステップで「成立する」「飛躍あり」をマークし、論理の穴を可視化する。
### データ管理
データはブラウザの localStorage に保存。サーバー送信なしなので、障害情報など機微なデータを安全に扱える。
## 技術スタック
| 用途 | ライブラリ |
|---|---|
| UI フレームワーク | React 19 + TypeScript |
| ツリー描画 | @xyflow/react (React Flow v12) |
| 自動レイアウト | @dagrejs/dagre |
| スタイリング | Tailwind CSS v4 |
| ビルドツール | Vite |
| 永続化 | localStorage |
## 設計の要点
### React Flow でインタラクティブなツリーを実現
ツリー描画には [@xyflow/react](https://reactflow.dev/) を採用した。ノードとエッジをデータとして管理し、カスタムノードコンポーネント(`WhyNode.tsx`)で重みの色や操作ボタンを自由にレンダリングできる。
ただし React Flow はデフォルトで自動レイアウト機能を持たないため、ノードを追加するたびに座標を自分で計算して渡す必要がある。
### dagre で自動レイアウト
`@dagrejs/dagre` で有向グラフの自動レイアウトを実装している(`src/lib/layout.ts`)。dagre はノードサイズとエッジ情報を受け取り、トップダウンの階層レイアウト座標を返す。ノードを追加するたびにこのレイアウト計算を走らせ、React Flow に座標を注入している。
```
事象
│
├── なぜ1(高)
│ └── なぜ1-1(中)
└── なぜ2(低)
└── なぜ2-1(スキップ)
```
手動配置なしでツリーが綺麗に整列するのはこの仕組みによる。
### ルーティングは App.tsx で完結
外部ルーターを使わず `App.tsx` で「ホーム画面 ↔ エディタ画面」を単純な state で切り替えている。分析数が増えても SPA として動くことが前提で、URL をブックマークする用途を想定していないためこれで十分と判断した。
### localStorage による永続化
`src/lib/storage.ts` が localStorage の CRUD を担当する。サーバーなしで完結する設計にした理由は「障害情報を外部送信したくない」という要件から。GitHub Pages への静的デプロイとも相性がよく、インフラコストゼロで運用できる。
## ディレクトリ構成
```
src/
├── types.ts # 型定義
├── App.tsx # ルーティング(ホーム ↔ エディタ)
├── lib/
│ ├── storage.ts # localStorage CRUD
│ ├── layout.ts # dagre 自動レイアウト
│ └── treeUtils.ts # ツリー操作ユーティリティ
└── components/
├── HomeScreen.tsx # 分析一覧・新規作成
├── AnalysisEditor.tsx # メインエディタ(編集/検証モード)
├── WhyNode.tsx # React Flow カスタムノード
├── NodeModal.tsx # ノード追加・編集モーダル
└── VerificationPanel.tsx # 因果検証パネル
```