GitHub Copilot Agent の力を借りて Next.js から React Router に移行しました

ANDPAD フロントエンドエンジニアの小泉です。

普段は Vue での開発をメインにしているのですが、並行して React のプロジェクトも担当しています。

今回は、「ANDPAD 資料承認」というプロダクトのサービスページを Next.js から React Router に移行した際の、 GitHub Copilot の活用法について紹介します。

特に、「コーディングエージェントが凄いのはわかったけど、実際のプロダクト開発にどう取り入れて良いかわからない」という悩みを持っている方の参考になれば幸いです。

なお、この記事は、ある程度 Copilot や コーディングエージェントを使ったことのある方に向けた内容となっています。そもそもの Copilot の導入・設定方法、基本的な使い方・事例について知りたい方は、以下の記事を先に読んでいただくのがオススメです!

tech.andpad.co.jp

また、プロンプト例を一部紹介していますが、「この記事を読めば Next.js から React Router に移行できる」という手順書ではないので、その点もご了承ください。

Next.js から React Router に移行する理由

本題の前に、まずはこの意思決定を行った理由を説明します。

今回、あえてフレームワークを移行する理由として大きかったのは、自分のチーム内で利用する技術スタックを統一したいという点でした。

現在自分が関わっているチームで管理しているフロントエンドのリポジトリは他に 3 つあり、そのうち 2 つが Nuxt 3、そしてもう 1 つが React Router を採用しています。

フレームワークとして React Router を使っているのは昨年新たに立ち上がったプロダクトで、技術的制約から React を採用する必要があり、かつリリースまでのスピード感を求められたことから、Remix SPA を初めて採用しました(現在は React Router 7 にアップデート済み)。

この時の開発体験が単純に良かっただけでなく、基盤が Vite なので環境変数やプラグイン・ビルド周りの設定方法などに Nuxt で得た知見を活かしやすいというのが、普段 Nuxt での開発をメインにしている身として非常に大きなメリットだと感じました。

一方、今回の資料承認プロダクトは、Next.js の中でもかなり古いバージョンのままで、最新に追従できていないことが数年前から運用上の課題となっていました。SPA なので App Router や RSC などといった Next.js の機能・メリットを活用する予定もない中で、「現時点での最新バージョンにアップデートできたとしても、今後も Next.js の最新仕様に追従していくのか」という問題がありました。

特に 2025 年現在、フロントエンドのビルドツール・バンドラ周りはかなりの過渡期で、Rolldown、Turbopack、Rspack といった様々な Rust 製ツールのリリースが予定されています。これを React Router に移行すれば、ビルドツールが全て Vite で統一され、「Rollup / esbuild から Rolldown への移行」という共通のテーマを考えれば良くなります。

Next.js の最新バージョンへのアップデートは、この 1 回に限れば React Router へのマイグレーションよりも容易ですが、それは今後自分のチームで「Nuxt・Next・React Router それぞれの最新トレンドをキャッチアップしながら運用を続けていく」という意思決定でもあります。

実際にアップデートが滞ってしまっていた状況を鑑みても、Next.js から React Router に移行することでチームとしての運用負荷を下げるのは、十分な価値があると判断しました。

ちなみに、この「技術スタックの統一」が最大のモチベーションであったため、TanStack Router のような新しいライブラリの採用はキリがないと考えて見送りました(React Router 採用済みのプロダクトがなければ検討していたかもしれません)。逆に、Next.js から Nuxt への移行は、得られるメリットに対してコストが大きすぎるので検討しませんでした。

Copilot Agent で useRouter を React Router に置き換える

今回の移行作業のもう 1 つのテーマとして、記事タイトルにも入っている通り、GitHub Copilot Agent をなるべく積極的に活用し、作業の効率化を図りました。

ただし、全ての作業を Copilot Agent に行わせたわけではなく、 Copilot Agent が力を発揮しやすい一部のタスクのみ依頼しました。

ここからは、「next/linknext/router から import されている useRouter 関数を、 useLocationuseParams といった React Router 版の API に置き換える」というタスクを例に挙げて、Copilot Agent を活用してのタスク遂行例を紹介します。

1. 詳細な指示書をチケットにする

まず、GitHub の issue を作り、どのように修正してほしいかの指示を、かなり具体的かつ細かく書きました。

最初は雑に「useRouter を使っている箇所を React Router に書き換えてください」というような指示を出したのですが、期待したような動きには全くならず、最終的には、どんなパターンがあって、どのように修正すれば良いかを全て手作業で検証して書き出しました。

例えば、 これまで router.push を使っていたページ遷移に関する指示は、以下のようなものです。

Next.js から React Router に移行するため、以下のような変更を行います。

修正は src 以下の全てのファイルに対して適用してください。

また、修正の際、全ての変更を一気に行わず、 ## または ### の見出しごとに分けて修正を行ってください。

## 1. useRouter について

useLocation, useNavigate, useSearchParams に分けて書き換える必要があります。それぞれ、必要な場合は react-router から import してください。

### 1-1. router.push

router.push は以下のように useNavigate を使って書き換えてください。

```
// const router = useRouter();
// router.push("/")

const navigate = useNavigate();
navigate("/")
```

### 1-2. router.replace

router.replace は以下のように useNavigate を使って書き換えてください。

```
// const router = useRouter();
// router.replace("/")

const navigate = useNavigate();
navigate("/", { replace: true })
```

このように、指示内容と、修正前後のコード例をセットでチケットに記載しました。

ちなみにこの時、修正指示を番号で区切ることで、作業を分割しやすくなります。コンテキストが独立していたらチケット自体を分けてしまうのも手だと思います。

2. チケットの情報を Agent に取得させる

チケットへの記載がある程度終わったら、 VSCode の Copilot Agent Mode での実際の作業に入っていきます。

まずはチケットの URL を渡して内容を取得させます。この時、今年 4 月にリリースされた GitHub MCP Server を利用することで、プライベートなリポジトリのチケットにアクセスできるようになります。

たまに Playwright MCP などを使ってブラウザ経由で fetch しようとしてしまうこともありますが、キャンセルして再度指示を出すといつかは GitHub API を使ってくれます。

そしてこの時、いきなり作業に入るのではなく、まず「チケットの内容を説明してください」という指示を出します。

こうすることで、チケットの内容が正しく Agent に伝わっているかを事前にチェックできます。説明した内容に不足があればチケットを加筆修正して、再度チケットを取得させます。

3. 修正作業を開始する

要約されたチケットの内容に問題がなさそうであれば、修正を開始するように伝えます。チケットの各セクションに番号を振っていることと、その内容をあらかじめ説明させていることから、番号を指定することで特定の指示だけを実行させたり、途中までコミットした上で作業を再開することもできます。

この指示の結果、以下のようにコードが修正されました。

内容に問題がなければコミットを行います。一連の会話が長くなると、チャットの内容を勝手に要約してしまい、エージェントの応答精度が下がったり、最初の指示を忘れて英語で喋りだしたりする傾向があるので、なるべく 1 つの作業が上手くいった時点でコミットして会話を終える方が良いです。

問題があればチャットで追加の指示を出したり、チケットの記載を修正して、場合によってはここまでの作業を一度リセットして最初から作業をやり直させます。

Copilot Agent を使ってみて良かったポイント

機械的に検出しきれない差分に対応してくれる

Copilot Agent を用いることで、機械的に直しきれない細かい差分を吸収した上で多数のファイルを一括修正してくれるというのは大きなメリットでした。

これまで、こうしたアップデートやライブラリ移行などの作業をする場合、正規表現や eslint などを使った一括置換で対応しようとすることが多かったのですが、今回の移行作業の場合、移行の内容がかなり複雑であり、lint の範囲では移行できないものが多くありました。

特に、 useRouter と React Router API が 1 対 1 で綺麗に対応しておらず、 ファイル全体を確認してどのプロパティが参照されているかを確認しないと useRouter の置換先が特定できません。

その点、 Copilot であれば、コード例と文章で仕様を説明することで、かなり柔軟に書き換え作業を行ってくれます。これによって、本来であれば手作業で書き換えるしかなさそうな部分を自動化できたので、作業工数をかなり削減できました。

チケットに全ての指示がまとまっているので後からレビューしやすい

全ての作業の内容がチケットに記載されているため、レビュー依頼時にもそのチケットを見てもらうことで「何をしたかったか」が明確になっているのが、今回の手法の最大のメリットでした。

これまで自分が担当したライブラリのアップデートやマイグレーションといったケースでは、「エラーが出たところを逐一直していく」みたいな細かい作業の繰り返しになるため、どうしてもコミットの単位が大雑把になってしまいがちでした。

その点、今回の方法では「AI でも理解できる粒度で説明する」というステップを絶対に省略できません。作業内容が確実に言語化されるという強制力が働くのが良かったです。

ベースモデルでも問題なく作業を遂行できる

これは直接的な Copilot Agent のメリットではありませんが、今回の手法であれば最新のモデルを使わなくても良いのが嬉しい部分でした。

この作業を行った 5 月時点で、GitHub Copilot のプレミアムリクエストの回数制限の導入が予告されていたため、現時点でのベースモデルである GPT-4.1 を優先的に利用してみたのですが、今回のユースケースでは GPT-4.1 でも全く問題なく作業を完遂してくれました。

これまでいくつかのテーマで Agent を利用してみた所感として、創造的な領域、ゼロからコードを書くような指示を与えた場合の精度はモデルによって明確な差があり、Claude Sonnet 4 や 3.7 と比べて GPT-4.1 を使うとアウトプットの品質が下がったり必要なやり取りの回数が増えたりする印象を受けました。

一方、今回の記事のようにかなり細かい指示を与えた上で、機械的に進められる作業を依頼した場合、モデルの性能による差がほとんど現れません。この点で、今後プレミアムリクエストの制限がかかったとしても、今回の手法では Agent を制限なく使い続けられそうだという安心感を得られました。

また、「モデルの性能に左右されない」ということは「アウトプットの品質が人間の指示精度のみに依存する」ということでもあります。少し言い方を変えたら良くなる、モデルを変えたら上手くいく、数週間待ったらできるようになる、といった AI のブラックボックス度と向き合わずに作業を進められるのは大きな利点だと思います。

Copilot Agent を使う上での課題

作業が劇的に速くなるわけではない

今回のようにチケットでの作業指示を細かく行うためには、事前に自分で挙動を検証し、何なら 1 ファイル分は自分で修正して問題ないことを確認してからその修正を破棄して改めて Copilot に作業させる、という流れになるので、時間はかかります。

もちろん、ファイル数が多くなれば効率は上がるのでリポジトリの規模にもよりますが、今回の修正に限って言えば、完全に自分で修正するのとトータルでそこまで変わらなかったのではないか、という感覚もあります。

ただし、前述した通り「チケットに指示内容がまとめられる」というドキュメント化が作業時間に含まれているので、「本来は人間がやる場合もこのくらい修正が文書化されているべき」と考えれば実質的な作業時間は短縮しているといえるでしょう。

また、人間がこのような作業を大量に行うと、精神的にも疲れてしまいますし、どうしても見落としや typo といったヒューマンエラーが発生するリスクがあるので、広い意味での生産性は向上したと感じます。

何よりも、「Copilot を使ったタスク遂行の経験を積む」という意味で、長期的に AI に指示するためのトライアンドエラーが減れば複利的に作業が効率化できるでしょうから、短期的な生産性が上がりきらないのは仕方ないと割り切っています。

人間の手を完全に離せるわけではない

今回のような進め方だと、最終的なコミットや PR 作成のために、アウトプットを人間が把握してチェックする必要がありました。

チケットの指示を厳密に言語化したとはいえ、あくまで自然言語での指示なので、完全な再現性があるわけではありません。 Copilot のコンテキスト上限の問題もあってか、変更行数が多すぎると変更が途中で止まってしまったり、意図しない変更が発生したりすることもあり、その都度チャットで「変更漏れがないかもう一度確認してください」「このフォルダも修正してください」というような指示を追加で出していました。

このように細かく人間が介入することで Copilot の不安定さを吸収できたのは良かった点ですが、結果として「Copilot Agent に作業を任せて自分は別のタスクを進める」という形での生産性の飛躍的な向上にはあまり繋がりませんでした。

現段階で Agent に既存のコードを大幅に書き換える作業を依頼する場合には、まだ人間の介入が不可欠ではないかと思っていますが、コミットや PR 作成の権限を与えて PR を作らせるところまで Copilot に任せてみるというアプローチをもう少し試してみても良かったのかもしれない、というのはやや反省点です。

また、最近では「AI にコード生成ツールを作らせる」という形で間接的に AI を使って再現性を担保する事例もいくつか見かけるようになったので、次回このような作業に取り組む場合は、 ts-morphunjs/magicast を使う方法も試してみたいです。

まとめ

急激に普及してきた AI Agent を用いての開発ですが、現時点ではまだエージェントの適している作業とそうではない作業がある、という印象を持っています。

今回の記事では触れていませんが、例えば vite.config.tsapp.tsx といった設定ファイルの置き換えは、一度しか行わないのに AI で定型化するメリットが薄かったため完全に手作業で行いましたし、ユニットテストの置き換えなども、一部は Agent に実行させたもののあまり上手くいかず自分で調整した部分が多くありました。

仮に今回の作業を、「絶対に自分でコードを書かない」と決めて AI に実行させていたら全く終わらなかったか、何倍もの時間がかかっただろうと思っています。

ただし、 AI に全てのコードを書かせることを目標にせず、あくまで 1 つの手段として活用する分には十分に力を発揮してくれます。現時点で、特に既存のコードベース上でプロダクトを開発する場合には、最も取り入れやすいアプローチなのではないでしょうか。

また、今後 AI がさらに賢く進化していくにつれて、AI に任せられる領域はさらに増えていくでしょうし、その上で「どのように作業内容を言語化・細分化すれば AI に渡しやすいのか」という経験を今から積んでおくことに価値があると感じました。

この記事が Copilot Agent をどう実務に活かしたら良いか悩んでいる方の参考になれば幸いです。

終わりに

アンドパッドでは、「幸せを築く人を、幸せに。」というミッションの実現のため、一緒に働く仲間を大募集しています。

開発部内での AI 活用への関心も高く、エージェントを使った開発に関する勉強会も定期的に開催されています。現在は全メンバーが GitHub Copilot Business を利用できるようになっており、他のツールについても検討が進んでいます。

会社や事業、開発チームにご興味を持たれた方は、ぜひお気軽にカジュアル面談や選考に応募いただけると嬉しいです!

engineer.andpad.co.jp

hrmos.co

hrmos.co