Figma makeで作ったWebアプリをKiroでリファクタリングした
POSSEでエンジニアインターンをしている吉川唯音です。本記事では、Kiroでリファクタリングしてみて気づいたことについて書いていきたいと思います。
▶︎実際にリファクタリング後にデプロイしたアプリケーション
https://no-vel.link/

はじめに
Figma makeを使えば、デザインからコードまで一気通貫でWebアプリケーションを作成できます。私もこの便利さに惹かれて、プロトタイプをサクッと作ってみました。
しかし、気づいた時には「保守不能」なコードベースが出来上がっていました。
- すべての画面がステートで管理され、URLはすべて同じ
- UIとロジックが混在
if文のネストで画面を切り替える実装- 使われていない大量のファイル
any型だらけ、DOM直接操作

CursorやClaude Codeでリファクタリングを試みましたが、部分的な修正しかしてくれず、またエラーが出ても問題と判定されず、理想の状態には到達できませんでした。
そこで出会ったのがKiroのスペック駆動開発モードです
CursorとClaude Code
最初のアプローチで直面した問題:
- 全体像を把握してくれない - 部分的な修正のみで、関連ファイルへの影響を考慮しない
- エラーを問題と判定しない - TypeScriptエラーがあっても「完了です」と返す
- 理想状態に到達しない - 部分最適の積み重ねで、結局ぐちゃぐちゃに
- 作業単位が不明瞭 - 今何をしているのか、次に何をすべきかが見えない
時間をかけても動かないコードが量産されるだけでした。
Kiroのスペック駆動開発モード
Kiroの特徴は、既存のコードベースに対して
- 要件(Requirements) を明確化
- 設計(Design) を文書化
- タスク(Task) を自動生成
という流れで進められます。

特にリファクタリングに向いている理由:
- 既存コードの構造を理解した上で要件を整理できる
- 段階的な変更を計画的に進められる
- タスク単位で進捗を確認できる
実践:要件定義から実装まで
リファクタリングの計画
Phase 1として、URLベースのルーティングへの移行を設定しました。MainApp内部のルーティングなど、その他の課題も段階的に対応する計画です。
Kiroとの対話で要件を整理
現状のコードベースを見せ、対話しながら要件を整理:
現在のApp.tsxでは、useStateによる状態ベースのルーティングを行っており、
12種類のAppStateをif文で切り替えている。
この実装をReact Router v7に移行し、URLベースのナビゲーションを実現する。
デザインや既存の動作は一切変更せず、内部構造のみをリファクタリングする。
Kiroはコードベースを分析し、kiro/spec/requirements.mdを生成してくれました。

重要だったのは、私が理想とする状態を明確に伝えることです。
設計とタスクの自動生成
要件が固まると、Kiroは設計書とタスクリストを自動生成します。

Kiroは各タスクを順番に実行し、タスクごとに確認を求めてくれます。承認のタイミングは自分で決められ、フェーズごとにbuildチェックも可能です。
メリット:
- 今何をしているかが明確
- いちいち細かい指示を出す必要がない
- テストコードまで自動生成してくれる


リファクタリング結果
Before:
function App() {
const [appState, setAppState] = useState<AppState>('landing');
if (appState === 'landing') {
return <LandingPage
onGetStarted={() => setAppState('auth')}
// ...大量のコールバック
/>;
}
// 以下、12種類のif文が続く...
}
After:
function App() {
return (
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/auth" element={<AuthPage />} />
<Route path="/pricing" element={<PricingPage />} />
<Route path="/app/*" element={<MainApp />} />
{/* ... */}
</Routes>
);
}
if文の嵐から解放され、宣言的なルーティングになりました。
自分で理想を考えて、ハンドルする重要性
Kiroは強力ですが、すべてを任せきりにすると上手くいかないこともわかりました。
私が自分で判断したこと
1. ディレクトリ構造の理想形
2. 使用するライブラリの選定
3. リファクタリングのフェーズ分け
4. Kiroが出したコードのレビュー
GitHubリポジトリを参考にする
Kiroの便利な機能として、GitHubのリポジトリを参照できる点があります。
以前作った綺麗な構造のプロジェクトをKiroに見せると、そのベストプラクティスを踏襲してくれました。過去の良い設計を再利用でき、プロジェクト間の一貫性も保てます。
リファクタリングした主要な箇所
Phase 1とその他のタスクで改善できた箇所:
1. ルーティング改善
Before:
function MainApp() {
const [currentView, setCurrentView] = useState<'dashboard' | 'settings'>('dashboard');
if (currentView === 'dashboard') return <Dashboard />;
if (currentView === 'settings') return <Settings onBack={() => setCurrentView('dashboard')} />;
}
After:
function MainApp() {
return (
<Routes>
<Route path="dashboard" element={<Dashboard />} />
<Route path="settings" element={<Settings />} />
</Routes>
);
}
2. DOM直接操作の排除
Before: window.location.pathname = "/dashboard";
After: navigate('/app');
3. その他の改善
any型の削除と型安全性の確保- if文のネスト削減
- react-hook-formへの統一
- コンポーネントの再利用性向上
- UIとロジックの分離
- SWRを使用してステート管理を改善
自動サマライズ機能
Kiro(Cursorなどもですが)はコンテキストが上限に達する前に自動的にサマライズしてくれます。

これにより、作業が途切れることなく継続できました。
完了:動作確認と学び
すべてのタスクが完了し、ビルドも成功しました。
実際にブラウザで確認すると、一部importの忘れなどがありましたが、CursorやClaude Codeでは到達できなかったゴールに、同じ労力で到達できたことに驚きました。
反省点として、テストを早い段階で作成すれば良かったと思います。Kiroはテストコードも生成してくれるので、最初から書いてもらえば細かいミスは防げたでしょう。
要件や事前情報を伝えることの重要性
Kiroを使って最も学んだのは、事前に伝える情報の質が、成果物の質を決めるということです。
- 理想のディレクトリ構造
- 使用するライブラリとバージョン
- ベストプラクティスの参照先
- リファクタリングの優先順位
これらを明確に伝えることで、Kiroは期待以上の仕事をしてくれました。
将来の展望
Figma makeのガードレール作成
今回のリファクタリングで、AIがどのように判断してコードを記述するかが見えました。これを応用して、Figma makeで最初から綺麗に書いてもらうガードレールを作成できそうです。
自動化と学習のバランス
Kiroと一緒にリファクタリングするからこそ、コードへの理解が深まります。タスク単位で確認しながら進めることで、自然と学習できます。完全自動化よりも、人間とAIの協働が最も効率的だと感じました。
まとめ
Kiroの強み
- ちゃんと動くものを提供してくれる
- やりきってくれる - タスク単位で計画的に進め、最後まで完遂
- スペック駆動で安心 - 要件・設計・タスクが明確
- テストも自動生成
- コンテキストを自動サマライズ
Kiroのスペック駆動リファクタリングは、保守性の高いコードベースを維持する強力な味方になってくれそうです。