LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

AIで進める技術的負債の返済 ― 「いつかやる」を「今できる」に ―

こんにちは。Yahoo!フリマでバックエンド開発を担当している高木です。

ソフトウェア開発において避けられない「技術的負債」。
「いつかやる」と後回しにしているうちに積み重なり、気づいたら大きな負担になっていた……という経験はありませんか?

本記事では、私たちのチームがAIを活用して技術的負債を安全かつ効率的に返済した取り組みを紹介します。
「対象の選び方」「承認と設計の流れ」「品質を担保する工夫」を具体例とともに解説していきます。

技術的負債が溜まりやすい理由

技術的負債はどんなシステムにも存在しますが、特に溜まりやすい構造を持つコンポーネントがあります。
Yahoo!フリマでは、その代表例が BFF(Backend For Frontend) です。

Yahoo!フリマは、個人間で取引できるフリマアプリです。
最近では、グッズ交換機能をはじめ、「らくらくAI出品」や「ゴールド出品者プログラム」など、ユーザー体験を高める施策を次々に展開しています。

これらの機能をユーザーに安全に届ける裏側で動いているのがBFFです。
バックエンドの前段に位置し、モバイルアプリからのリクエストを受け、必要なデータを集約して返却する役割を担っています。
BFFの採用メリットについては 過去の記事でも詳しく紹介されています。
以下に、アーキテクチャの大まかな概要図を示します。

architecture

Yahoo!フリマではBFFを採用することで、スピード感を持って新機能を提供できる仕組みを作り出しており、ビジネスにも大きく貢献しています。
一方で、この構造が技術的負債を生み出してしまう要因にもなっています。

モバイルアプリ × バックエンドの非同期性

モバイルアプリはユーザーが任意のタイミングで更新するため、新しいバージョンをリリースしても、すぐに全ユーザーが移行するわけではありません。
そのため、新バージョンが浸透するまでの間は旧バージョンをサポートし続ける必要があります。

例えば、新機能に関するデータを返すケースを考えてみましょう。

  • 新バージョンのアプリ
    新機能に対応しているため、バックエンドのレスポンスをそのまま利用できます。

  • 旧バージョンのアプリ
    新機能に対応していないため、バックエンドから返されたデータをそのまま使うと正しく動作しない場合があります。
    この場合、BFFがレスポンスを加工し、旧バージョンでも扱えるようにします。

コード例

次に、簡略化したコード例を示します。
このように、アプリのバージョンごとに挙動を切り替える分岐ロジックがBFFに追加されていきます。

type BackendResponse = {
    id: string;
    title: string;
    featureA?: object; // 新機能に関するデータ
};

const MIN_FEATURE_A = 18;

export function adapt(res: BackendResponse, appVersion: number) {
    if (appVersion < MIN_FEATURE_A) {
        const copy = { ...res };
        delete copy.featureA; // 旧アプリは意図しない挙動となる可能性があるため、返却しない
        return copy;
    }

    // 新アプリでは必須のため返却する
    if (!res.featureA) throw new Error('Invalid response: featureA is required');

    return res;
}

使われなくなった分岐はそのまま残る

新しいバージョンが十分に浸透すると、旧バージョンの利用者はいなくなり、対応する分岐処理はもう実行されなくなります。
この時点で分岐ロジックは不要になるはずですが、現実には残り続けてしまう場合がよくあります。

結果として、「実行されないのに削除されないコード」が積み重なり、BFFは技術的負債を抱えやすい構造になってしまいます。
これが蓄積し、放置され続けると、将来的な新機能の追加や改善スピードに影響を与えるリスクがあります。

なぜ削除が後回しになるのか?

不要なコードを消すこと自体は難しくありません。
しかし、以下のような理由から後回しになりがちです。

  • ユーザー価値につながりにくい:削除しても新機能が増えるわけではなく、目に見える改善にはならない。
  • 短期的には問題がない:不要コードが残っていても直ちに障害が起こるわけではない。
  • 他タスクに埋もれやすい:緊急性が低いため、新機能開発や不具合対応に優先順位を奪われやすい。

こうした事情から、削除が後回しになり、気づけば負債が積み重なっていくのです。

AIを活用した負債返済の実践

取り組みのきっかけ

不要になった分岐コードは消した方がよいと誰もが分かっていても、実際には後回しにされがちです。
私自身も日常業務の中で何度もそうしたコードを目にしては、「いつか時間ができたら……」と思いながら手をつけられずにいました。

そんな中、「これってAIに任せられるのでは?」と考えたのが今回の取り組みのきっかけです。

ターゲットは明確で、やることもシンプルです。

  • コード上の不要な分岐を削除する
  • それに伴って不要になるコードや単体テストを削除・修正する

範囲が限られており、内容がブレにくいため、AIが取り組むには適した題材だと感じました。

また、同じ時期に全社的にもAIコーディングエージェント(Claude CodeやRooCodeなど、コード修正を対話的に任せられるツール)の活用が推進されていました。
一方で、自分がリーダーを務めるチームでは十分に活用できていなかったため、安全にAIを実務へ導入できるユースケースとしても意義があると考えました。

進め方

取り組みは以下の流れで進めました。

  1. チケット化
    AIに任せられる分岐をAPI単位でタスク化し、対象を明確にする。

  2. 設計
    いきなり実装させず、まずAIに「削除計画」を考えさせる。
    AIが出力した内容を確認し、問題がなければその設計をもとに実装を進めてもらう。

  3. 実装とレビュー
    AIにコード修正を行わせ、人間がプルリクエスト(PR)の内容を確認。必要に応じて動作確認を追加。

  4. リリース
    問題がなければリリースし、不要な分岐を安全に削除する。

AIに任せるための工夫

AIにコード修正を任せるといっても、完全に丸投げできるわけではありません。
安全かつ効率的に進めるために、いくつか工夫を取り入れました。

  • 権限の設定
    AIにはファイルの読み取り権限を自由に与える一方で、書き込みは必ず人間の承認を通すようにしました。
    これにより、誤った修正が直接反映されるリスクを避けられます。

  • 設計のレビュー
    AIへの指示は自然言語で行うため、意図がどの程度伝わっているか把握しづらい面があります。
    そこで、いきなり実装させるのではなく、まず対応計画を出力させ、その内容を自分がレビューしてから実装へ進ませました。
    こうすることで方向性のズレを早期に修正でき、余計な手戻りを防げました。

  • テストの準備
    設計段階からAIに単体テストの調査も依頼し、特にバージョン制御に関する境界値テストの有無を確認しました。
    網羅が不十分な部分は事前に洗い出し、AIの実装と並行して手動確認用のデータや環境を整備しました。

これらの工夫により、私は他のタスクを進めながらも、AIに負債返済を並行して進めてもらうことができました。

特に効果的だったのは、事前に設計させる手法です。
修正が必要な箇所の調査から任せることで、AIがタスクの目的やコードをどこまで理解しているかを測ることができました。

さらに、自分が多忙なときは、AIに「設計貯蓄」として対応計画を複数作らせ、テキストファイルに出力させておきました。
計画の作成は読み取りベースの作業であり、承認を必要としないため、先行してストックしておけます。
一方で、実装は書き込み権限を伴うため都度承認が必要になります。
そのため、自分がフォローできるタイミングに合わせて実装を進められる点が大きな利点でした。

結果として、自分自身の生産性を落とすことなく、負債返済を継続できる体制を築けました。
最終的には3週間で6個のPRを作成し、不要分岐を複数削除できました。

実際の様子

ここからは、AIにタスクを進めてもらった様子を紹介します。
題材は、先ほどの簡略化したコード例から「不要になった分岐を削除する」というタスクです。

今回の作業環境はVSCodeで、拡張機能として RooCode を導入しました。
RooCodeはGUIベースのAIコーディングエージェントで、チャット形式でのやり取りや、承認・拒否といった操作をボタン一つで行えます。
環境構築の手軽さと直感的な操作が大きな魅力です。

作業時には Architect モードと Code モードを切り替えて利用しました。
Architect モードではコードが書き換わらないため、設計段階で誤変更のリスクを避けられます。

roo-image1

最初は、タスク依頼の場面です。
「techblog-sample.controller.tsの旧アプリ向け分岐が不要になったから削除したい。まずは対応計画を作って。」といった自然言語の指示で十分に伝わります。
ファイルが大きい場合やコードが複雑な場合は、行番号や変数名を補足すると、より精度の高い計画が返ってきます。

roo-image2

次にAIの出力結果です。
直接コードを書き換えるのではなく、調査内容を整理したうえで、TODOリスト形式の対応計画を提案してくれました。
小さなタスクであれば、このように調査して計画まで提示してくれるのが強みです。

roo-image3

計画を確認し、問題なければコードの修正をAIに任せます。

roo-image4

こちらの意図を汲み取り、コード修正だけでなくコメント更新まで行ってくれました。

roo-image5

以上が、実際にAIにタスクを進めてもらった様子です。
今回は1ファイルで完結する例を紹介しましたが、プロダクトの開発では複数ファイルにまたがる修正が多いものです。
AIコーディングエージェントはディレクトリ全体を横断的に調査・実装できるため、そうしたケースでこそ真価を発揮します。

得られた成果

この取り組みで得られた成果は大きく2つあります。

  1. AI活用の経験値を積めた
    実務フローの中でAIに安全に実装を任せる方法を具体的に検証できました。
    まだAI活用の事例が少ない中では、AI導入の現実的なノウハウを得られたこと自体が価値でした。

  2. 技術的負債を返済できた
    放置されがちな不要分岐を複数削除し、PRを作成してリリースできました。
    着実にコードベースが軽くなり、心理的負担が減ったことで今後の開発スピードの向上にもつながると感じています。

つまり今回の取り組みは、AI活用の経験値を積みつつ、技術的負債も減らせる一石二鳥の成果につながりました。

取り組んで分かったこと

実際にAIを使って技術的負債の返済を進めてみると、いくつかの学びがありました。

  • 小さな単位こそAIは力を発揮する
    範囲が明確でブレが少ない、小さいタスクがAIに最適でした。

  • 大きなタスクは説明や確認のコストが増える
    反対に、大きい修正だと背景を伝えるのに手間がかかってしまいます。
    特に、はっきりとした正解のないタスクの場合は、レビューの難易度も上がります。

  • クリティカルパスは避けた方がよい
    AIのアウトプットはコントロールしづらく、軌道修正も大変です。
    そのため、プロジェクトの進行に直結する領域でのAI利用はリスクが高いと改めて実感しました。
    まずは今回のような、失敗しても致命的でない領域で活用するのが最適解だと考えました。

今後の展望

今回の取り組みはまだ第一歩にすぎません。
設計からリリースまでを通しで実施したことで、今後さらに効率を上げられる余地も見えてきました。

  • Issue連携による自動化
    現状はチケットを元に手動で指示を出していますが、Issueの内容を読み取り、AIに自動でタスクを進めさせる仕組みを作れれば、さらに効率を上げられると感じました。

  • PR数の増加を見据えたリリースフロー改善
    AIが担うタスクが増えるにつれて、PRの個数も増加します。
    そのため、リリース作業の省力化や、複数変更をまとめてリリースできる仕組みの整備が必要になると感じました。

これらを踏まえると、人間とAIの役割分担を最適化することが、プロダクト開発全体の効率化につながる と考えています。

おわりに

技術的負債は、いつかやろうと思いながら後回しにされやすいものです。
今回の取り組みでは、この技術的負債返済をAIに任せることで、AI活用の経験値獲得と負債削減の両立を実現できました。

現時点では、AIに丸投げできる領域はまだ限られていると感じます。
それでも、小さくて明確なタスクからAIに任せてみる ことで、確実にコードは改善されていきます。

「いつかやる」を「今できる」に変える一歩を、AIと一緒に踏み出してみませんか?