Web未経験MLエンジニアが社内プロダクト開発でAIコーディングにどハマりするまで

はじめに

こんにちは、AIオペレーション室のエンジニアの菊田です!AIオペ室と略されるこの組織は、サイバーエージェント全社での生成AIの活用を促進するエンジニアリング組織です。今回は生成AIを活用し、サイバーエージェントの広告代理店業務を効率化する「タテadくん」という社内向けプロダクトの実装を担当しました。

AIオペ室では所属するエンジニア自身もAIを活用すべくAIコーディングを推進しています。このタテadくんの開発を通して、私個人のAIコーディングの依存度もどんどん上がってきました。今回は「タテadくん」の開発を通した、このAIコーディングの話について書いていこうと思います。

なお私の経歴をざっくり話すと、大学院で博士を取得後、コンピュータネットワークの研究者を務め、外資系のIT企業(GAFAMのどれか)やベンチャー企業にて自然言語処理のMLエンジニアや研究者を経験。6年前にサイバーエージェントへ中途入社し、5年近くAI事業本部の「極TD」チームでMLエンジニアを経て、1年前にAIオペ室に転属してきました。
これまで自然言語処理の機械学習のモデルを構築していたエンジニアから、転じてAIを「使うだけ」のアプリエンジニア(自称フルスタックエンジニア)に成り替わった、そんなキャリアのエンジニアが書いたブログとして読んでいただけると幸いです。

プロダクトとチーム体制

私の所属チームはAIオペ室の中でも広告代理店事業向けの生成AIプロダクトを作っているところで、ベテランPMの永山さん、新卒2年目エンジニアの大城さん、そして私の3人体制です。大城さんは新卒といえども大学時代にWebアプリを作って来たとのことでTypeScriptもなんのその。学生のうちからガンガンアプリを作るだなんて、私の大学時代との違いを感じます。一方の私はこれまでのエンジニア職歴を通して、Ruby,
C#, C++, Objective-C, Pythonあたりは使いこなして来ましたが、フロントエンドは全くの初心者。そんなデコボココンビでの開発が始まりました。

そんな我々が今回解決しなければならない課題は、関連会社のCyber ACEの縦型動画作成です。TikTokやInstagramリールの台頭により縦型動画の需要が急増している一方、その制作現場では以下のような課題を抱えていました。

  • 構成案のクオリティが担当者に依存する
  • 案出しに時間がかかる
  • 過去のナレッジが活用されにくい

「タテadくん」は、こうした課題を解決するために開発した、縦型動画の構成案をAIにより自動生成するWebアプリです。クライアントや広告商品の情報をDBに蓄積しておくことで、「このクライアントのこの商品で縦型動画を作りたい」という指示だけで、生成AIが広告の構成案を瞬時に作成してくれます。

AIコーディングのはじまり

タテadくんの開発よりも数ヶ月ほど前になりますが、AIオペ室のドラえもんこと齋藤さんがにこやかな顔で話しかけて来ました。彼は新技術を見つけてくるのが得意で、特に昨今のAI関連技術も困ったら彼に聞けば、ドラえもんのアイテムのように解決ツールを教えてくれる頼りがいのあるエンジニアです。そんな彼は私に何気なくAIコードエディタのCursorを勧めてきました。
「菊田さん、エディタは何をつかってますか?」私はVimでもEmacsでもなく、Macに標準で付属するXcodeユーザーでした。OS付属のエディタで十分だと感じているという大した理由ではないものの、慣れた環境を変えるのは多少は抵抗はあります。そんな私に齋藤さんの話は続きます。「Cursor使ってみませんか?」「AIコーディングめっちゃ便利ですよ」「Xcodeもいまや標準でインストールされないじゃないですか」そうでした。気がつけばXcodeは標準インストールではありません。
新技術はまずは使ってから考えるべきです。使ってみて利便性を感じなかったらやめればいいのです。ということで、一番の心理的障害となる初期セットアップを齋藤さんの助けにより乗り越え、AIによる開発を試みてみることになりました。

しかしながら、当時のAIコーディングは私としては納得の行くクオリティのツールではありませんでした。
頼んだ箇所と関係ない箇所が勝手に編集されてしまう。DRY(Don’t Repeat
Yourself)原則を無視して同じようなロジックのコードを増殖される。そのくせ書き方には統一性がなく、またバグもガンガン入れてくれます。さらにはプロンプトを送ってからコードが書き上がるまでの待ち時間が長すぎる。
時間がかかる上にレビューと手直し。はっきり言って私にとってはコードを自らの手で直接編集した方がよほど早く確実であり、当時のAIコーディングはまだまだ便利ではないなと感じました。

見方が変わったのはフロントエンド側の実装でした。その頃ちょうどこの「タテadくん」の開発が始まり、初めは私がバックエンド、大城さんがフロントエンドを担当していました。クライアントから要件を聞き取っては、大城さんがフロント部分のプロトタイプを生成していたところでした。プロトタイプの要件を伝えると、Cursorはスクラッチからものすごい勢いでコードを完成させていき、デザインを整えていきます。HTMLやReactのコードに不慣れな私にとっては、LLMには我々が見えないものを見ているかのように、「このインプットボックスをもう少し左に」「このselectをラジオボタンに」と言えば自由にデザインを調整してくれます。
とはいえ、このブラックボックス開発で私のようなエンジニアが納得できるわけがありません。「何が行われているのか」「見た目は正しく動いてそうだがコードはどうなのか」「効率化された適切なコードが書かれているのか」これらを追求したく、ReactやTypeScriptまわりをまず徹底的に学ぶこととしました。

AIコーディングにどハマり

TypeScriptとReactは別途で時間をきっちり取って学びました。ここは私のポリシーですが、中途半端な知識はこの業界では役に立ちません。プロダクト内で実験してその場しのぎで実装を続けるのではなく、空のディレクトリをプレイグラウンドとしてスクラッチからコードを自分で書き一つずつ機能を試しながら身につけます。ReactであればuseQueryを始めとする各フックが何をしているだとか、どのタイミングで再レンダリングが起きているだとか、みっちりと身につけていきます。またそのプレイグラウンドのコードを残しておくことで資産にもなります。ソフトウェアエンジニアである限り、永遠に学習し続けることは避けられません。この学習法は個人的には非常におすすめです。

さておき、Reactの原理原則が身について来た頃に「タテadくん」のコードを見直してみると、自分の経験からして納得のいくコードではありませんでした。
共通化できる余地が多く残されている。UIとロジックが密結合になっており責務が分離されていない。エラーが握りつぶされ障害時に原因を追えない状態になっている。このコードを改善すべく壮大なリファクタをかけることとしました。
その頃、Anthropicから新型モデルClaude Opusが登場しました。齋藤さんに勧められ、再度Cursorを使い始めることとしました。
これがどハマりです。Cursor上で動くClaude OpusはTypeScriptに不慣れな私が書くよりも早く、そして正確にコードを書いてくれます。
もちろん指示は必要です。「この処理は冗長なので共通関数に切り出してください」「この関数は薄すぎるのでインライン展開してください」「この命名では意図が読み取れないので改名してください」この最後の改名作業は単に一括置換すればいいような気がしますが、「改名先の名称がすでに使われていて衝突しないか」をチェックする必要を忘れないでください。そしてこれもOpusは抜け目なく対応してくれます。
後からわかったことは、特にTypeScriptとは相性がいいということ。また、あまり創造性が求められないリファクタ作業には特に向いていたということです。
そしてモデルの影響は非常に大きいです。一時的にOpusが使用できない時はSonnetに切り替えますが、当時は出力の精度に差を感じる場面がありました。

こうしてAIコーディングの力を得たリファクタは、驚くほどのスピードで完了しました。
ログは適切な箇所に出力され、問題が起きても即座に原因を追える。胸を張ってそう言えるコードになりました。
以降の開発工程については本記事では割愛します。現在は開発を終え、運用フェーズに移行しています。

ここで改めて、この1年を振り返ってみます。たった一年で、AIコーディングを取り巻く状況は一変しました。モデルの性能は飛躍的に向上し、できることの幅も質も別物です。この勢いが続く以上、今の常識もすぐに過去のものになるでしょう。
それを踏まえた上で、あくまで個人的な感想ですが、現時点で私が感じているAIコーディングの使いどころを整理してみます。

AIコーディングの使いどころ

言語の向き不向き

  • TypeScript: ★★★

型があるせいか、それとも過去の学習データが多いためか、非常に正確なコードを書いてくれます。
また一般的にフロントエンド側では複雑な作業がないためか、言語化しやすく、AIに伝えやすいということもあるかもしれません。
がしかし、気を抜くとDRY原則を無視してコピペコードのように同じロジックを量産します。
またデザインも、左に、右にと言えば移動してくれますが、親コンポーネントで調整すべき箇所をマージンで調整するような間に合わせの修正も入るので注意が必要です。

  • Terraform: ★★★

こちらはそもそも書き方が定まっている故に、ミスがしにくいのでしょう。
そして人間が記述しようとすると書く時間よりも調べ物に時間を割かれ、またスペルミスをはじめ不毛なミスにより無駄に時間が割かれるところを考えると、AIコーディングが非常に重宝します。
「こんなアーキテクチャ」と伝えるとAIが瞬時にコードを書いてくれます。
それも、各インフラの仕組みがわからないときに質問すると丁寧に教えてくれます。
そしてHTML同様、我々には見えていないものが見えているかのように、構築しようとしているインフラの「この部分がセキュリティ上のリスク」など指摘してくれます。また金額などもざっくり見積もってくれますし、インフラ周りは間違いなくAIにTerraformコードを書かせて管理すべきでしょう。
うまく動かないときにもgcloudやAWSコマンドを生成してくれ、実行すると勝手にデバッグしてくれます。

  • SQL: ★★★

こちらも構文が定まっており、やりたいことを自然言語で伝えやすい。人間が書くとスペルミスや構文ミスに悩まされるところを、AIは正確なコードを書いてくれます。
また、MySQLなどのデータベースには述語プッシュダウンをはじめとするクエリオプティマイザが備わっており、多少非効率な書き方をしてもエンジン側で実行計画を最適化してくれます。
AIはこれも考慮した上で、「この記述をした方が読みやすく、かつ効率的に実行される」などのコメントとともに優れたSQLを書き出してくれます。
とはいっても、SQLAlchemyのようなORMを使用していれば、実務上でSQLを書くことはデバッグのときなどに限られるかもしれません。

  • Python: ★★☆

TypeScriptと違い型がなく、メタプログラミングによる動的な処理も多いため、AIの出力精度が落ちる印象があります。
加えて、バックエンドはロジックが複雑なぶんAIへの指示も難しく、思った通りに実装してくれないことがあります。
リファクタ時に取りこぼしがあり、それが実行時まで発見されないということもありました。
一方で、的確な目的によりサードパーティライブラリを導入したい時は、どのライブラリを使うべきか、そのメリットデメリットを調べる時にはLLMは知識の宝庫なので大変役に立つでしょう。
またそのライブラリが思った挙動をしなくて困った時にも、そのライブラリのコードまで読みに行ってくれるので力になってくれます。

  • Shell Script: ★☆☆

私の期待通りでないというだけかもしれません。だいたいシェルスクリプトにするものは数行程度の簡単なものだと思います。
正しく動作するコードを出してくれるのですが、どうしてもコードの行数が期待よりも大幅に長くなります。
数行で済むはずだったスクリプトが、引数処理までガッチリ組み込んだ100行近いコードを書き上げて、結局手直しに時間を取られたりします。
とはいえ、指示を出せば短くもしてくれますし、シェルスクリプトは癖があるので、不慣れであればプロンプトで細かく指定したり、聞きながら開発を進めるのもいい手だと思います。

AIコーディングの便利な使い方

  • 導入すべきライブラリの選定

コードを書いていて、これは自分以外にも同じ課題を抱えた人がいそうだなと思う時、対応するサードパーティライブラリが既に公開されていることが多いです。
そんな時にLLMには膨大な知識がありますから、ライブラリがあるか一声かけてみましょう。大体の場合は、いくつかの候補を、メリットデメリットやサンプルコード、そしてプロジェクトの健全性まで教えてくれます。
これ以上、依存関係を広げたくない。自分で実装したいという場合もあるでしょう。私も割と自前実装しがちです。
それでもとりあえずは尋ねてみることをお勧めします。手頃で思いがけないライブラリが見つかる場合もありますし、
自前実装だとしてもAIがアドバイスをくれる場合もあります。

  • 変数や関数の命名相談

プログラミングの中で変数名や関数名ほど大事なものはありません。良いコードというのは、まるで人が書いたプレゼンテーション資料を読んでいるようにスラスラ読めるのが理想的です。そのためには変数や関数、クラスやデコレータなどの名前はこれ以上になく重要なものです。
特に英語を母国語としない我々には手頃な単語が思い浮かばず、どれも似たような変数名になりがちです。
こんなときにAIに問い合わせると、ロジックや文脈に基づいて手頃な名前の候補を出してくれます。

  • セキュリティーリスクのチェック

これは特にTerraformの構成ファイルに対してかけると非常に効率がいいです。構成ファイルに基づき、どのようなリスクがあるかを洗いざらい出してくれます。
もちろん、セキュリティに関しては人間がちゃんと知識を有して、人間が管理するべきであるとは思いますが、
うっかりミスや、インフラ設定の認識のずれなどもあります。ダブルチェックとしてデプロイ前に一度はAIにチェックしてもらうことをお勧めします。

一方で、うまくいかなかったケースもあります。本プロダクトにおいてDBのマイグレーションを導入する際、簡素なものが良かったのですが都合のいいライブラリが見つからず自前実装していました。後にこのファイルを修正する必要がありAIコーディングに頼ろうとしたのですが、全くもって期待通りに動いてくれませんでした。
おそらくですが、マイグレーションを自前で書くケースが少ないために過去のデータがあまりないことや、またDBのプロダクトデータ、マイグレーションのバージョン情報、チェックインするマイグレーションファイルなどの管理のような複雑なタスクには向いていなかった、さらには自然言語で説明しにくいという点が影響し、このような結果になったのではないかと思います。

AIコードレビュー

ここまでコーディングの話をしてきましたが、AIによるレビューもこの一年でものすごく進化したと感じます。
GitHubでは標準でCopilotが動作できますし、Greptileなど外部のAIレビューツールを導入して動作させられます。
個人的にはCopilotのレビューだけで十分かと思います。
セキュリティ周りは敏感で、的確なコメントをしてくれますので、プルリクエストでは少なくとも一度はレビューをしてもらうことをお勧めします。
可能であれば、修正と再レビューを繰り返し、Copilotがコメントしなくなるまで繰り返しレビューしてもらうと良いと思います。
一方で、AIレビューには必要以上に慎重なコメントを出すこともあれば、明らかに間違った初歩的なロジックのミスを見逃してしまうこともあります。
AIレビューは強力な補助ツールですが、最終的な判断は人間の目で行うべきでしょう。

AIコーディング vs ソフトウェアエンジニア

AIによるコーディング開発の進化には目を見張るものがあります。かつて私は自然言語処理のモデルを構築する側でした。一週間GPUを回して学習させていた「データを覚えさせただけ」のモデルが、今やまるで人が「考えている」かのようにコードを書いてくれる。ここまで述べたように、たった1年間でモデルの性能は飛躍的に向上し、エンジニアにとっても役に立つものとなったと思います。これからしばらくも同じように性能向上が続くでしょう。
そしてAIオペ室のエンジニアでも、この技術進化に圧倒され「エンジニアも仕事がなくなるのではないか」と心配する声が上がることがあります。
エンジニアという職は不要となり、なくなってしまうのでしょうか。これには様々な議論があるかと思います。

確かに、エンジニアがこれまでやってきたことをAIが代替してくれます。自然言語で対話するだけで、何百文字と書いていたコードをAIが代わりに代筆してくれます。
とはいえプロダクトとなって人々に使われるまでに、少なくとも現時点では誰かが指示を出し、出力をチェックし、これは安全で信頼できるコードだと確認できてからリリースする必要があります。
今後もそれは変わらないでしょう。その作業を行う人を「エンジニア」と呼ぶのかというだけだと思います。
そして、問題は「エンジニア」と呼ぶかどうかでなく、その作業する人にどのようなスキルが求められるかだと思います。

過去を振り返ってみましょう。Pythonのようなインタープリタ言語の登場によって、人々は簡単にプログラムを書けるようになりました。
C言語では理解する必要があったポインタ、メモリ管理、コンパイルの仕組みやリンカの動作など、低レベルな知識がなくてもプログラムが書けるようになりました。ガベージコレクションがメモリを勝手に解放してくれますし、インタープリタがコンパイルの手間を省いてくれます。pip
installでライブラリを入れれば、複雑な機能も数行で実現できます。
このおかげで「エンジニア」と呼ばれる人々が増えたのは確かでしょう。しかし実際に私が見たものとして、Pythonが書けるという若手エンジニアが、メモリが有限資源であることを意識せずに処理すべきデータをすべて一度に展開してOOM(Out-Of-Memory)を起こしたり、オブジェクトの参照と実体の違いを意識せず意図しない副作用を起こしたり、スレッドとプロセスの違いを理解せず並列化で躓いたりと、基礎的な理解が欠けているケースは少なくありません。
さらには、コーディング面接でPythonが書けると言っていた候補者に対し、簡単なforループを用いた数行のプログラムを書いてもらおうとしても、全く書けないというケースもありました。おそらくそのような候補者たちは、どこかのライブラリを呼び出して使うだけで満足していたのでしょう。

AIコーディングの時代になってもこれと同様でしょう。単にソフトウェアが作れますというだけでは「AIで十分ではないか」と言われるのは明らかです。
コンピュータの仕組みや、ソフトウェア設計により詳しく、「優れたシステム」を作るエンジニアを目指すことが求められるでしょう。

一方で我々エンジニアにとって追い風なのは、我々自身もAIコーディングを使って仕事を加速させられるということです。
加えて、生成AI自体を使ったプロダクトのニーズは加速的に増えており、ますますソフトウェア開発が求められるでしょう。

「優れたエンジニア」とは

では「優れたシステム」とは何でしょうか。そしてそれを作れるエンジニアとはどのような人でしょうか。

プログラムが動くだけでは「優れたシステム」とは言えません。
不具合が起こった時に、どれだけ早くバグを特定し、解決できるでしょうか。適切な箇所にログが出力され、障害時に即座に原因を追えるようになっているでしょうか。
新たな機能を追加する時に、どれだけ早く対応できるでしょうか。責務が適切に分離され、変更が一箇所で済む設計になっているでしょうか。
ユーザー数が急増した時に、システムは耐えられるでしょうか。スケーラビリティやコストを考慮したインフラ設計ができているでしょうか。
本番環境でデータベースのスキーマを変更する必要が出た時に、安全にマイグレーションを実行できるでしょうか。
リリース前にバグを検出できるテスト戦略が整っているでしょうか。

これらを考慮し、実現できるのが「優れたエンジニア」です。そしてこれらはすべて、AIも手を貸してくれる領域です。テストコードを書いてくれ、インフラ構成を提案してくれ、ログの出力箇所を指摘してくれます。
しかし「何が必要か」を判断し、「これで十分か」を見極めるのは人間の仕事です。

さらに上流には「何を作るべきか」という判断があります。ユーザーの要望をそのまま実装すべきか、本質的な課題を解決する別のアプローチがあるか。開発速度を優先すべきか、可読性を優先すべきか。機能を増やすべきか、コストを抑えるべきか。ビジネス要件と技術的制約のすり合わせは、文脈を理解したエンジニアにしかできません。

コードを書く速度はAIが圧倒的に速い時代になりました。だからこそ我々に求められるのは、要件の本質を見抜き、適切なトレードオフを選び、AIの出力を検証し、責任を持ってリリースできる力でしょう。

AIコーディング時代に求められる開発速度

もう一つの話として、我々のチームのPMの永山さんが使っていたノーコード開発ツールを紹介します。
Replit
Agentというサービスで、簡単に言うとコードを1行も書かずに、プロンプトだけでサービスが開発できるものです。DBなどがサービス側で提供されており、ややこしいインフラ問題に触れることがありません。開発時のターミナル出力がそのままLLMにつながっており、LLMが勝手に試行錯誤し、デバッグし、求める機能を実装していきます。これにより永山さんはエンジニアの手を借りることなくサービスを構築しました。

出来上がったコードを見ると、エンジニアの視点では改善の余地が多く見られました。保守性も可読性も考慮されておらず、先ほど述べた「優れたシステム」とは程遠い。しかし「とりあえず動く」コードを一瞬で作り上げたのは事実です。

これが現実です。エンジニアでなくても、動くコードを短時間で作れる時代になりました。
だからこそ、我々エンジニアにも同等かそれ以上の開発速度が求められます。もちろんAIコーディングを使って構いません。むしろ使わない手はありません。
その上で、Replit Agentでは実現できない「優れたシステム」を作れること。それが我々の価値になるのではないでしょうか。

まとめ

AIコーディングとの出会いは、正直なところ失望から始まりました。しかしモデルの進化とともに、いまでは開発に欠かせないツールとなっています。

この一年の経験から言えることは以下の3点です。

  1. AIコーディングは万能ではない。言語やタスクによって向き不向きがあり、特に複雑なロジックや自然言語で説明しにくい処理には不向きです。
  2. 基礎知識は依然として重要。AIの出力を評価し、修正するためには、言語やフレームワークの原理原則を理解している必要があります。ブラックボックスのまま使い続けることは危険です。
  3. AIを使いこなすエンジニアが求められる。コードを書く速度ではAIに勝てません。だからこそ、要件の本質を見抜き、トレードオフを判断し、AIの出力を検証できる力が我々の価値になります。

AIコーディングの進化はこれからも続くでしょう。その波に乗りながらも、流されずに自分のスキルを磨き続けること。それが、この激動の時代を生き抜くエンジニアの姿勢ではないでしょうか。

アバター画像
2020年に中途入社したフルスタックエンジニア。外資系テック企業を含む複数社にて、自然言語処理を軸としたMLエンジニアとして、検索・変換・生成などの言語系プロダクトの研究および実用化に携わってきた。 サイバーエージェントでは「極TD」にて自然言語分野のMLエンジニアとしてプロダクト開発に従事した後、現在は「AIオペ室」に所属し、社内AIツールの開発を行っている。