株式会社LIFULLのブログ - TECH PLAY

TECH PLAY

株式会社LIFULL

株式会社LIFULL の技術ブログ

全668件

テクノロジー本部事業基盤部アーキテクトグループの福留です。最近気になっている技術はAWS CodeBuildの Docker Server です。 LIFULL HOME'Sの開発環境を改善した際の、組織を超えた協業の様子をお伝えします。 1. 背景 2. ローカル環境化への道のり 3. 部署を超えた協力体制の構築 4. 技術基盤だけでは開発環境にならない 5. TEが共通の開発基盤を整える 6. PEがE2E基盤で機能を検証する 7. LFTVとLFTMが利用者として検証する 8. 課題を組織の間で受け渡す 9. 終わりに 1. 背景 LIFULL HOME'SのC向けレガシーWebアプリケーションは、15年ほど前から開発が続けられており、今でも現役で稼働しています。ゆえにその開発方法も昔ながらで、中央サーバにSSH接続して開発を行うスタイルでした。 この開発スタイルには次の問題がありました。 サーバを維持する運用工数と費用がかかっていた サーバに搭載されているミドルウェア起因で、AIコーディングエージェントツールが利用できなかった LIFULLの多くのリポジトリはローカル環境が整備されていて、AIコーディングエージェントツールが利用できています。一方このリポジトリの開発サーバには、コーディングエージェントツールの利用要件とは異なるミドルウェアが搭載されており、コーディングエージェントが利用できません。したがってローカル環境のあるリポジトリと比べると開発効率に大きな制約がありました。また、このリポジトリは月間で相当数の開発者がコミットを行なっており、AIを利用できないことによる制約の影響が大きくなっていたともいえます。 サーバのミドルウェアを入れ替えて同じ開発スタイルを続けることもできましたが、維持コストの問題を解決するためにはローカル環境しかないと考え、ローカル開発環境化に踏み切りました。 2. ローカル環境化への道のり LIFULL HOME'Sを構成する多くのアプリケーションは全社共通アプリケーション実行基盤で実行されています。この基盤はKubernetesをベースとしているので、Dockerを用いて実行されています。 このアプリケーションも全社共通アプリケーション実行基盤のしくみに乗っているので、本番環境やステージング環境はDockerコンテナで実行されています。そのため、Docker Composeをベースとした開発環境を構築できる状態でした。 まずはステージング環境のk8s manifestをもとにdocker-compose.yamlを構築して起動できる状態にしました。 しかし、アプリケーション全体が開発サーバを前提として構築されていたため、それだけではページ遷移などに問題がありました。しかも、無数のページがあるのでどこで問題が発生しているのかわかりませんでした。 そこで、社内で用いられているE2Eテスト基盤を用いてこの課題を解決しました。このE2E基盤は従来ステージング環境に対して恒常的に実行されており、テストシナリオが豊富にそろっています。そのため、そのシナリオをローカル環境で実行して問題を見つけ、一つずつ解決していきました。 こうして、ステージング環境と同等の機能をもつローカル環境ができあがりました。 3. 部署を超えた協力体制の構築 長くなりましたが、ここからが本題です。この取り組みは、私が所属するテクノロジー本部(TE)だけで行っていたものではありません。 LIFULL HOME'Sの主な機能開発はプロダクトエンジニアリング部(PE)が、LIFULL Tech Vietnam(LFTV)/Malaysia(LFTM)とともに行っています。 まず私たちTEがDocker Compose、 Makefile、READMEなどの技術的な土台を整備しました。その土台に対してPEがE2Eテストをかけたり、細かい機能の不備を修正して品質を高めていきました。LFTV/LFTMのメンバーには実際に環境を構築して日常の開発で使ってもらい問題点を報告してもらいました。 ここからは、私たちがどのように協業したのかを紹介します。 4. 技術基盤だけでは開発環境にならない ローカル環境を作るには、Docker Composeでコンテナを起動できる状態を用意する必要があります。 しかし、コンテナが起動するだけでは、開発者が継続的に使える環境にはなりません。 編集したコードが正しく反映されることや既存の画面遷移が動作することはもちろんですが、初回セットアップで迷わないこと、問題が起きたときに相談先がわかることも必要です。 これらの問題は、環境を実装する側だけでは見つけにくいものでした。 TEが構成や起動手順を確認していても、異なるOSやDocker実行環境で初めて構築する利用者がどこでつまずくかまではわかりません。 一方で、利用者が問題を発見しても、原因がMakefile、コンテナ、アプリケーション、ネットワークのどこにあるかを判断できるとは限りません。 そこで、PEとTEがそれぞれの立場から動作を確認し、LFTVとLFTMが実際の利用結果を共有する進め方を取りました。 5. TEが共通の開発基盤を整える まず、移行を主導するTE/PE間で、アプリケーションの編集、起動、確認をローカルで行えることを、共通の目標として整理しました。 そこでTEは、利用者が迷わず開発環境を構築・起動できるようにするため、Docker ComposeとMakefileを整備しました。 ローカルのソースコードをコンテナへマウントし、コンテナ上でアプリケーションを起動することで、開発者はローカルでコードを編集しながら動作を確認できるようにしました。そのうえで、起動手順はMakefileへ集約しました。 ところで、ローカル環境そのものの利用状況がわからなければ、どの環境で問題が発生しているかを把握しにくくなり、サポートの優先順位も付けにくくなります。また、エラーの報告が上がらなければ、利用不可能な状況に陥っていることすらわからない、受動的な状態になっていました。そこでTEは、誰の端末で起動失敗しているのか、利用状況を追跡できる方法を用意しました。 利用状況の追跡方法のアイデアはシンプルです。環境起動開始、起動完了時に、社内に作ったWeb APIサーバへ以下の形式でGETリクエストを送るだけです。 /build/<start|complete>?repositoryOwner=<リポジトリオーナー>&repositoryName=<リポジトリ名>&executor=<実行したユーザ>&status=success&hash=<起動シーケンスを識別するハッシュ>&buildSystemVersion=<ローカル環境のバージョン>&commitHash=<リポジトリのコミットハッシュ> TE側ではリクエストログを集計するだけで、誰がどのバージョンで起動成功・失敗しているのかが自動でわかるようになり、能動的にサポートを行えるようになりました。 OSによる違いにも対応しました。macOSとWSL2で異なる部分をOS別のMakefileへ分け、利用者が同じ入口からセットアップできる形を整えました。 READMEには環境構築手順を追加し、問題が起きた場合はSlackのユーザーグループ宛に相談する流れも案内しました。 このように、TEでは起動手順、利用状況の確認、ドキュメント、サポートの入口を含めた、開発環境を使うための一連のしくみを整えました。 6. PEがE2E基盤で機能を検証する PEは、ローカル環境が起動することだけでなく、既存の機能がステージング環境と同じように動作することも確認しました。 検証には、画面操作を含む一連の動作を確認する全社共通E2Eテスト基盤のシナリオを使いました。 PEは、シナリオが失敗した場合に、失敗した操作、再現条件、エラーメッセージ、発生した画面などを整理しました。確認では、URL生成、外部サービスとの連携、画面要素の検出など、複数の種類の問題が見つかりました。 これらの問題は、E2Eテストのシナリオを修正するだけでは解決しません。アプリケーションの修正が必要な場合もあれば、Docker Composeや環境設定の修正が必要な場合もあります。PEは問題を課題管理表に記録し、必要に応じてTEや関係する開発者へ調査を依頼しました。期待する動作や再現手順が不明な場合は、QAにも確認しました。 修正後は、同じE2Eテストのシナリオを再実行して動作を確認します。Pull Requestのレビューとシナリオの再実行を繰り返すことで、問題の検出、修正、修正後の確認を同じ手順で進められるようにしました。 E2Eテストは、失敗した操作と再現条件を共有し、修正後の状態を確認するための共通の検証手段として機能しました。 7. LFTVとLFTMが利用者として検証する LFTVとLFTMのメンバーは、実際にローカル環境を構築して使う利用者として参加しました。 利用者からは、次のような問題が報告されました。 ホストOS(macOS/Windows)の違いによるDocker Engineの挙動の違い Rancher Desktop の設定 起動に必要なファイルの権限不足 利用者が実行ログと環境情報を共有したことで、TEは手順の不足と実装上の問題を切り分けられました。この情報は、READMEの修正やdocker-compose.yamlの変更、セットアップ手順の改善へ反映されました。 LFTV/LFTMとの協業では、E2Eテストの課題調査も分担しました。LFTV/LFTMのメンバーが課題リストを確認し、対応可能な項目を引き受ける流れが作られました。課題を一覧化して担当者を割り当てることで、調査の進み具合を共有しやすくしました。 環境を提供する側が手順を公開するだけでなく、利用者が実際に試し、わからない点を質問し、その質問を次の手順改善へつなげる流れができました。 8. 課題を組織の間で受け渡す PE、TE、LFTV、LFTMの協業では、課題を発見した人が解決までを一人で担当するのではなく、問題の種類に応じて調査や修正を引き継ぎました。 まず、課題を発見した担当者が、再現手順、実行ログ、利用環境などを課題管理表に記録します。PEがE2Eテストの実行中に見つけた問題であれば、失敗したシナリオや画面も記録しました。LFTVやLFTMが環境構築中に見つけた問題であれば、使用したOS、Docker実行環境、実行したコマンドを共有しました。 その後、問題の種類に応じて担当者を決めました。Docker ComposeやMakefile、READMEの問題はTEが調査し、アプリケーションの機能や画面遷移に関する問題は関係する開発者が調査しました。期待する動作や再現手順が不明な場合は、PEやQAに確認しました。 修正後は、Pull Requestで変更内容を確認します。必要に応じてPEがE2Eテストのシナリオを再実行し、LFTVやLFTMのメンバーがローカル環境を再構築して、同じ問題が解消したことを確認しました。 課題の発見、原因調査、修正、再確認の結果は、Slack、課題管理表、Pull Requestに分けて記録しました。これにより、問題を個別の問い合わせで終わらせず、次の担当者が調査を続けられる状態にしました。 9. 終わりに 今回の移行はDocker Composeでコンテナを起動するだけでは終わりませんでした。開発者が環境を構築し、問題を報告し、修正後の状態を再確認するまでの運用を整えました。 利用者が見つけたOSやDocker実行環境の違いは、READMEやセットアップ手順の改善のきっかけになりました。E2Eテストで見つかった画面遷移や外部サービス連携の問題は、アプリケーションやDocker Composeの修正へとつながっていきました。 このように、ローカル開発環境を一度構築して終わりにするのではなく、次の流れで改善を続けられる状態を作りました。 環境を構築する 実際の開発やテストで使う 問題を再現手順とともに共有する 担当者が修正する E2Eテストや利用者の再構築で確認する この流れを組織間で共有できたことで、開発環境の問題を特定の担当者だけが抱え込まず、手順や実装の改善へ反映できるようになりました。ローカル開発環境への移行で得られた成果は、Docker ComposeやMakefileなどの技術基盤だけでなく、複数の組織が同じ課題を発見から再確認まで扱える協業のしくみです。 最後に、LIFULLではともに挑戦していける仲間を募集しています。ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
こんにちは、データサイエンスプロダクトグループの清田です。 2026年6月8日から12日にかけて、群馬県高崎市のGメッセ群馬で開催された 人工知能学会全国大会(JSAI2026) に参加してきました。私たちはこの大会で、 オーガナイズドセッション「不動産とAI」 (OS-27)を企画・開催しました。今年はこのセッションにとって特別な年で、「不動産とAI」という研究コミュニティが10周年の節目を迎えました。 本記事では、セッションの内容をダイジェストでお伝えするとともに、その10年の裏側にあった LIFULL HOME'Sデータセットの提供 という取り組み、そして私たちがこれからの10年をどう描こうとしているのかを、あわせてご紹介します。 JSAI2026の会場となったGメッセ群馬 「不動産とAI」オーガナイズドセッションとは 10年の裏側にあった、LIFULL HOME'Sデータセット この10年の歩み ―「価格を当てる」から「価値を捉える」へ 黎明期(2016–2017) 学際展開期(2018鹿児島・2019新潟) 進化期(2020・2021オンライン) 体系化・生成AI期(2022京都〜2025大阪、そして2026群馬) セッションダイジェスト テーマ1:AIが機能する「情報基盤」を問う テーマ2:予測モデルを、AI自身が高度化する テーマ3:感性・意味・物語を、価値にする これからの10年 ― 価値の多元化 おわりに 「不動産とAI」オーガナイズドセッションとは 「不動産とAI」は、人工知能学会全国大会で毎年開催してきたオーガナイズドセッションです。今年は6月10日(水)午前中に開催し、9件の研究発表と総合討論を行いました。会場(K会場)は終始盛況で、オンラインからの参加者や、同じ時間に隣の会場で開催されていた GeoAI(地理空間情報とAI)のセッション からの合流もあり、活発な議論が交わされました。 sites.google.com オーガナイザは、橋本武彦さん(GA technologies)、私 清田、山崎俊彦先生(東京大学)、諏訪博彦先生(奈良先端科学技術大学院大学)、清水千弘先生(一橋大学)、吉原勝己さん(スペースRデザイン/NPO法人福岡ビルストック研究会)の6名です。不動産の事業者、AI・情報学の研究者、経済学者、まちづくりの実践者と、立場の異なるメンバーが集まっているのが、このコミュニティの特徴です。 ここで言う「不動産とAI」は、賃料や価格の予測だけを指すのではありません。国内では「不動産テック」、海外では PropTech(プロップテック)と呼ばれる広い領域――取引仲介、不動産×金融、物件管理、建築・建設、スマートビル、さらには街づくりや人の流れまで――を視野に入れています。 「不動産とAI」セッション冒頭の趣旨説明のスライドは、こちらで公開しています。 speakerdeck.com 10年の裏側にあった、LIFULL HOME'Sデータセット 実は今回は、コミュニティの10周年であると同時に、研究の土台の一つとなってきた LIFULL HOME'Sデータセット の提供開始からも、ちょうど10年の節目にあたります。 このデータセットは、2015年11月に、国立情報学研究所(NII)の 情報学研究データリポジトリ(IDR) を通じて、研究者の皆さまに提供を開始したものです。物件情報や間取り画像といった、それまで研究の世界ではなかなか手に入らなかった不動産データを、産学連携の形でオープンにしていく――この取り組みが、不動産分野の機械学習・AI研究が立ち上がる一つのきっかけになりました。 www.lifull.blog 「不動産とAI」コミュニティが2016年に始まったのも、こうしてデータが流通し始め、研究テーマが具体的に語れるようになってきたことと無関係ではありません。データを提供する側だったLIFULLにとって、この10年は「提供したデータが、どんな研究を生み、社会にどう還っていくのか」を見届ける10年でもありました。 この10年の歩み ―「価格を当てる」から「価値を捉える」へ セッションの趣旨説明では、この10年を一言でまとめるなら「価格をどう当てるかという問いから、価値をどう捉えるかという問いへ」の深化だった、とお話ししました。 かつての不動産AIは、ヘドニック回帰に代表されるように、価格という一点の数字をいかに精度よく当てるかが中心でした。それが、不動産物件の感性価値・本来価値・長期価値といった多面的な価値をどう捉え、社会と共有するかへと、関心が移ってきています。不動産は、あらゆる財の中でも最も価値の測定が難しい対象です。その難しさに、私たちは10年かけて少しずつ近づいてきました。 歩みは大きく4つの時期に分けられます。 黎明期(2016–2017) データのオープン化。LIFULL HOME'Sデータセットの提供開始、FIT2016(富山)・FIT2017(東大)、そして2017年名古屋からの人工知能学会全国大会セッション開始。 FIT2016 第15回情報科学技術フォーラム FIT2017 第16回情報科学技術フォーラム sites.google.com www.lifull.blog 学際展開期(2018鹿児島・2019新潟) 経済学・建築学・都市学・情報学が交わる場へ。間取りのグラフ化や賃料予測など、テーマが一気に多様化。国際会議ワークショップの開催にもつながる。 sites.google.com sites.google.com sites.google.com sites.google.com 進化期(2020・2021オンライン) 山崎先生の「 魅力工学 」が合流し、感性のデータ化が本格化。情報の非対称性や、減価償却ルールによる建物価値の毀損といった本質的な問いへ。 sites.google.com sites.google.com 体系化・生成AI期(2022京都〜2025大阪、そして2026群馬) LIFULL HOME'Sデータセットの研究利用実績は150件を超え、生成AIが新しい潮流に。 sites.google.com sites.google.com sites.google.com www.lifull.blog sites.google.com ここに述べたように、富山から始まり、名古屋・鹿児島・新潟、オンライン、京都・熊本・浜松・大阪、そして群馬へ。 毎年場所を変えながら、議論を積み重ねてきました。 セッションダイジェスト 今年の9件の発表は、大きく3つのテーマに束ねられます。 テーマ1:AIが機能する「情報基盤」を問う 生成AIの性能は飛躍的に上がりました。しかし現場では、AIの性能よりも前に、そもそもAIが使えるデータが整っていないという壁にぶつかります。 合同会社アキューズの齋藤孝春さんは、宅地建物取引士でありAIエンジニアでもある立場から、重要事項説明書(重説)作成の現場を報告されました。重説に必要な情報は、法務局・区役所の複数部署・水道局・ガス事業者……と7〜10もの窓口に分散し、統合的に照会する仕組みがありません。齋藤さんの「真の障壁はAIの性能不足ではなく、情報基盤の構造的課題だ」という指摘は、セッション全体を貫く論点になりました。総合討論やSlackでの質疑では、「行政情報が情報化されても、私人間の文書(境界確認書など)が残るため、AIが担えるのは作成業務の7割程度ではないか」という、現場ならではの踏み込んだ議論にも発展しました。 [3K1-OS-27a-02] 重要事項説明書作成におけるAI活用の前提条件 情報基盤の課題と提言 〇齋藤 孝春 (合同会社アキューズ) 日本取引所グループの田中麻由梨さん・土井惟成さんは、J-REITの有価証券報告書から投資物件情報を構造化する手法を発表されました。投資法人ごとにバラバラな表形式を、共通のプロンプトとチャンク化で頑健に読み取り、主要項目でF1スコア0.977という高い精度を達成。開示文書という「半構造データ」をAIの入力に変える、実務に直結する研究です。 [3K1-OS-27a-05] 多様な表形式のデータに対してロバストなJ-REIT投資物件情報の構造化手法の提案 〇田中 麻由梨、土井 惟成 (株式会社日本取引所グループ) 東京大学の増田俊太郎さん・山崎先生、エムディーの平井樹さんのグループは、衛星画像・ストリートビュー・道路名といった公開データから、大規模マルチモーダルモデルで意味特徴を抽出し、道路の交通量を推定する研究を発表されました。観測コストが高く幹線道路に偏りがちな交通量データを、公開データで補うという発想で、店舗の商圏分析にもつながります。 [3K2-OS-27b-04] マルチモーダル地理意味特徴に対するタスク考慮型クラスタリングによる交通量推定 〇増田 俊太郎1、平井 樹2、山崎 俊彦1 (1. 東京大学大学院、2. エムディー株式会社) テーマ2:予測モデルを、AI自身が高度化する 東京大学の髙辻優太さん・山崎先生、estieの岩成 達哉さんらのグループは、賃料予測モデルの改善プロセスそのものをLLMに自動で反復させるフレームワークを発表されました。「誤差を分析し、改善案を出し、コードを実装し、評価する」というデータサイエンティストの試行錯誤をGPTが代行し、全国の賃貸データでベースラインから統計的に有意な精度向上を実現しています。 [3K1-OS-27a-04] 大規模言語モデルによる多角的誤差分析に基づいた不動産賃料予測手法の自動改善 〇髙辻 優太1、岩成 達哉2、勝田 良介2、増田 俊太郎1、易 聖舟1、山﨑 俊彦1 (1. 東京大学、2. 株式会社estie) 東京大学の玉真永棋さんらは、金利上昇下でも高騰を続ける東京の住宅市場を、エージェントベースモデル(ABM)で再現しました。世帯や投資家といった異質な主体の「トレンド追随(群集行動)」を組み込むことで、ファンダメンタルズだけでは説明できない価格の増幅メカニズムを分析しています。 [3K1-OS-27a-03] 住宅市場ABMにおけるハーディングモデルの拡張と価格増幅メカニズム分析 〇玉真 永棋、藤井 秀樹 (東京大学大学院) テーマ3:感性・意味・物語を、価値にする 東京科学大学の沖拓弥さんらは、オフィスビルの外観の印象を、約2万棟の画像と20万件のアンケートから定量化し、視覚言語モデルを使って「どんな外観要素が好印象につながるか」まで分析されました。狙いは、新しく大きい建物が高評価という当たり前の結論を超えて、古く小さな既存ストックの魅力を引き出すことにあります。 [3K1-OS-27a-06] 賃貸オフィスビルの外観の印象評価構造 藤田 晋太朗1、〇沖 拓弥1、松尾 和史2、今関 豊和2 (1. 東京科学大学、2. オフィスビル総合研究所) ニュージャージー工科大学の楢原太郎さんは、間取りの「住み心地」をAIがどこまで読めるかを検証されました。GPTは開放感や現代性といった視覚的印象には強い一方、動線やプライバシーのような「部屋同士のつながり」の理解にはまだ弱い――AIの能力の境界を、丁寧に示す研究です。 [3K2-OS-27b-01] 人間と大規模言語モデルによる不動産間取り評価の比較分析 ―視覚的印象評価と構造理解の差異― 〇楢原 太郎1、山崎 俊彦2 (1. ニュージャージー工科大学、2. 東京大学) そして今年特に話題を集めたのが、 「ビル格(Building Personality)」 という考え方でした。樅山拓大さん(マレーシアAPU)と吉原勝己さん(吉原住宅)は、建物を「数字で測る対象」から「意味を語り、判断する主体」へと捉え直し、建物の歴史・文化・関係者の想いといった質的情報をLLMで構造化する枠組みを提案されました。舞台となったのは、築67年で民間のRC集合住宅として日本初の登録有形文化財となった福岡の「冷泉荘」です。 [3K2-OS-27b-02] ビル格(Building Personality):人格を持つ不動産がもたらす新領域 生成AIによる建物の主体化と既存建築ストックの価値再定義 〇樅山 拓大1、吉原 勝己2 (1. Asia Pacific University of Technology & Innovation (APU)、2. 吉原住宅有限会社) LIFULL HOME'S PRESS: ビンテージマンションを多様な個性が集まるミュージアムに。福岡「冷泉荘」を訪問 www.space-r.net 樅山さん・吉原さんによるご発表の様子 私(清田)と麗澤大学の学生2名(豊田智康さん・長嶋一樹さん)は、この続編として、ビル格を起点に生成AIで動画と音楽をつくり、不動産リブランディングに使えるかを実験しました。分かったのは、「らしさ」の源泉は築年数や外観といったスペックではなく、入居者・文化・歴史といった一次情報にあること。そして生成AIの価値は、出力そのものより、目的設計と人による編集(Human-in-the-loop)にあること、でした。 [3K2-OS-27b-03] 建物人格を媒介とした生成AIによる不動産ブランディング 冷泉荘におけるマルチモーダル生成実験の報告 〇清田 陽司、豊田 智康、長嶋 一樹 (麗澤大学) speakerdeck.com 麗澤大学の学生2名による動画・音楽生成の実践報告 これからの10年 ― 価値の多元化 総合討論では、次の10年に向けた三つの問いを掲げました。すなわち、①解決すべき課題(研究・応用の障壁)は何か、②必要なデータとは何か、③求められる研究は何か、です。 私からは、これからの不動産の価値が「多元化」していくという見立てをお話ししました。鍵となるのは3つの価値軸です。 感性価値:街の音・光・緑・人の流れを可視化する 本来価値:建物の性能や管理の履歴、長期リスクをふまえて評価する(AIやドローンによる点検が支える) 長期価値:10年・20年・30年先を、街の文脈ごとシミュレーションする これらは制度としても、AI点検の標準化、性能履歴に基づく本来価値の評価、ウェルビーイングや街の魅力の都市評価への組み込み……といった形で社会に根づいていくと考えています。世界の不動産テック市場も、2025年の約450億ドルから2036年には約2500億ドルへと、大きな成長が見込まれる領域です。 総合討論では、「過去の情報で学習するLLMで、創造的な未来の街を描けるのか」(防災の観点から)、「自治体ごとにデータがバラバラなのは、実は民間にも原因があるのではないか」、「LLMのおかげで自然言語のデータも資産にできるようになった」といった、刺激的な論点が次々と出ました。国土交通省・内閣官房が2026年に立ち上げた「ジオAI研究会」の紹介もあり、GeoAIコミュニティとの連携、そして何より研究と現場の接続が、次の10年の大きなテーマになりそうです。 www.mlit.go.jp おわりに 10年前、私たちはデータを提供する側として、この分野のスタートラインに立ちました。10年が経ち、データは多くの研究を生み、生成AIという新しい力も加わって、「価格」から「価値」へと問いは深まってきました。次の10年は、その多元的な価値を、研究者だけでなく現場の方々と一緒に、社会と共有できる形にしていく10年にしたいと思っています。 LIFULLは、これからもデータと研究を通じて、「あらゆるLIFEを、FULLに。」という思いのもと、不動産とAIの未来づくりに取り組んでいきます。 LIFULLでは、データサイエンス・AIに取り組む仲間を募集しています。ご興味のある方は採用ページをご覧ください。 hrmos.co
こんにちは! LIFULLのマーケット横断部署でエンジニアリングマネジャーをしている吉永です。 本日は、エンジニアもサービス改善の施策を提案しやすくするために、生成AIへ調査手順や参照する情報、出力形式をまとめた、再利用可能な指示書を作った取り組みについて紹介します。 ※本記事では、この指示書を「施策提案スキル」と呼びます。 生成AIを活用してチームの企画力を広げたい方や、AIに施策案を出してもらっても一般論にとどまりがちだと感じている方の参考になれば幸いです。 取り組みを始めた背景 施策提案スキルで実現したこと 2つの使い方と、その結果 私のアプローチ: データから課題と施策を探す チームのエンジニアのアプローチ: アイデアの確からしさをAIで補強する 結果の違いから見えたドメイン知識の価値 次に取り組みたいこと 最後に 取り組みを始めた背景 実際にチームへ展開すると、2つのケースで結果に違いが出ました。一つは、私が生成AIに現状分析から施策案の作成までを任せたケースです。もう一つは、長くサービス開発に携わってきたエンジニアが自分のアイデアを生成AIで補強したケースです。 この経験から、生成AIに施策を考えてもらう際に、プロンプトやデータ分析と同じくらい大切だと感じたものがあります。それが、人が持っているドメイン知識です。 ※ここでいうドメイン知識とは、サービスの仕様やユーザー理解、過去施策の経緯など、担当業務を通じて蓄積される知識や経験のことです。 私たちのチームでは、サービス改善を企画するメンバーがSEOやCRO(Conversion Rate Optimization、コンバージョン率最適化)など、複数領域の施策を並行して担当していました。 継続的に改善を進める一方で、施策の選択肢を出し続けることには難しさがあります。特に当時は、チーム目標と現状のギャップを埋めるプランを早急に立て、実行へ移す必要がありました。 そこで考えたのが、エンジニアも施策提案に参加しやすい環境を作ることです。 エンジニアは、日々の開発を通じてサービスの仕様、データ構造、技術的な制約、ユーザー体験上の違和感に触れています。ただし、気付きを企画として説明するには、現状の数値、期待効果、過去施策との差分、A/Bテストの設計などをそろえる必要があります。アイデアはあっても、提案書へ落とし込むまでのハードルが高い状態でした。 このハードルを生成AIで下げられないかと考え、過去の不動産情報を提供するアーカイブサイトの課題抽出から改善提案までを支援するスキルを作成しました。 スキルを作成した後は、企画担当者のタスクが多く、施策を十分に検討する時間を確保しにくい一方で、チーム目標とのギャップを埋める必要があるという現状をエンジニアへ共有しました。そのうえで、「こんなスキルを作ってみたので、試しに使ってみませんか。みんなで施策案を出してみましょう」と声をかけました。 完成した仕組みを渡すだけではなく、なぜ今エンジニアからも施策案を出したいのかを伝えたことで、チームの課題を自分ごととしてとらえてもらえたと思います。 施策提案スキルで実現したこと 初版のスキルでは、生成AIに「施策を考えて」と依頼するだけではなく、施策提案に必要な調査と整理を一定の手順で進められるようにしました。 当初扱っていたのは、主に次の情報です。 行動データから、ページ閲覧や導線の利用状況を確認する ソースコードを読み、現在の仕様や実現可能性を確認する 課題、仮説、対象ユーザー、期待効果、リスクを整理する A/Bテストの指標と判断基準を含む、施策仕様書のたたき台を作る 初版で特に意識したのは、推測と事実を混ぜないことです。仮説を立てたらデータで確認し、確認できないものは仮説として残すようにしました。また、施策の魅力だけではなく、対象となるユーザーの規模、実装コスト、既存機能への影響まで整理するようにしていました。 これにより、エンジニアは自分の気付きやアイデアを入力し、企画担当者が優先度や実施可否を検討できる内容まで具体化しやすくなりました。 一方、実際に使ってみると、過去の類似施策や足元のチーム目標とのつながりまで十分に確認できないケースがありました。この点は、後述する施策案の比較を通じて見えてきた課題です。 そこで現在のスキルには、次の観点を追加しています。 関連する過去施策とA/Bテスト結果を確認し、同じ失敗を繰り返さない 足元のチーム目標や中間指標と、施策が動かす指標のつながりを確認する 「なぜ行うか」「何を変えるか」「誰に届けるか」を整理し、提案の優先理由を明確にする スキルも一度作って終わりではなく、実際の提案結果から得た学びを取り込みながら更新しています。 2つの使い方と、その結果 スキルを使って、私とチームのエンジニアがそれぞれ施策案を作りました。興味深かったのは、同じスキルを使っていても、生成AIへの入り口が異なっていたことです。 私のアプローチ チームのエンジニアのアプローチ 出発点 まず行動データを分析する 日々感じていた改善アイデアを入力する 生成AIの役割 数値から課題を抽出し、施策案を広く作る アイデアの確からしさをデータや過去事例で検証する 人が主に提供したもの 分析対象と目標 仮説、ユーザー理解、実装経験、過去施策の記憶 結果 複数の案を作ったが、実施候補には選ばれなかった 2件が実施候補に選ばれ、いずれもA/Bテストでエンジニアが提案したBパターンが既存パターンを上回り、採用された 私のアプローチ: データから課題と施策を探す 私は、行動分析ツールのデータから現状を把握し、課題を抽出したうえで改善案を作るところまで生成AIに依頼しました。 生成AIは、複数のデータや実装を横断し、短時間で施策候補を並べることには向いていました。施策ごとの期待効果や実装コストも整理できたため、検討材料を増やすという点では役立ちました。 一方で、作成した案は実施には至りませんでした。 実施に至らなかったのは、案そのものが成立していなかったためではありません。中には、過去に類似施策を実施し、A/Bテストで新しいパターンが既存パターンを下回っていた案もありました。また、足元で改善したい指標へ直接つながらず、優先度が下がった案もありました。 データから一見妥当に見える改善余地を見つけるだけでは、今その施策を選ぶ理由として十分ではありません。過去の失敗を踏まえて再挑戦するなら何を変えるのか、現在の目標に対してどの指標を動かすのかまでつながって、初めて実行候補になります。初版のスキルには、その判断に必要な文脈を確認する仕組みが不足していました。この経験が、過去施策の結果と足元の目標指標を確認する現在の形へ更新するきっかけになりました。 チームのエンジニアのアプローチ: アイデアの確からしさをAIで補強する 今回施策を提案したのは、長年アーカイブサイトのフロントエンド開発に携わっているチームメンバーです。 開発を通じて、過去にどのような施策を実施し、何がうまくいかなかったかを知っています。さらに、普段の開発やサービス利用の中で感じていた改善アイデアも持っていました。 今回は、そうした経験から生まれたアイデアを生成AIに入力し、関連する行動データや過去施策を調べてもらうことで、仮説の確からしさを補強しました。つまり、AIにゼロから施策を発明してもらうのではなく、自分の中にある仮説を検証し、企画として説明できる形へ整えるために使ったのです。 その中から2件が実施候補に選ばれました。どちらのA/Bテストでも、エンジニア提案のBパターンが既存パターンを上回り、採用されました。エンジニアのアイデアが提案で終わらず、検証と本実装まで進んだことは大きな成果でした。 結果の違いから見えたドメイン知識の価値 この結果だけで、データ起点のアプローチが悪く、アイデア起点のアプローチが常に正しいとは言えません。試した施策の性質や優先順位も異なるため、単純な比較はできないと思います。 それでも、今回の経験から強く感じたのは、生成AIは入力された情報を増幅する存在だということです。 チームのエンジニアが入力したのは、施策のアイデアだけではありません。その背景には、長年の開発で蓄積した次のような情報がありました。 ユーザーが画面上で迷いやすい箇所 過去に試した施策と、その成否だけでは表せない学び データやコードがその形になっている理由 実装コストや既存機能への影響に関する感覚 日々の開発で感じていた、小さな違和感や改善の余地 これらは、データベースやドキュメントを検索するだけでは、すべてを取得できるとは限りません。人の中にある経験知と、生成AIが集められるデータや実装情報が組み合わさったことで、提案の説得力が増したのだと思います。 生成AIによって、調査や資料化のコストは大きく下げられます。一方で、調べる対象や深掘りする違和感を選び、結果を業務の文脈で解釈するには、引き続きドメイン知識が必要です。 生成AIの急速な高度化に伴い、人間の業務を支援・代替する場面も増えています。私自身、これから人の役割はどう変わっていくのだろうと考えていました。 しかし、今回の2施策では、エンジニア提案のBパターンが既存パターンを上回りました。その結果を見て、ドメイン知識を持つ人の役割はまだまだ大きいと感じました。AIが十分なデータへアクセスできても、最初に渡す問いや仮説の質、その結果を業務の文脈で解釈する力によって、得られる成果は変わります。 人間にしか担えない領域はまだあります。生成AIが発達しても、担当するサービスや業務への理解を深める重要性は変わらないと思います。むしろ、生成AIが知識やアイデアを増幅できるようになったことで、入力となるドメイン知識の価値がさらに高まるのではないかと感じています。 次に取り組みたいこと 今回のスキルには、行動データ、ソースコード、計測仕様、過去の施策資料など、すでに言語化されている情報を参照できるようにしました。 次の課題は、人だけが持っている情報を、生成AIが利用しやすい形に整えることです。 たとえば、次のような情報を継続的に残せると、施策提案の質をさらに高められると考えています。 施策を実施した事実だけでなく、当時の仮説と判断理由 A/Bテストで勝った理由、負けた理由についての振り返り 見送った案と、見送った時点の制約 開発や問い合わせ対応で感じたユーザー体験上の違和感 サービス固有の用語、データの定義、実装上の制約 ただし、すべてを無制限にAIへ渡せばよいわけではありません。情報の公開範囲、個人情報や機密情報の取り扱い、古くなった知識の更新方法、AIが参照した根拠を追える状態も合わせて設計する必要があります。 最終的には、職種に関係なく、誰でも気軽に質の高い施策提案ができる状態を目指しています。人のアイデアと経験を起点に、生成AIが調査、検証、具体化を支援する。その積み重ねによって、企画担当者の負荷を分散するだけでなく、チーム全体でサービスを良くする文化につなげていきたいと思います。 最後に 今回の取り組みを通じて、生成AIが得意なことと、人が持つ知識の価値をあらためて考えることができました。 生成AIに施策案を作ってもらう際は、いきなり「改善案を出して」と依頼するのではなく、まずチームが持っている仮説や過去の経験を入力できないか考えてみると、結果が変わるかもしれません。 チームで生成AIを使った施策提案に取り組む方の参考になれば幸いです。最後まで読んでいただきありがとうございました! 最後に、LIFULLではともに挑戦していける仲間を募集しています。ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
はじめに こんにちは、LIFULLクリエイターの日運営委員の布川です。 6月26日、弊社の1, 2年目のエンジニアを中心とした「1, 2年目+αエンジニア交流会」が開催されました! はじめに 今回の交流会で目指したこと 部署を超えた先輩とのつながりをつくる 気軽に頼れる関係をつくる 当日の様子 みんなで盛り上がったチーム対抗クイズ大会 最後は再び自由歓談 その他、いただいた声から見えたこと おわりに 普段の業務では、同じ部署やプロジェクトのメンバーとのコミュニケーションが中心になりがちです。特に入社して間もないエンジニアの中には、次のように感じている方もいるのではないでしょうか。 「他部署にはどんなエンジニアがいるんだろう?」 「部署や年次を超えて、気軽に話せる人とのつながりをつくりたい」 「他のチームではどんな仕事の進め方をしているんだろう?」 そう思っていても、普段接点のない人と話す機会はなかなかありません。 そこでクリエイターの日運営委員会では、1, 2年目のエンジニアを中心に、年次が上の先輩エンジニアも自由に参加できる交流会を企画しました。本記事では、開催の目的や当日の様子、参加者のみなさんから寄せられた声をご紹介します。 今回の交流会で目指したこと 今回の交流会では、大きく2つのことを目標にしました。 部署を超えた先輩とのつながりをつくる 1つ目は、 普段の業務では接点のない他部署の先輩と交流し、多角的な視点を得るきっかけをつくること です。 同じエンジニアでも、所属する部署や担当するサービスによって、使っている技術や仕事の進め方、これまで歩んできたキャリアはさまざまです。 そうした先輩たちと話すことで、自分のチームだけでは得られない考え方に触れたり、新たなキャリアの選択肢を知ったりする機会になればと考えました。 気軽に頼れる関係をつくる もう1つは、 困ったときや相談したいときに、部署を超えてフラットに頼り合える関係をつくること です。 これまで接点のなかった相手に、いきなり相談したり、気軽に話しかけたりするのは少しハードルが高いものです。一方で、一度顔を合わせて話したことがある相手なら、そのハードルは少し下がるかもしれません。 そこで今回は、堅めの勉強会ではなく、自己紹介や食事、クイズなどを通して、まずはお互いを知り、自然に会話が生まれる場を目指しました。 そしてもちろん、おいしいご飯を食べることも大事な目的のひとつです。(笑) 当日の様子 当日は、参加者全員で簡単な自己紹介を行うところからスタートしました。 名前や所属に加えて、業務で使っている技術や最近のマイブームなどを紹介。お互いのことを少し知ったところで、食事を囲みながらのフリートークへ移りました。 1, 2年目のエンジニアを中心に、先輩エンジニアにも多数ご参加いただき、縦横のつながりを深める賑やかな時間となりました。 参加者の方々からも、 普段関わりがなかった、新卒の方や先輩エンジニアの方々とお話しできたことがとても良かったです。 2年目の先輩はもちろん、さらに上のベテランの方とも話せる機会があり、刺激になりました。 といった声をいただきました。 みんなで盛り上がったチーム対抗クイズ大会 交流が進んできたところで、1, 2年目のエンジニアでチームを組み、チーム対抗のクイズ大会を開催しました! 早押しや難問に一喜一憂 クイズは、チームで相談しながら答えを考えられる内容にしました。部署を超えた若手同士で一緒に盛り上がりながら、さらに距離を縮めるきっかけになりました。 アンケートでも、 クイズが盛り上がって楽しかった。前提知識が揃っていなくても仲良くなれるのがよかった。 早押しクイズで2年目の先輩方と仲良くなれた クイズイベントを若手のみに絞る判断、非常に良かったと思いました! と好評でした。 そして、優勝チームにはささやかな景品をプレゼント。 自社サービスの仕様からITトリビア、海外拠点のカルチャーやオフィスの豆知識まで幅広く出題される、エンジニア交流会らしい催しとなりました。 最後は再び自由歓談 クイズ大会の後は、再び自由歓談の時間です。 会話の弾む歓談タイム クイズの盛り上がりそのままに、若手からベテランまでエンジニアが入り交じり、わいわいと交流しました。 年次の高いエンジニアの方々もたくさんご参加いただいたおかげで、エンジニアのキャリアや仕事の進め方に関して有益な意見が得られました。 といった声もあり、時間いっぱいまで賑やかな歓談が続きました。 その他、いただいた声から見えたこと イベント後のアンケートでは、当日の企画についてだけでなく、今後の交流会につながるアイデアもいただきました。 たとえば、 グループに分かれた時、特定のテーマ(技術、キャリアなど)について話す時間があると、より深い交流ができるのではないかと思います。 という声がありました。 今回は「まずは知り合い、気軽に話せるようになること」を重視しましたが、次回はそこから一歩進んで、技術やキャリアなどのテーマをきっかけにより深く話せる機会を取り入れてもよさそうです。 また、 この会に限らず、業務コミュニケーションツールのアイコンを名札にできると交流がはかどりそうです というアイデアもいただきました。 普段見慣れているアイコンと実際の顔が結びつけば、イベント中に「あ、この人普段チャットでよく見かける人だ!」と話しかけるきっかけになります。イベント後のコミュニケーションにもつながりやすくなりそうです。 こうした声も、今後の交流の場づくりに活かしていければと思います。 おわりに 今回の交流会では、食事やクイズを楽しみながら、部署や年次を超えたさまざまな交流が生まれました。 イベントを企画したクリエイターの日運営委員会では、「創民祭」のような日々の業務を超えたテーマや創作に触れる機会を提供し、LIFULLの技術発信力を高めることを目的として活動しています。 www.lifull.blog www.lifull.blog 社内で交流の場を企画されているような方にとって、今回の取り組みや参加者の方々の声が少しでも参考になれば幸いです。 LIFULLではエンジニア同士のつながりや学び合いの機会を大切にしています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは、LIFULL HOME'Sのネイティブアプリケーション開発チームでエンジニアリングマネージャーをしている佐々木です。 前々回の記事 ではチームの業務知識をAIに構造化して渡すことで調査工数を削減した話を、 前回の記事 ではその技術設計(コンテキストレイヤ5層)について書きました。今回は マーケター9人で構成されるデジタルマーケティング(以下、デジマ)チーム に、AI業務基盤を導入したお話をしていきたいと思います。 課題:属人化60%、ツール散在、新人が自走できない デジマチーム(9人)は以下の課題を抱えていました。 属人化 : 全業務の60%が「個々のやり方に終始している」状態。見込み算出の方法も、KPIの計算式も、人の頭にしかない ツール散在 : BigQuery、Looker Studio、スプレッドシート、GAS、Gemini Gem、各媒体管理画面と、作業のたびに別のツールを開きます 引き継ぎコスト : 「売上」の定義がマーケットごとに7種類違う。新人が独力で正しい数字を出せるようになるまでに時間がかかる チームからの依頼は明確でした。「 属人化している数字管理・施策準備・報告業務を標準化して、担当者が判断と意思決定に集中できる状態を作りたい 」。 課題:属人化60%、ツール散在、新人が自走できない アプリケーションパッケージとの設計の違い 2ヵ月の開発ストーリー 初日:1日で骨格を作る(4/22) 最大の壁:KPI定義が7マーケットで全部違う BigQueryスキーマ97,000行問題(4/24) フィードバック→改善のサイクル(5月〜6月) AIが間違える問題との戦い 現在の構成:53スキル・4エージェント・7MCP 53スキルの「選び間違い」をどう防ぐか 具体例:「マーケットAの定例資料を作って」 セットアップ:スクリプトファイルをダブルクリックするだけ BigQueryにないデータの扱い ツール一本化:1つのチャット画面で全部やる 成果 学んだこと 1. 暗黙知の構造化が9割 2. 最初から完璧を目指さない 3. 出力品質はスキル設計で制御する 4. 利用者の要望は進化する まとめ アプリケーションパッケージとの設計の違い 前回の記事で紹介したネイティブアプリケーション(以下、アプリケーション)向けパッケージは「ソースコードを読んで仕様を答える」ものでした。今回はまったく違います。 観点 アプリケーションパッケージ デジマパッケージ 入力 ソースコード BigQuery・CSV・媒体データ 出力 調査結果の回答 レポート文書・Confluence投稿・TSVデータ 核 画面→コード対応マッピング KPI計算式の完全定義 利用者 PdM・デザイナー マーケター コードベース型は「読み取り専用」で答えを返すだけです。一方デジマパッケージは BigQueryからデータを取得し、計算し、レポートを整形し、Confluenceに投稿する ところまで一気通貫で行います。 2ヵ月の開発ストーリー 初日:1日で骨格を作る(4/22) チームから受け取った業務棚卸しシート(18業務・週42時間分)を分析し、「AI化可能な業務」を仕分けました。 ✅ 完全吸収可能: 6業務(週14時間) 🔶 部分的に吸収: 8業務(週20時間) ❌ 対面・判断系で不可: 4業務(週8時間) この分析をもとに、初日で39スキル・3エージェントの骨格を構築。 ただし、この時点のKPI定義はまだ「たたき版」でした。 最大の壁:KPI定義が7マーケットで全部違う 最初にぶつかった壁は、 「売上」の定義がマーケットごとに違う ことでした。 パターン 「売上」の計算方法 マーケットA〜D 実績テーブルの特定カラムを参照 マーケットE 固定単価 × 反響数 マーケットF 月次変動単価 × 件数(単価は毎月BigQueryから自動算出) マーケットG そもそもKPIの定義自体がほかと異なる 「今月の売上を教えて」と聞かれても、マーケットによって見るべきカラムや計算式が全然違います。これを知っているのはチーム内の特定のベテランだけでした。 ヒアリングを重ね、最終的に21,000字超のKPI定義ファイルに全マーケットの計算式・区分構造・按分ロジック・異常値判定基準を一元化しました。 これがこのパッケージの心臓部になっています。 BigQueryスキーマ97,000行問題(4/24) BigQueryのテーブル定義を自動生成したら97,000行になりました。うっかりこれをsteeringディレクトリ(AIが起動時に必ず読み込むファイル群)に配置したところ、 Kiro IDE が起動直後にコンテキストウィンドウの上限に達して動かなくなりました。コンテキストウィンドウが上限に達するとこういう挙動になるのか、という良い検証にはなりました。 解決策は 配置の分離 。スキーマ本体は参照用ディレクトリに移し、steeringにはテーブル名とデータソースの対応マッピングだけを置く。さらに月別に重複していたテーブル定義を統合し、全1,439カラムに日本語説明を追加して97,000行→約1,800行に圧縮。「全部steeringに入れる」のではなく「必要なときに必要な分だけ参照する」設計にしました。 フィードバック→改善のサイクル(5月〜6月) パッケージをチームに配布してからが本番でした。改善要望がスプレッドシートで管理され、2ヵ月で33件。チームメンバーが各自記載してくれています。 初期(5月下旬): 「金額をK表記にしないで」「課金率を追加して」— 出力の体裁 中期(6月上旬): 「定例資料を自動生成したい」「検収フローをガイドして」— 業務プロセスの自動化 最近(6月中旬): 「ワークフローを自動化したい」「時間トリガで自動実行したい」— パワーユーザー化 「使い方を覚える」段階から「もっとこうしたい」段階に変化していったのが印象的でした。 AIが間違える問題との戦い 特に印象的だったのは、プロジェクトリーダーからの指摘です。 媒体分析時にKPI定義ファイルで「反響=カラムA」と定義されているのに、別のカラムで出される事象が何度か発生。確認したところ「定義は読み込まれていたが、出力整形時に照合するステップを飛ばした」とのこと。 AIは定義を「知って」いても、出力時に「確認」しないことがある。これに対して、スキル内に「出力前に必ずKPI定義と照合するチェックステップ」を追加して解決しました。 AIの出力品質は、スキル設計で制御する 。 現在の構成:53スキル・4エージェント・7MCP 2ヵ月の改善を経た現時点でのパッケージ構成(まだ進化中)です。 カテゴリ スキル数 代表例 レポート・報告 9 着地見込報告書、週次定例資料、施策結果報告書 データ分析・異常検知 8 媒体別パフォーマンス、変動要因分析、異常値検出 予算・配分 8 予算消化ペース監視、配分提案、来期予算策定 クリエイティブ 6 疲弊検知、勝ちパターン抽出、コピー提案 施策・計画 8 施策概要書ドラフト、シミュレーション、開発依頼書 運用・ナレッジ 6 検収フロー案内、プライバシーポリシー対応フロー、重複チェック ストア改善(広告・最適化) 5 キーワード分析、入札調整提案、週次レポート Amplitude連携 1 ファネル分析、CVR深掘り 7つのMCPサーバ (BigQuery・Jira・Confluence・Google Ads・Amplitude・AFAD・ASA)を接続し、1つのチャット画面からすべて操作できます。 53スキルの「選び間違い」をどう防ぐか スキルが53個もあると、別の問題が出てきます。 ユーザーの質問に対して、間違ったスキルが選ばれる 問題です。 たとえば「レポート作って」と言われたとき、候補になるスキルが5つあります。 マーケット別定例資料 全体エグゼクティブサマリー 施策別進捗管理表 着地見込報告書 施策結果報告書 AIはdescription(スキルの説明文)だけでは適切なスキルを選べません。実際に定例資料を作りたかったのに着地見込報告書が生成されるケースがありました。 学術的にも、スキルが重複する環境ではルーティング精度が31〜44ポイント低下すると報告されています( SkillRouter )。 対策として、ルール定義ファイルに ルーティング優先度ルール を追加しました。 ### 週次レポート系 - 「定例」「定例資料」「マーケット別」→ マーケット別定例資料スキル - 「全体サマリー」「概況」→ 全体サマリースキル - 「施策の進捗」「ステータス」→ 施策進捗管理スキル - 「レポート作って」(曖昧)→ 用途を確認する質問を返す さらに各スキルのdescriptionに「Use when(このとき使う)/ Do NOT use when(このときは別のスキル)」を明記しています。あいまいな指示に対しては「どのレポートですか?」と確認を返すフォールバックルールも設けています。 スキルを増やすだけでは足りない。「選ばれ方」も設計する。 これはスキル数が30を超えたあたりから意識すべきポイントです。 具体例:「マーケットAの定例資料を作って」 最もインパクトが大きかった業務変革の1つが、週次定例資料の自動生成です。 Before 1. 月次レポート(自動生成)の数値を確認(5分) 2. そこから各自の着地見込を手動で作成(30分) 3. 内容を読み取り、週次の進捗比較・変動分析を行う(20分) 4. 定例資料としてコメントを成型(15分) 5. Confluenceの定例ページにコピー&ペースト&整形(10分) → 合計80〜90分、7マーケット分で週10時間超 After 「マーケットAの定例資料を作って」と入力。 AIがBigQueryからデータを取得し、KPI定義ファイルに従って按分計算を行います。先週差分を算出し、変動要因を分析し、所定のフォーマットで定例資料を出力します。所要時間は数分です。 セットアップ:スクリプトファイルをダブルクリックするだけ 非エンジニアのチームに配るにあたり、最もこだわったのはセットアップの簡易化です。 セットアップスクリプトをダブルクリック ブラウザが開いてGoogle認証(クリック1回) Jira/Confluenceのトークンを入力(コピー&ペースト2回) 完了。所要時間5分 内部では、BigQuery MCPの認証設定、MCP Toolboxのダウンロード、mcp.jsonの自動構成をすべて処理しています。「ターミナルを開いてください」は一度も言いません。 BigQueryにないデータの扱い すべてのデータがBigQueryにあるわけではありません。オークションインサイト(Google Ads管理画面からCSV出力)やASOキーワードデータなど、BigQuery外のデータも業務には必要です。 これらは専用のインポートディレクトリに「ダウンロードしたファイルをそのまま置く」だけで使えるようにしました。ファイル名の変更不要、フォーマット変換不要。 ツール一本化:1つのチャット画面で全部やる 以前は業務ごとに別のツールを行き来していました。 業務 Before After データ取得 BigQuery管理画面 or Looker Studio 「今月のCPAを教えて」 レポート作成 スプレッドシート + 手動計算 「定例資料作って」 報告書投稿 Confluenceを手動編集 「Confluenceに投稿して」 チケット起票 Jiraを手動操作 「開発依頼チケットを起票して」 競合分析 管理画面CSV + スプレッドシート 「オークション分析して」 広告データ確認 Google Ads管理画面 「アクティブなキャンペーン一覧を教えて」 すべて同じKiro IDEのチャット画面で完結します。 成果 チームのプロジェクトリーダーが効果試算を行ってくれました。結果、大幅な削減効果が見込まれています。 特に効果が大きかった業務は以下です。 業務 Before→After 月間削減 BigQueryデータ問い合わせ・SQL抽出 1.5h→0.25h(月10回) 12.5h クリエイティブ分析 2.0h→0.5h 6.0h Confluence/Jira投稿・整形 4.0h→1.0h 6.0h オークション分析 2.0h→0.5h 6.0h 定性的にも変化が起きています。 - SQLが書けないメンバーでもデータ確認が自走できるようになった - 新人のオンボーディングが早まった(KPI定義・業務フローを自習できる) - 単純作業から解放されて、判断・意思決定に時間を使えるようになった 学んだこと 1. 暗黙知の構造化が9割 技術的に一番難しかったのはAI実装ではなく、 チームの暗黙知をMarkdownに書き出すこと でした。特にKPI定義は、ベテランメンバーに何度もヒアリングして初めて正確に書けるものです。ここが不正確だとAIの出す数字が全部間違います。 2. 最初から完璧を目指さない 初日に39スキルの骨格を作りましたが、定義やルール、スキルのすべてがたたき版でした。利用者のフィードバックを元に磨き上げる前提で「60点で配布→改善→配布」を繰り返し、2ヵ月半で22回リリースしました。 3. 出力品質はスキル設計で制御する AIは定義を「知って」いても出力時に従わないことがある。スキル内にチェックステップを入れ、ルール定義ファイルに「⚠️ よくあるミス」を太字で書く。 AIの行動を信頼するのではなく、しくみで保証する。 4. 利用者の要望は進化する 「表記直して」から「時間トリガで自動実行したい」まで、使い込むほど要望が高度化する。これはツールが浸透している証拠であり、同時にパッケージが追い続けるべき目標を示してくれます。 まとめ 非エンジニアのチームにAI業務基盤を導入するために必要だったのは以下でした。 KPI定義の構造化 (21,000字のMarkdown。これが心臓部) BigQueryスキーマの配置設計 (steeringに入れたらコンテキスト爆発→参照用ディレクトリへ分離し、steeringにはテーブルマッピングだけ配置) セットアップスクリプトの自動化 (ダブルクリック1回で完了) フィードバックサイクル (2ヵ月半で22回リリースし、33件の要望に対応) 前回の記事ではコードベースパッケージの技術設計を紹介しましたが、今回は 「ビジネス知識をAIに教えて、チームの働き方を変える」 話でした。技術的な難易度よりも、人間のドメイン知識を正確に構造化することの方がはるかに難しく、そして効果が大きかったと感じています。 最後に、LIFULLではともに挑戦していける仲間を募集しています。ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
こんにちは、LIFULLでUXリサーチャーをしている小川です。 LIFULLは「RESEARCH Conference」の初回から継続してスポンサーを務めておりますが、今年はありがたいことに、スポンサー枠とは別にポスターセッションへの発表機会もいただくことができました。 2026年6月28日に開催された「 RESEARCH Conference 2026 」のテーマは「WEAVING」。このカンファレンスのテーマに合わせ、私たちは 「『眠れる資産』を『生きたユーザー』として呼び覚ます」 というタイトルで発表を行いました。当日使用したポスターの全体像は、こちらからご覧ください。 今回発表したのは、過去の調査データを眠らせたままにせず、日々の業務に活かすための「ユーザーライブラリ」という取り組みです。 インタビューデータと既存ユーザーセグメントを組み合わせ、生成AIを活用することで、開発現場のメンバーがいつでも手軽にリサーチデータを引き出せる仕組みをつくりました。 この記事では、限られた時間の中ではお伝えしきれなかった背景や、当日よくいただいたご質問について、少し深掘りして補足させてください。 当日話しきれなかったポスターの補足 補足1. なぜ「ユーザーライブラリ」に取り組んだのか? 私が所属するユーザーファースト推進グループは、全社横断でUXリサーチを行っている組織です。普段は開発チームからの依頼を受けて調査やレポート作成を行っています。 これまで数多くのインタビュー調査を行ってきましたが、集めた内容のすべてが調査レポートに活用されるわけではありません。しかし、それらは決して無駄なデータではなく、別の視点で見れば、新規調査が不要になるほど価値あるデータであるケースも多くあります。 このような 「今回の調査目的には不要でも、別の文脈では価値があるデータ」 を、担当リサーチャーしか辿り着けない状態のまま埋もれさせてしまうのは非常にもったいないと感じていました。 これらを個人の手元で眠らせるのではなく「開発メンバーが活用できる資産」へ生き返らせる。そんな組織のデータ活用に変化を起こすために、今回のプロジェクトを立ち上げました。 補足2. 定性データ管理のとりくみ 現在、定性データを以下の3つのデータソースとして整理し、役割を分けて運用しています。 調査レポートソース(NotebookLM) :過去の調査結果そのものを蓄積するデータソース。 インタビュー個票ソース(NotebookLM) :発話などの生データをそのまま参照するためのデータソース。 セグメント別対話AI(Gemini) :今回のポスターセッションで焦点を当てた、ユーザーセグメントにフォーカスを絞ったデータソース。 今回の試行錯誤のなかで「今の目的には合わないが、将来的に別の目的で活きる」と判断したデータソースもできました。そのデータソースは今も管理を続けています。 補足3. なぜ「Gemini」を選んだのか 当日「なぜ数ある生成AIの中からGeminiを選んだのですか?」というご質問も多くいただきました。 結論から言うと、ツールの純粋な性能云々というよりも、 「私たちの社内環境において最適解」 と判断したからです。ツールの選定にあたっては、以下の3つの観点を重視しました。 社内アクセス性 :開発メンバーやリサーチャーが日常業務で使いやすいツールであること。 カスタム指示の柔軟性 :チームの知見やプロンプトをAIに学習させやすいこと。 知識データの指定 :Googleドライブ等と連携し、既存のインプット資産を活用しやすいこと。 重要なのは特定のツールに依存することではなく、 「どうすれば社内のリサーチデータが活きた資産になるか」 という目的そのものです。どんなに優れたAIツールであっても、利用するために複雑な設定や申請が必要なものは最初に除外しました。 現在、私たちはGeminiで運用をしておりますが、同じようなアプローチはNotebookLMでも実現可能ですし、環境さえ整えば他のLLMツールでも同様の仕組みは十分に構築可能です。 補足4. 「確証バイアス」への対策 今回の発表において、参加者の方々から特に多くの共感の声をいただいたのが、解決策のなかでも『「都合の良いデータだけを見る」リスクの防止』に関する取り組みでした。 人はどうしても自分の仮説を後押ししてくれる「都合の良いデータ」ばかりに目が向いてしまいがちです(確証バイアス)。そうした思い込みや視野狭窄に陥るのを防ぐため、今回の仕組みでは、 あえて相反するファクトや関連するデータを一緒に提示する工夫 を入れました。 「一方向からの情報だけで満足せず、多面的に仮説をブラッシュアップしてもらいたい」という、私自身の強い気持ちから生まれた対策です。 おわりに まずは、当日のタイトなスケジュールのなか、私たちのポスターブースに足を運んでくださった皆さま、本当にありがとうございました! コアタイム以外でも熱心に議論が続き、多角的な視点でフィードバックをいただけたことは、私自身とても大きな学びとなりました。温かいコメントや鋭いご指摘のすべてが、今後の励みになります。皆さまからいただいたヒントを胸に、今後も取り組みをブラッシュアップしてまいります。 今回の発表を通じ、多くのチームが私たちと同じように「リサーチデータの活用」に頭を悩ませているのだと強く実感しました。またどこかのカンファレンスでお会いした際は、ぜひ情報交換をさせてください! 運営スタッフの皆さまにも心より感謝申し上げます。引き続き、リサーチデータを「眠らせない」ための工夫を現場で続けていきたいと思います。 LIFULLでは共に成長できるような仲間を募っています。よろしければこちらのページもご覧ください。 hrmos.co
こんにちは、LIFULL HOME'Sのネイティブアプリケーション開発チームでエンジニアリングマネージャーをしている佐々木です。 前回の記事 では、チームの業務知識をAIに構造化して渡すことで調査工数を80〜90%削減した話を書きました。その最後に「コンテキストレイヤー」という概念に触れました。企業のデータを束ね、ビジネスロジックを理解できる層をAIエージェントに供給する基盤のことです。 今回は、そのパッケージの技術設計について掘り下げます。作ったものをあらためてコンテキストレイヤーの視点で整理してみたら、5つのレイヤーにきれいに分解できたので、その構造に沿って説明していきたいと思います。 パッケージの全体像 レイヤー①:セマンティック — ドメイン知識の構造化 レイヤー②:メタデータ — 30リポジトリを25ファイルで表現する レイヤー③:リネージ — 画面名からコードへの追跡可能性 レイヤー④:ポリシー — 行動ルールと委譲構造 絶対ルール:メインはコードを読まない サブエージェントへのスキル情報の橋渡し 7体のサブエージェント 行動定義 > ロール設定 レイヤー⑤:トライバルナレッジ — 45個のスキル Progressive Disclosure(段階的開示) 目的単位での切り出し 複合スキルと依存関係 レイヤーを横断するしくみ:ナレッジキャッシュ 具体例:PdMが4リポジトリを横断して障害原因を特定した話 まとめ パッケージの全体像 まず構成要素を示します。 .kiro/ ├── steering/ … メインエージェントの行動ルール(5ファイル) ├── agents/ … サブエージェント定義(7体) └── skills/ … 質問パターンごとの手順定義(45個) docs/ … API仕様・画面マッピング・ドメイン知識 repos/ … ソースコード(6リポジトリ) メインエージェント(オーケストレーター)が質問を受け取り、スキルを参照して適切なサブエージェントに調査を委譲する。サブエージェントは独立したコンテキストでコードを読み、結果の要約だけをメインに返す。この構造を支えているのが「5層のコンテキストレイヤー」です。 レイヤー パッケージでの実装 役割 セマンティック docs/domain-knowledge.md 業務用語・分類体系の定義 メタデータ docs/bff/ , docs/backend-api/ API仕様の構造化 リネージ docs/screen-mapping.md 画面→コードの追跡可能性 ポリシー steering/delegation.md 行動ルール・制約・委譲手順 トライバルナレッジ skills/ (45個) 調査手順・暗黙のノウハウ 以下、各レイヤーの設計を詳しく見ていきます。 レイヤー①:セマンティック — ドメイン知識の構造化 docs/domain-knowledge.md には、LIFULL HOME'Sアプリケーション固有の業務用語と分類体系が定義されています。 たとえば「新築」には2種類あります。 新築分譲 : デベロッパーが直接販売。DB仕様書Aで管理 新築仲介 : 築1年以内・未入居だが仲介扱いの流通物件。DB仕様書Bで管理 この区別を知らないAIは「新築の物件詳細を教えて」と聞かれたとき、どちらのDBを見ればよいかわかりません。ドメイン知識がなければ調査が始められないのです。 物件種別コード(bukken_type)の分類体系、現行BFFと新BFF(未移行)の関係など、エンジニアの頭の中にしかなかった知識をMarkdownとして書き出しています。このレイヤーがあることで、AIは質問の文脈を正しく解釈できます。 レイヤー②:メタデータ — 30リポジトリを25ファイルで表現する LIFULL HOME'SアプリケーションのBFFはGitHub上に30のマイクロサービスリポジトリとして存在します。バックエンドAPIも39エンドポイントを持っています。これらをすべてパッケージに含めるとサイズが膨大になる上、AIのコンテキストも溢れます。 設計方針は「 アプリケーションが実際に利用しているエンドポイントの仕様だけを、Markdownとして抽出する 」です。 docs/ ├── bff.md … 全24エンドポイントのアーキテクチャ概要 ├── bff/ … 利用エンドポイントの詳細仕様(19ファイル) │ ├── search-common.md … 物件検索共通パラメータ・変換仕様 │ ├── detail-rent.md … 賃貸物件詳細のレスポンス構造 │ ├── detail-sale.md … 売買物件詳細 │ └── ... ├── backend-api.md … 全39エンドポイントの一覧 └── backend-api/ … 利用エンドポイントの詳細仕様(6ファイル) 30リポジトリのコードを丸ごと入れる代わりに、各エンドポイントの入力パラメータ・レスポンス構造・変換ロジックをドキュメント化しています。steeringの references.md にはこの docs/ へのルーティングだけを記述しています。「物件詳細のAPI仕様を聞かれたら docs/bff/detail-*.md を参照」という形でサブエージェントに渡します。 ソースコードを丸ごと含めるのは、UI実装を持つiOS / Android、Kotlin Multiplatform (KMP) による共通ロジック層、通知配信、DB仕様書2つの計6リポジトリだけ。この設計で190MBのzipに収まっています。 レイヤー③:リネージ — 画面名からコードへの追跡可能性 エンジニアに「物件詳細画面のコードどこ?」と聞けば即答できます。でもこの知識はエンジニアの頭の中にしかありませんでした。 これを screen-mapping.md として構造化しました。 | 画面名 | iOS | Android | |---|---|---| | 物件詳細 | (iOSの物件詳細ディレクトリ) | (Androidの物件詳細ディレクトリ) | | お気に入り一覧 | ... | ... | | 問い合わせ | ... | ... | | ... | ... | ... | 34画面について、各プラットフォームのディレクトリパスを対応付けています。iOS/Android間で共通化されたロジック層がある場合はその所在も記載し、サブエージェントが無駄に探索しないようにしています。 AIはこのマッピングを 調査の起点 として使います。「物件詳細画面の表示項目を教えて」と聞かれたら、まずここからパスを引き、それをサブエージェントへの指示に含めて並列起動する。マッピングがなければリポジトリ全体をgrepで探索することになり、検索に時間がかかる上、大量のファイルパス候補がコンテキストに載って肥大化します。マッピングを用意したことで、検索速度の向上とコンテキスト肥大化の抑制を同時に実現しています。 このマッピングは「完全な一覧」ではなく「調査の起点」と位置付けています。載っていない画面はリポジトリ内を検索して探しますし、それでも見つからなければ「見つかりませんでした」と正直に返します。 レイヤー④:ポリシー — 行動ルールと委譲構造 steering/delegation.md はパッケージの中で最も重要なファイルです。メインエージェントの行動を制御するポリシーレイヤーとして機能します。 絶対ルール:メインはコードを読まない 自分自身で readFile、readCode、grepSearch、readMultipleFiles を 使ってリポジトリ内のコードを読んではいけない。 このルールに例外はない。「ちょっと確認するだけ」「1ファイルだけ」も禁止。 データ取得(コード調査)→ 分析 → 回答生成を1つのエージェントのコンテキスト内で全部走らせると、取得したコードが積もった時点でコンテキストが枯渇し、分析・回答生成の品質が落ちます。調査はサブエージェントの独立コンテキストで行い、結果の要約だけをメインへ返す構造にすることで、メインのコンテキストをクリーンに保っています。 サブエージェントへのスキル情報の橋渡し Kiro IDE のサブエージェントには、スキルを読み込む手段がないという制約があります。steeringファイルはサブエージェントにも自動で注入されますが、スキル定義についてはCLI版のような resources フィールドが存在せず、サブエージェントに設定できません。つまり、サブエージェントはスキルの内容を直接参照できません。 重要 : サブエージェントはスキルを直接参照できない。スキルに記載された調査のヒント(具体的なファイルパス、定義箇所、調査観点など)は、サブエージェントへの指示(query)に必ず含めること。 この制約を解決するために、delegation.mdは委譲手順を5ステップで定義しています。 質問がどのリポジトリに関係するか判断する 質問の種類に応じたスキルを参照し、調査に必要な情報を把握する スキルから得た情報をサブエージェントへの指示に含めて 並列起動する 各サブエージェントの結果を統合して回答する 結果が不十分な場合は追加のサブエージェントを起動する メインエージェントはスキルの中身(ファイルパス・調査観点・注意事項)を読み取り、それをサブエージェントへの指示にそのまま含めて渡す。この「橋渡し」がdelegation.mdの核です。 7体のサブエージェント エージェント 役割 コードを読む? ios-investigator iOSアプリケーション調査 ✅ Android-investigator Androidアプリケーション調査 ✅ kmp-investigator KMP(iOS/Android共通ロジック)調査 ✅ db-investigator DBテーブル仕様調査 ✅ backend-investigator 通知配信ロジック調査 ✅ product-analyst 数値の分析・解釈 ❌ bq-data-fetcher BigQueryクエリ設計・実行 ❌ product-analyst と bq-data-fetcher は意図的に分離しています。 bq-data-fetcher は「クエリを書いて実行してデータを返す」だけの役割です。そのデータに意味を見出す(So What?を言う)のは product-analyst の仕事です。取得と分析を同一コンテキストに入れないことで、それぞれの品質を保っています。 行動定義 > ロール設定 各エージェント定義において、「あなたは最高峰のiOSエンジニアです」のようなロール設定は行っていません。LLMに対するペルソナ設定は性能向上に寄与しない( むしろ最大26.2%の劣化が報告されている )ことが研究で示されています。 代わりに、各エージェントには具体的な行動を定義しています。 何をするか : 対象リポジトリのsteering配下のファイルをすべて読み、最新のルールを把握する 何をしないか : コードの編集は一切行わない。書き込み系MCPツール使用禁止 完了条件 : 根拠となったファイルパスを必ず明示する あいまいなロール設定より、具体的な行動指示の方がAIは正確に従ってくれます。 レイヤー⑤:トライバルナレッジ — 45個のスキル skills/ ディレクトリには45個のスキルが格納されています。PdMから「こういうことを知りたい」とリクエストがあったものと、「この人ならこういうことができたら喜ぶだろうな」と先回りして追加したものの積み重ねです。 カテゴリ 数 例 仕様調査 17 画面の表示項目、ビジネスロジック、API仕様、画面遷移、計測イベント デザイナー支援 6 アクセシビリティチェック、実装可能性判定、アセット命名提案 データ分析 8 CVR・ファネル分析、レビュー傾向、A/Bテスト結果 統合分析 6 UX課題発見、KPI下落診断、競合比較、デザインと実装の差分 評価・意思決定支援 2 施策比較、優先順位付け ドキュメント・タスク管理 6 仕様書ドラフト、Jiraチケット起票、ナレッジ保存 Progressive Disclosure(段階的開示) Kiro IDEの スキル機能 は Agent Skills仕様 に基づいています。重要な特徴が段階的開示です。 セッション起動時にはスキルの フロントマター (名前・説明・トリガキーワード)だけが読み込まれる ユーザーの質問がトリガへマッチしたときに初めて 全文が展開 される 45個のスキルの全文を常時コンテキストに載せると、それだけでコンテキストの大部分を消費します。Progressive Disclosureにより、必要なスキルだけが必要なときに展開され、コンテキストが節約されます。 目的単位での切り出し スキルは「ステップ順」ではなく 「何を明らかにするか(目的)」 単位で切っています。 ❌ ステップ順: search-file → read-code → format-output ✅ 目的単位: comparing-screens / explaining-business-logic / diagnosing-kpi-drop 目的単位で切ると、再利用可能になり、各スキルに品質基準・完了条件・出力フォーマットを定義でき、複合スキルがほかのスキルを「呼び出す」構造を作れます。 複合スキルと依存関係 45個のスキルは独立して動くものと、ほかのスキルを内部で呼び出す「複合スキル」があります。delegation.mdに依存関係グラフが明記されています。 summarizing-screen ⊃ {comparing-screens, tracing-navigation, investigating-api, investigating-tealium, explaining-business-logic} drafting-specification ⊃ {comparing-screens, investigating-api, analyzing-change-impact, investigating-tealium} + investigating-web-site(任意) 「物件詳細画面の全体像を教えて」と聞くだけで、 summarizing-screen が5つの基本スキルを順に呼び出し、表示項目・画面遷移・API仕様・計測イベント・ビジネスロジックをまとめて返します。 レイヤーを横断するしくみ:ナレッジキャッシュ 5つのレイヤーは調査のたびに参照されますが、頻出する質問のたびに毎回サブエージェントを起動してコードを読むのは非効率です。そこで調査結果をConfluenceに蓄積し、2回目以降はキャッシュから即答するしくみを入れています。 フロー: 1. 調査系スキルの起動前に、Confluenceで [KB] 接頭辞のページを検索 2. ヒット → 鮮度チェック(キャッシュの最終更新日 ≥ パッケージの更新日時なら有効) 3. 有効ならサブエージェント起動なしで即答 4. 重い調査(サブエージェント3つ以上起動したもの)の完了後 → 保存を提案 リアルタイム数値を扱うデータ分析系スキルはキャッシュ対象外にしています。昨日のCVRと今日のCVRは違うからです。 具体例:PdMが4リポジトリを横断して障害原因を特定した話 5つのレイヤーが連携して機能した実例を紹介します。 ある日、「お気に入りに追加できない」というユーザー報告がありました。PdMがこのパッケージを使って調査した結果は以下でした。 ポリシー層 (delegation.md)が explaining-business-logic スキルを選択 トライバルナレッジ層 (スキル)が「お気に入り機能なら、共通ロジック層+iOS/Androidのキーチェイン/キーストア周りを見るべき」と指示 リネージ層 (screen-mapping)からお気に入り関連のパスを特定 3つのサブエージェントが並列起動(ios/Android/kmp-investigator) セマンティック層 のドメイン知識を踏まえて共通ロジック層内の該当箇所で kSecAttrAccessible 未設定を特定 原因判明:バックグラウンド復帰時にKeychainアクセスが失敗 → 毎日16,500件のエラーが発生していた エンジニアに依頼していたら、割り込み待ちも含めて数日かかってもおかしくない調査です。それが数分で完了しています。4リポジトリを横断して1行のコードまで特定できたのは、5層のコンテキストレイヤーが連携した結果です。 まとめ コードベースパッケージの技術設計は、突き詰めると「 AIが正しく答えるために必要なコンテキストを、いかに効率的に供給するか 」の設計です。 レイヤー 解決する問題 セマンティック AIが業務用語を誤解する メタデータ 30リポジトリを丸ごと含められない リネージ AIがどのファイルを見ればよいかわからない ポリシー AIが何をすべきか/すべきでないかを制御する トライバルナレッジ エンジニアの調査ノウハウを再現する 前回の記事で「コンテキストレイヤー」に言及したとき、それは振り返って気付いた概念でした。今回この記事を書くにあたり、あらためて自分のパッケージを5層で整理してみると、各レイヤーが明確な役割を持って連携していることがわかります。 この構造は特定のツールや言語に依存していません。実際に、同じ設計をベースに賃貸・流通チーム向けのパッケージ(18リポジトリ×13エージェント)も稼働しています。自分のチームでコンテキストレイヤーを構築する際の参考になれば幸いです。 次回は、このしくみをエンジニアのいないチームに応用して、業務効率化に取り組んだ話を書く予定です。 最後に、LIFULLではともに挑戦していける仲間を募集しています。ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
こんにちは! LIFULLでユーザーファーストを推進しているチームに所属している木住野(きしの)です。 職種はQAEですが、ユーザーにとっての"あらゆる品質"をより良くするため、UXリサーチャーのメンバーと共にビジョン実現に向けて動いています。 2026年6月28日開催の RESEARCH Conference 2026 に参加してきたので、 カンファレンスの様子や刺さったセッションについてご紹介いたします。 会場の様子 今回響いた2つのキーワード 共体験 - 一緒にやるから深くわかる モンスト海外展開のリサーチ:「そのまま出さない」判断はどう生まれたか 「LOCAL RESEARCH LAB 中津川」の立ち上げと産学官横断での街のアクティベーション 風の人・土の人 - 組織にリサーチを根付かせる 組織にリサーチを根付かせる、技術よりも大切な「土着」の視点 まとめ - 自チームとの重なり 終わりに 会場の様子 入口 ランチと過去5年のリサーチカンファレンスの歩みを振り返れるZINE 今回響いた2つのキーワード 2026年のテーマは「WEAVING(織る)」でした。 年々リサーチに求められることは多様で高度になり、一つの専門性や視点だけでは抱えきれなくなっています。この状況において、私たちは異なる特徴をもつ人や役割を「織る」ことに可能性があると考えました。 そのため、リサーチに関わる人たちの関係性に着目するセッションが多かったです。 複数のセッションを聴いた中で、特に印象に残ったのが「共体験」と「風の人・土の人」という2つのキーワードでした。 どちらも、支援者として組織に伴走し、リサーチの価値を届けようとしている自分たちのチームに深く通じるテーマです。 特に印象に残っている3セッションをご紹介します。 共体験 - 一緒にやるから深くわかる モンスト海外展開のリサーチ:「そのまま出さない」判断はどう生まれたか 登壇:島崎 顕北 氏・古藤 拓実 氏(株式会社MIXI) 島崎氏・古藤氏からは、モンストのグローバル版「STRIKE WORLD」の開発プロセスが語られました。 印象的だったのは、単なる翻訳ローカライズではなく「再構築」するという判断に至った経緯です。 14名の多様な立場のメンバーが現地に赴き、プレイテストを実施しました。 ここでのポイントは、リサーチャーだけが現地を見るのではなく、エンジニアやプロデューサーを含む全員で「その場の空気を共有する」ことを最優先にした設計だったという点です。 市場調査の数字からではなく、ともに体験したからこそ見えた発見がありました。たとえば「引っ張る動作が海外ユーザーには直感的に伝わらない」という想定外のインサイト。机上のデータ分析では到達しにくい気付きが、共体験によって生まれていたのです。 ステークホルダーと同じ体験をしたうえで目線を合わせながら開発へ反映していくプロセスは、「リサーチ結果をレポートで伝える」モデルとはまったく異なる説得力を持っていました。 「LOCAL RESEARCH LAB 中津川」の立ち上げと産学官横断での街のアクティベーション 登壇:牛丸 維人 氏(株式会社KESIKI)・吉澤 克哉 氏(東海旅客鉄道株式会社) もう一つ「共体験」の力を感じたのが、JR東海グループ × KESIKI × 岐阜県中津川市による協働プロジェクトです。 旧中山道の宿場町というフィールドで、地域内外の多様な参加者を「ラボメンバー」として募集し、コ・フィールドリサーチ(共同でのフィールドリサーチ)を実施。人類学・デザイン・まちづくりの知見を横断的に応用した「共創」がプロジェクトの核になっていました。 このセッションで特に響いたのは、「ともにリサーチすることで深い理解が生まれ、仲間になることでアイデアの実装につながる」というメッセージです。 リサーチの成果物がレポートではなく「関係性」であり、その関係性が具体的なアクションを生み出す。実際に多数のコミュニティが生まれ、まちづくりを支える動きが創出されていたそうです。 風の人・土の人 - 組織にリサーチを根付かせる 組織にリサーチを根付かせる、技術よりも大切な「土着」の視点 登壇:福島 麻衣 氏(株式会社Muture) 福島氏のセッションでは、デザイン会社として外からインサイトを持ち込む立場と、中で組織に伴走する立場の両方を経験してきた知見が語られました。 ここで紹介されたメタファが「風の人」と「土の人」です。 風の人 :異文化や革新的な技術を外部から導入する役割を担う存在 土の人 :地域や組織の特性を深く理解し、基盤を整える存在 新しいものへの感度が鋭いリサーチャーは、往々にして「風」の役割を持ちます。しかし風は土壌を理解しないと、持続的な変化をもたらせません。リサーチの技術やメソッドの前に、その組織固有の文化や慣習を深く理解し尊重することが土台になるという主張でした。 土の人を理解することで得られるものとして、以下の3つが挙げられていました。 価値を感じてもらいやすい方法がわかる 風を吹かせるタイミングが見える 信頼が生まれる セッションの後半では、実践している パターン・ランゲージ も紹介され、具体的な実践知として持ち帰れる内容でした。 まとめ - 自チームとの重なり 2つのテーマに通底していたのは、「関係性を築くことでリサーチの価値が生まれる」という考え方です。 私たちはインハウスのリサーチチームではありますが、横断部署として各事業部を支援する立場にいます。 つまり、新しいプロジェクトに入るときは「風」として入ることが多いです。 だからこそ、土の人を理解し、ともに体験するプロセスを丁寧に踏むことで、支援が一時的なもので終わらず組織に根付いていくことに繋がると思います。 またステークホルダーとのユーザー観察の共体験も実践している部分があるので重要性を再認識しました。 今回のカンファレンスで得た2つのキーワードは、自分たちのチームがこれから目指す方向をあらためて言語化してくれたように感じました。 明日からの支援の現場で、意識を変えて動いていこうと考えるきっかけになりました。 終わりに 今回 LIFULL はポスターセッションで登壇しました。 そのポスターの紹介は別記事で行う予定です。ご期待ください! LIFULLでは共に成長できるような仲間を募っています。 よろしければこちらのページもご覧ください。 hrmos.co
こんにちは、LIFULL HOME'Sのネイティブアプリ開発チームでエンジニアリングマネージャーをしている佐々木です。 「この画面、何が表示されてるか教えてもらえますか?」 目の前のタスクに集中しているときにSlackに飛んでくるこの一文で、エンジニアの手は止まります。悪気はない。でもチームのリードタイムは確実に伸びていく。 この問題を、AIに業務知識を構造化して渡すことで解消した話をします。 背景:人間が"コンテキストの運び屋"になっていた 試行錯誤:最初からこの形だったわけではない 何を作ったか:業務知識をパッケージ化する なぜ効いたか:3つの設計判断 ① 定義の集約:誰がいつ聞いても同じ答えが返る ② スキル化:「やりたいこと」を伝えるだけで手順が走る ③ ツール統合:分析もチケット起票も1箇所で完結 成果:「聞く側」も「聞かれる側」も変わった 余談:世界では「コンテキストレイヤー」と呼ばれているらしい まとめ 背景:人間が"コンテキストの運び屋"になっていた 私たちのチームでは、メイン施策を進めている最中に、次の施策のための質問・相談が頻繁に飛んできていました。 PdMから:「この画面の表示ロジックってどうなってる?」 デザイナーから:「この機能、実装上の制約ある?」「この表現はコード的に可能?」 マーケから:「この数値、どのイベントで計測されてる?」 エンジニアは手を止めてコードを読み、回答する。1往復30分〜数時間。これが毎日何回も発生していました。 問題はそれだけではありません。質問する側も「エンジニアの手を止めてしまう」という心理的ハードルを感じていて、遠慮して質問を溜め込む → まとめて聞く → 大量の回答待ちが発生する、という悪循環もありました。 本質は明確でした。 チームの業務知識が人の頭にしかなく、AIが参照できる形になっていなかった 。 試行錯誤:最初からこの形だったわけではない 前提として、利用者は非エンジニアです。GitHubアカウントを持っていない人がほとんどで、 git clone もターミナルも使えない。この制約の中で、どうやってコードベースの知識をAIに渡すか。 最初に試したのはGoogle GeminiのGem(カスタムAI)+ GitHub連携でした。でも連携した本人しか使えず、チームには共有できない。NotebookLMも同じ問題。 Repomix (コードを1ファイルに圧縮するツール)も試しましたが、ディレクトリ構造やファイル間の関係性が失われ、調査精度が出ませんでした。 結局たどり着いたのは「コードをそのまま同梱してzipで配る」という原始的な方法でした。全員が同じ環境を使えて、コードの構造もそのまま残る。「Googleドライブからダウンロード→解凍→フォルダを開く」だけで始められる。これが一番確実だった。 何を作ったか:業務知識をパッケージ化する 作ったのは、チームの業務知識を構造化してAIエージェントに渡す「パッケージ」です。zipを解凍して Kiro IDE (AIエージェント機能を内蔵したエディタ)で開き、日本語で質問するだけで使えます。 パッケージの中身は3層で構成されています。 steering(ルール・定義) : KPI定義、データソースの所在、業務上の制約 skills(手順・ナレッジ) : 分析の手順、レポート作成の方法、調査の進め方 agents(専門家) : コード調査担当、データ分析担当など、役割に特化したサブエージェント 3層構造の概念図 このしくみを、現在4チームに展開しています。 対象チーム 当初の課題 利用者 状態 ネイティブアプリ開発チーム 仕様調査でエンジニアの手が止まる PdM・企画・デザイナー ✅ 稼働中 デジタルマーケティングチーム 数値管理・レポートが手作業で属人的 マーケター ✅ 稼働中 アプリ広告運用(ASA/ASO)チーム 運用判断に専門知識が必要 企画・マーケター 🔶 一部利用 賃貸・流通領域チーム 仕様調査の横展開 PdM・企画・デザイナー 🔶 検証中 このほかにも試作段階のものがあり、少しずつ適用範囲を広げています。 このしくみの展開により、従来のコミュニケーションフローが大きく変わりました。 Before/Afterフロー比較 なぜ効いたか:3つの設計判断 ① 定義の集約:誰がいつ聞いても同じ答えが返る 「この指標の定義は?」「この計算式の出どころは?」。これまで人の頭にしかなかった情報を、Markdownファイルに一元管理しました。誰がいつ聞いても、AIが同じ定義に基づいて同じ答えを返します。属人化が構造的に解消されるしくみです。 ② スキル化:「やりたいこと」を伝えるだけで手順が走る 「着地見込を出して」と伝えるだけで、AIがデータ取得→計算→フォーマット整形まで実行します。利用者は「やりたいこと」を伝えるだけでよく、手順を知っている必要がありません。業務手順の暗黙知がスキルとして構造化されているからです。 ③ ツール統合:分析もチケット起票も1箇所で完結 BigQueryでの数値分析も、Jiraへのチケット起票も、Confluenceへの報告書投稿も、全部同じKiro IDEの中で完結します。「あの作業はスプレッドシート、この分析はGemini、あれはGoogle Apps Script」というツール跨ぎが消え、非エンジニアにとっての認知負荷が劇的に下がりました。 成果:「聞く側」も「聞かれる側」も変わった 利用者の一人である企画メンバーは、公式noteで以下のように書いてくれています。 以前は、「この仕様はどうなっていますか?」とエンジニアに確認を依頼し、その回答を待つまでに数時間〜1日ほどのリードタイムが発生していました。エンジニア側の作業を止めてしまうという心理的ハードルもありました。 しかし現在では、企画担当である私自らが調査パッケージを使い、5分〜10分程度でコードベースの一次調査を完結させています。コミュニケーションの往復が消えたことで、調査工数は約80〜90%削減され、施策検討のサイクルは圧倒的に加速しました。 — エンジニアから企画へ。LIFULL HOME'S アプリ部署で目撃した、AIシフトがもたらす「職種を越えた共創」 単に工数が減っただけではありません。「ここまで調べた結果、ここを変えれば実現できそうですが、どう思いますか?」という提案ベースの相談ができるようになったことで、意思決定の質も上がっています。 そしてエンジニア側は、調査依頼に中断されることなく、メイン施策の開発に集中できるようになりました。 余談:世界では「コンテキストレイヤー」と呼ばれているらしい ちなみに、2026年3月にa16z(米国の大手VC)が公開した記事「 Your Data Agents Need Context 」では、こう述べられています。 データ・分析エージェントは適切なコンテキストなしでは本質的に役に立たない。曖昧な質問を解きほぐすことも、ビジネス定義を解読することも、散在するデータを横断して推論することもできない。 同記事では、この問題の解決策として「企業のデータを束ね、ビジネスロジックを理解できる層をエージェントに供給する基盤」を「コンテキストレイヤー」と呼んでいます。振り返ると、私がやっていたことはまさにこれでした。 この記事を知ったのは後からです。現場の課題を解決していたら、同じ構造にたどり着いていました。 まとめ AIがどれだけ賢くなっても、チーム固有の業務知識を構造化して渡さなければ正しくは動きません。 大げさなプラットフォームがなくても、Markdownとスキル定義を整備してzipで配るだけで始められます。「人に聞く」を「AIに聞く」に変えるだけで、チームの循環は確実に変わります。 次回は、このしくみの技術的な設計と具体的なファイル構成について詳しく書く予定です。 最後に、LIFULLではともに挑戦し成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 https://hrmos.co/pages/LIFULL/jobs/010 https://hrmos.co/pages/LIFULL/jobs/010-9998
こんにちは、LIFULLでシニアエンジニア兼エンジニアマネージャーをしている渡邉です。普段はLIFULL HOME'Sの流通領域のエンジニアチームにて、マネジメントを担当しています。 最近のお気に入りはSupabaseです。 今回は、私たちが1年半にわたって磨き上げてきたGitHub完結型リリースフロー「Beezy」が、ついに弊社の一番メインのLIFULL HOME'Sシステム群に採用されたという大きなマイルストーンを迎えたことをご報告します。 これまでの歩み 🐝 「Beezy」という名前に込めた想い 名前の由来 なぜハチなのか なぜEasyなのか Beezyが目指すもの なぜメインシステム群への採用が重要なのか 本質的な課題は「スケールの壁」 Beezyが目指す3つの柱 1. 集約化:すべての情報をGitHubに 2. 自動化:人間の判断に頼らないしくみ 3. 加速化:価値をより早くユーザーへ Beezyの主要機能 承認フロー Issue駆動開発 リリースチェック 自動リリース リリース依存関係管理 Hotfixフロー 自動バージョンアップ 導入までの険しい道のり 最初の壁:既存フローへの愛着と不安 第二の壁:既存運用を損なわないための工夫 リリースカンバン機能の実装 リリース履歴ダッシュボードの作成 JIRAとの連携維持 第三の壁:技術的な課題の山積 1. 複数リポジトリ間の依存関係 2. 多様なリポジトリ形態への対応 3. 導入方法の簡略化 4. パフォーマンスの最適化 第四の壁:組織的な合意形成 ステークホルダーの多様性 合意形成のプロセス 1年半の成長の軌跡 フェーズ1:言語化とシステム化(最初の3ヵ月) フェーズ2:流通チームでの実証と汎用化(次の3ヵ月) フェーズ3:流通チーム以外への展開(次の6ヵ月) フェーズ4:メインシステム群への導入準備(次の6ヵ月) フェーズ5:メインシステム群への導入完了(現在) 導入を成功させた5つの要因 1. スモールスタートと段階的な展開 2. 早い段階での汎用化とリポジトリ分離 3. 複数マーケットでのテストマーケティング 4. 既存の運用を尊重する姿勢 5. 丁寧なサポート体制 組織全体への波及効果 開発者の声 今後の展望 さらなる進化に向けて まとめ これまでの歩み 私たちのリリースフロー改革の取り組みは、これまでに2回ブログで紹介してきました。 1本目の記事では、リリースフローをGitHubに集約し、自動化を図った初期の取り組みについてお伝えしました。 www.LIFULL.blog 2本目の記事では、その後の進化として、Chrome拡張機能の開発や自動リリース機能の実装など、さらなる改善について紹介しました。 www.LIFULL.blog そして今回、1年半のスモールスタートでの検証を経て、ついに弊社の一番メインのシステム群への採用が決定しました。 今回は導入までの行ってきたことを紹介させていただきます。 🐝 「Beezy」という名前に込めた想い 本格的な展開を前に、私たちはこのリリースフローシステムに「Beezy」という名前を付けました。 名前の由来 Beezy(ビージー)は、 Bee(ハチ)とEasy(楽)を組み合わせた造語 です。 なぜハチなのか ハチは自然界で 最も効率的で組織的な生き物 の一つです。巣の中では、それぞれのハチが明確な役割を持ち、無駄のない動きで協働しています。女王蜂、働き蜂、それぞれが自分の責務を果たすことで、巣全体が機能します。 このリリースフローも同じです。エンジニア、CodeOwner、G長(グループ長。開発チームの責任者)、PJ承認者(プロジェクト単位でリリース可否を判断する役割で、主に企画担当者が担う)、リリーサー(本番環境へのデプロイを実行する担当者)、企画担当者、デザイナー。 それぞれが自分の役割を果たし、GitHub上で一つの「巣」として機能します。 リポジトリごとにリリースに必要なactionsを適用していくことで、最終的に完璧なリリースパッケージが完成する。まさにハチの巣の構造そのものです。 また、ハチは 「集約」の象徴 でもあります。花から花粉を集め、一つの巣に集約し、蜂蜜という価値を生み出す。私たちも、 JIRAやSlack、Googleスプレッドシートに散らばっていた情報をGitHubという一つの巣に集約し、価値創造を加速させる基盤 を作りました。 なぜEasyなのか このリリースフローの最大の成果は、 「楽になった」 ことです。 リードタイムが最大60%短縮された という数字以上に、 承認者やリリーサーの心理的負担が劇的に軽減 されました。情報を探し回る手間、手作業でのチェック、見落としへの不安。これらがGitHub Actionsによる自動チェックで解消され、 人間は本当に必要な判断だけに集中できる ようになりました。 「Easy」は単なる「簡単」ではなく、 「気楽に、安心して」リリースできる状態 を意味しています。 Beezyが目指すもの Beezyは、 ハチのように効率的で組織的でありながら、誰もが気楽にリリースできる世界 を目指しています。 将来的にはリリーサーすら不要になる完全自動化を見据えながらも、今この瞬間、 チーム全員がリリースを「重荷」ではなく「日常」として扱えるようになること 。それがBeezyの願いです。 Busy(忙しい)ではなく、Beezy(ハチのように効率的で楽)なリリースを。 なぜメインシステム群への採用が重要なのか 本質的な課題は「スケールの壁」 私たちがBeezyを開発した当初、まずは小規模なシステムでスモールスタートを切りました。これは正しい判断でした。新しいしくみを導入する際には、リスクを最小化しながら検証を重ねることが重要だからです。 しかし、本質的な課題は「メインシステム群でこそ顕在化する」ということを、私たちは理解していました。 リリース頻度の高さ : メインシステムは日々多くの機能追加や改善が行われ、リリース頻度が圧倒的に高い 関係者の多さ : 開発者、企画担当者、デザイナー、リリーサーなど、多くのステークホルダーが関わる 承認プロセスの複雑さ : ビジネスへの影響が大きいため、承認プロセスも慎重にならざるを得ない 情報の分散 : JIRAとGitHubを行き来する手間、Slackでの確認など、情報が分散している つまり、メインシステム群でこそ、Beezyの真価が問われるのです。 Beezyが目指す3つの柱 Beezyの開発において、私たちが一貫して追求してきたのは以下の3つです。 1. 集約化:すべての情報をGitHubに 従来の課題 : リリースチケットはJIRA コードレビューはGitHub 承認依頼はSlack リリース履歴は別のツール 情報が分散していると、承認者やリリーサーは必要な情報を探すだけで多くの時間を費やしてしまいます。 Beezyのアプローチ : リリースに関わるすべての情報をGitHubのPRとIssueに集約 PR作成時に自動的に関連Issueが作成され、必要なタスクがすべて可視化 リリースカンバン機能により、GitHub上で進捗管理が完結 リリース履歴ダッシュボードで、過去のリリースも追跡可能 Before After 2. 自動化:人間の判断に頼らないしくみ 従来の課題 : 承認者は手動でチェックリストを確認 リリーサーは目視でリリース可否を判断 リリース忘れは人間の記憶に依存 Beezyのアプローチ : GitHub Actionsによる自動チェック 必要な承認がそろっているかを自動検証 リリース可能な条件を満たしたPRを自動検出 リリース忘れを防ぐ自動通知システム 自動リリース機能により、条件が整い次第リリーサーの介入なしでリリース 3. 加速化:価値をより早くユーザーへ 従来の課題 : リリースまでのリードタイムが長い 週2回程度のリリース頻度 承認からリリースまで数日かかることも Beezyのアプローチ : リードタイム中央値を最大60%短縮 1日2回のリリースが可能に 承認からリリースまで数時間に短縮 Beezyの主要機能 Beezyは、30以上のGitHub Actionsで構成された包括的なリリースフローシステムです。主要な機能を紹介します。 承認フロー LIFULLでは、本番環境へのリリース前に「G長承認(開発チーム責任者による技術的な承認)」と「PJ承認(企画担当者によるプロジェクト観点でのリリース可否判断)」という2段階の承認プロセスを設けています。これをGitHub上で完結させます。 G長承認・PJ承認のGitHub完結化 : PRのコメントで /G長承認OK 、 /PJ承認OK と書くだけで承認完了 適切な権限を持つ人のみが承認可能(GitHubチームで管理) Chrome拡張機能により、ボタン一つで承認コメントを投稿 自動承認スキップ : ドキュメントのみの変更など、プロダクトに影響のないファイルのみの変更は自動的に skip-release-check ラベルを付与 .dockerignore または .releasecheckignore でスキップ対象を定義可能 Issue駆動開発 SubIssueによるタスク管理 : PR作成時に、Epic IssueとSubIssueが自動生成 開発チェックシート、テスト仕様書、デザインチェックなど、必要なタスクを自動で分解 SubIssueの完了状況がPR上に進捗バーとして表示 すべてのSubIssueが完了すると、自動的に subissue-close ラベルを付与 リリースチェック ステージング確認・本番確認の自動化 : リリースPR上でチェックボックスをクリックするだけで確認完了 確認忘れを防ぐ自動通知機能 定時実行により、未確認のリリースを検出してSlack通知 自動リリース 条件が整い次第、自動的にリリース : ステージング確認・本番確認が完了したPRを自動検出 Googleカレンダーと連携してリリース可能日を判定 指定されたスケジュールで自動実行 リリース依存関係のチェックにより、順序を守ったリリースを実現 リリース依存関係管理 マイクロサービス間の依存関係を自動制御 : 設定ファイルで依存関係を定義 依存先のリリースが完了するまで、後続のリリースを自動的にブロック システム障害を防ぐための安全装置 Hotfixフロー 緊急リリースにも対応 : 通常のリリースフローとは別の、簡略化されたHotfixフロー Hotfix後のreverse merge PR(本番ブランチからdevelopへのPR)は自動承認 緊急時の対応をスムーズに 自動バージョンアップ メンテナンスの自動化 : Beezyのバージョンアップ時に、自動的にPRを作成 各リポジトリでの手動更新作業が不要 常に最新の機能とバグフィックスを利用可能 Beezy Flow 導入までの険しい道のり 最初の壁:既存フローへの愛着と不安 メインシステム群への導入を提案した際、最初に直面したのは「既存フローへの愛着」と「新しいフローへの不安」でした。 既存フローの強み : 長年の運用で培われた安定性 チーム全員が慣れ親しんだ手順 JIRAを中心とした統一的な管理 問題発生時の対応パターンが確立されている これらはけっして軽視できるものではありません。私たちは、この既存フローの良さを理解したうえで、Beezyを提案する必要がありました。 チームからの懸念 : 「GitHubに移行して、本当に大丈夫なのか?」 「企画担当者やデザイナーがGitHubを使えるようになるのか?」 「今までのリリース履歴はどうなるのか?」 「リリースカンバンでの進捗管理はどうするのか?」 「移行期間中、二重運用になって逆に負荷が増えるのでは?」 これらの懸念は、すべて正当なものでした。そして、私たちはこれらの懸念に一つ一つ真摯に向き合う必要がありました。 第二の壁:既存運用を損なわないための工夫 Beezyの開発で最も時間をかけたのが、「既存の運用を損なわない」ための機能開発でした。 リリースカンバン機能の実装 既存の運用 : JIRAのカンバンボードで、リリース予定のチケットを管理し、進捗を可視化していました。これは、リリーサーや企画担当者にとって、リリース状況を一目で把握できる重要なツールでした。 Beezyでの実現 : GitHub Projectsを活用したリリースカンバンの実装 PRの状態に応じて自動的にカードが移動 ラベルによる視覚的なステータス表示 フィルタリング機能により、特定の条件のPRのみを表示 試行錯誤の過程 : 最初は、GitHub Projectsの標準機能だけで実現しようとしましたが、既存のJIRAカンバンとの操作感の違いが大きく、ユーザーからの抵抗がありました。そこで、GitHub Actionsを使って、JIRAに近い操作感を実現するための自動化を追加しました。 リリース履歴ダッシュボードの作成 既存の運用 : 過去のリリース履歴を追跡し、「いつ、何がリリースされたか」を確認できることは、障害発生時の原因特定や、機能のリリース時期の確認に不可欠でした。 Beezyでの実現 : マージされたリリースPRの一覧表示 リリース日時、リリース内容、担当者などの情報を集約 検索・フィルタリング機能 各リリースに含まれる変更の詳細へのリンク 試行錯誤の過程 : 当初は、GitHubのリリース機能を使おうとしましたが、私たちの運用フローとは合いませんでした。そこで、GitHub APIを活用して、独自のダッシュボードを構築しました。これにより、既存の運用で必要だった情報をすべて提供できるようになりました。 JIRAとの連携維持 既存の運用 : すべてのプロジェクトがGitHubに移行できるわけではなく、一部のチームはJIRAでの管理を継続する必要がありました。 Beezyでの実現 : JIRAチケットとGitHub PRの相互リンク JIRAチケットの状態をGitHub上でも確認可能 段階的な移行をサポート これらの工夫により、「既存の運用を損なわない」という約束を守ることができました。 第三の壁:技術的な課題の山積 既存運用への配慮と並行して、技術的な課題にも取り組む必要がありました。 1. 複数リポジトリ間の依存関係 メインシステム群は、複数のマイクロサービスで構成されており、リリース順序に依存関係があります。 課題 : A→B→Cの順でリリースしなければならない場合、順序が逆転するとシステム障害につながります。 試行錯誤 : 最初は手動でのチェックを考えましたが、それでは自動化の意味がない 次に、依存関係を設定ファイルに記述する方式を試しましたが、メンテナンスが煩雑 最終的に、リリースブロック機能(release_block)を実装し、依存先のリリースが完了するまで後続のリリースを自動的にブロックするしくみを構築 実装のポイント : 依存関係を設定ファイルで定義することで、自動的にリリース順序を制御できるようになりました。 2. 多様なリポジトリ形態への対応 メインシステム群には、モノリス、マイクロサービス、フロントエンド/バックエンド分離など、多様な構成のリポジトリが存在します。 課題 : すべてのリポジトリ形態で同じ操作感を実現する必要がある。 試行錯誤 : 最初は個別にワークフローを作成していましたが、メンテナンス性が悪化 共通化を進めすぎると、柔軟性が失われる バランスを取るために、設定ファイルベースのアプローチを採用 実装のポイント : release_actions.config.yaml という設定ファイルを導入し、リポジトリごとに必要な機能を選択できるようにしました。 workflows : # G長承認とPJ承認をGitHub上で行う - id : approval_on_github enabled : true # 自動リリース機能 - id : auto_release enabled : true # Issue駆動開発 - id : issue_driven_development enabled : true inputs : ORGANIZATION : lifull REPOSITORY : your-repository-name PRODUCTION_BRANCH : main # その他、リポジトリごとの設定 この設定ファイルを用意した後、 renovate_actions ワークフローを実行することで、必要なワークフローファイルが自動生成されます。これにより、導入の手間を大幅に削減できました。 3. 導入方法の簡略化 課題 : 当初、対話形式のCLIツールを開発しましたが、以下の問題が発生しました: ローカル環境でのセットアップが必要 Node.jsのバージョン依存 チーム全員が同じ手順を踏む必要がある 試行錯誤 : CLIツールは便利でしたが、導入のハードルが高いという問題がありました。そこで、より簡単な方法を模索しました。 最終的な解決策 : release_actions.config.yaml と renovate_actions ワークフローを組み合わせた方式に変更しました。 導入手順 : テンプレートから release_actions.config.yaml と release_actions_renovate_actions.yaml をコピー release_actions.config.yaml を編集して、必要な機能を有効化 GitHubのActions画面から renovate_actions ワークフローを手動実行 自動的にPRが作成され、必要なワークフローファイルがすべて生成される この方式により、ローカル環境のセットアップが不要になり、導入のハードルが大幅に下がりました。 4. パフォーマンスの最適化 メインシステム群では、1日に数十件のPRが作成されることもあります。 課題 : GitHub Actionsの実行回数が増えると、コストとパフォーマンスの問題が発生します。 試行錯誤 : 不要なワークフローの実行を減らすためのフィルタリング キャッシュの活用 並列実行の最適化 実装のポイント : 変更されたファイルに応じてワークフローをスキップするしくみを導入しました。これにより、ドキュメントのみの変更では、重いチェック処理をスキップできるようになりました。 第四の壁:組織的な合意形成 技術的な課題以上に難しかったのが、組織的な合意形成でした。 ステークホルダーの多様性 開発者 : 新しいツールへの学習コスト、既存の開発フローの変更 企画担当者 : GitHubアカウントの作成、新しい承認フローへの適応 リリーサー : 役割の変化への不安、新しいツールの習得 マネジメント層 : 移行リスクへの懸念、投資対効果の検証 合意形成のプロセス 1. 小規模チームでの実証(3ヵ月) : 協力的なチームで実証実験を実施 週次で振り返りを行い、問題点を洗い出し フィードバックをもとに機能改善 2. 成果の可視化(6ヵ月) : リードタイムやリリース頻度の改善を数値で示す 開発者、企画担当者、リリーサーそれぞれの声を収集 定量的・定性的な成果をレポートにまとめる 3. 段階的な展開計画の策定(3ヵ月) : 一気に移行するのではなく、段階的な計画を提示 リスクの高いシステムは後回しにする 移行期間中のサポート体制を明確化 4. 充実したサポート体制の構築(継続) : 詳細なドキュメントの整備 ハンズオンセッションの定期開催 Slackチャンネル(リリースフローに関するすべての窓口)でのリアルタイムサポート Chrome拡張機能による操作の簡略化 特に重要だったのは、「既存の運用を尊重する」という姿勢を明確に示すことでした。リリースカンバンやリリース履歴ダッシュボードの実装は、この姿勢を具体的な形で示すものでした。 1年半の成長の軌跡 Beezyの開発は、決して一直線ではありませんでした。多くの失敗と学びを経て、現在の形にいたっています。 タイムライン フェーズ1:言語化とシステム化(最初の3ヵ月) 目標 : 現在のリリースフローの構成要素を言語化し、システム化する 取り組み : このフェーズでは、とにかく既存のリリースフローを徹底的に分解し、理解することに注力しました。 既存のリリースフローの各ステップを洗い出し それぞれのステップの目的と必要性を言語化 一つのリポジトリを対象に、大量のワークフローを作成 少しずつ検証を進めながら、システム化の可能性を探る 直面した課題 : 暗黙知として存在していたルールの発見 「なぜこの手順が必要なのか」を理解すること GitHub Actionsでどこまで実現できるかの見極め ワークフローの数が増えすぎて管理が煩雑に 学んだこと : リリースフローは想像以上に複雑で、多くの暗黙知が存在する すべてを一度に自動化しようとすると失敗する 小さく検証を重ねることの重要性 ワークフローの整理と構造化の必要性 この3ヵ月は、地味で泥臭い作業の連続でした。しかし、この期間に得た理解が、その後の開発の基盤となりました。 フェーズ2:流通チームでの実証と汎用化(次の3ヵ月) 目標 : 実際のチームで使ってもらい、汎用化する 取り組み : 私の所属する流通チームの企画担当者とエンジニアに説明し、マイクロサービスの1リポジトリで導入させてもらうことを握りました。 流通チームの企画担当者とエンジニアへの説明会を実施 マイクロサービスの1リポジトリで導入 実際に使ってもらいながら、フィードバックを収集 機能開発とユーザビリティ改善を並行して実施 汎用化への挑戦 : このタイミングで、ほかの流通リポジトリにも導入するつもりだったので、まずは今の1リポジトリに作ったワークフローをcomposite actionsとして汎用化することに全力を尽くしました。 個別のワークフローをcomposite actionsに分解 共通部分と個別部分を明確に分離 設定ファイルによるカスタマイズのしくみを構築 composite actions用の専用リポジトリを作成し、移設 この専用リポジトリの作成が、後の展開において非常に重要な役割を果たすことになります。 他の流通リポジトリへの展開 : 汎用化ができ次第、ほかの流通リポジトリでも検証を開始し、効果を検証しました。 直面した課題 : 企画担当者のGitHub習熟度のばらつき リポジトリごとの微妙な運用の違い composite actionsの設計の難しさ ドキュメントの不足 学んだこと : 実際のユーザーからのフィードバックの価値は計りしれない 汎用化は想像以上に難しい 「使いやすさ」は技術的な正しさとは別の次元 ドキュメントとサポート体制の重要性 早い段階での汎用化とリポジトリ分離が、後の展開を容易にする この期間で、Beezyは「動くもの」から「使えるもの」へと進化しました。 フェーズ3:流通チーム以外への展開(次の6ヵ月) 目標 : 流通以外のチームでも使ってもらい、効果を確固たるものにする 取り組み : 機能改善も行いながら、マイクロサービスを運用しているほかのチームに、流通での結果をもとに導入の相談を持ちかけました。 流通チームでの成果をレポートにまとめる ほかのチームへのプレゼンテーションと導入相談 導入サポートを丁寧に実施 実際に使ってもらってアンケートを実施 改善の数字を確固たるものに テストマーケティングの効果 : 社内のさまざまなチームで先にテストマーケティングさせてもらっていたことが、後のメインリポジトリ導入において非常に大きな意味を持つことになります。 成果の可視化 : リリース頻度の向上 リードタイムの短縮 リリーサーの作業時間の削減 開発者、企画担当者、リリーサーそれぞれの満足度 直面した課題 : チームごとの運用の違いへの対応 「流通でうまくいったから」だけでは説得力が不足 導入サポートの負荷 機能改善と導入サポートの両立 学んだこと : 数字で示すことの重要性 定量的な成果だけでなく、定性的な声も重要 導入サポートは想像以上に時間がかかる 異なるチームでの成功事例が説得力を生む 複数のマーケットでの実績が、組織全体への認知度を高める この期間で、Beezyは「流通チームのツール」から「複数チームで使えるツール」へと進化しました。そして、メインシステム群への導入に向けた確信を得ることができました。 フェーズ4:メインシステム群への導入準備(次の6ヵ月) 目標 : LIFULL HOME'Sのメインリポジトリ群への導入を実現する 取り組み : いよいよLIFULL HOME'Sのメインリポジトリ群への導入相談と調整を開始しました。 組織的な調整 : ものづくり全体への導入相談 予算の確保 ステークホルダーとの合意形成 移行計画の策定 認知度の高さが後押し : いろんなマーケットで先にテストマーケティングさせてもらっていたので、いざメインリポジトリに導入するとなった時にも、多くの関係者はBeezyについて知ってくれていました。これは非常に大きなアドバンテージでした。 「あのリリースフローのことね」という認識がすでにあった 成功事例を知っている人が多かった 「使ったことがある」という人が組織内に点在していた 新しいツールへの抵抗感が大幅に軽減された 課題解決への注力 : とにかく課題解決に時間を費やして粛々と準備を進めました。 リリースカンバン機能の実装 リリース履歴ダッシュボードの作成 JIRAとの連携維持 複数リポジトリ間の依存関係管理 パフォーマンスの最適化 運用上の問題への対策 : 運用上の問題が発生しないように、ドキュメントの充実と告知もしっかり行いました。 詳細なドキュメントの整備 企画担当者向けガイドの作成 ハンズオンセッションの実施 Slackチャンネルでのサポート体制の構築 Chrome拡張機能の開発 直面した課題 : メインシステム群特有の複雑さ 既存フローへの愛着と新しいフローへの不安 多様なステークホルダーとの調整 移行リスクへの懸念 学んだこと : 大規模な変更には、技術以上に組織的な調整が重要 既存の運用を尊重する姿勢を示すことの重要性 丁寧な準備が成功の鍵 予算確保には明確な効果の提示が必要 事前の認知度が、導入のハードルを大きく下げる この期間は、技術的な開発よりも、組織的な調整と準備に多くの時間を費やしました。しかし、この準備があったからこそ、スムーズな導入が実現できました。 フェーズ5:メインシステム群への導入完了(現在) 目標 : メインシステム群への導入を完了させる 取り組み : 準備が整い、いよいよメインシステム群への導入を開始しました。 段階的な導入計画の実行 リアルタイムでのサポート 問題発生時の迅速な対応 継続的なフィードバックの収集と改善 成果 : そして今、メインリポジトリへの導入が完了しました。 品質の向上 : 人的ミスの完全排除 リリース品質の安定化 直面した課題 : 導入初期の混乱 予期しないエッジケース ユーザーの習慣を変えることの難しさ 学んだこと : 1年半の準備があっても、導入時には予期しない問題が発生する リアルタイムでのサポート体制の重要性 継続的な改善の必要性 成功は一つのマイルストーンであり、ゴールではない 導入を成功させた5つの要因 1年半の道のりを振り返ると、メインシステム群への導入を成功させた要因は、以下の5つだと考えています。 1. スモールスタートと段階的な展開 一気に大規模な変更を行うのではなく、小さく始めて段階的に展開したことが成功の鍵でした。 最初の3ヵ月: 1リポジトリでの検証 次の3ヵ月: 流通チーム内での展開 次の6ヵ月: 流通チーム以外への展開 次の6ヵ月: メインシステム群への導入準備 各段階で学びを得て、次の段階に活かすことができました。 2. 早い段階での汎用化とリポジトリ分離 フェーズ2の段階で、composite actions用の専用リポジトリを作成し、ワークフローを移設したことが、後の展開を大きく容易にしました。 メリット : 複数のリポジトリで同じアクションを使える バージョン管理が容易 機能追加や修正が一ヵ所で完結 導入リポジトリ側のメンテナンスコストが低い この判断により、ほかのチームへの展開やメインシステム群への導入が、スムーズに進みました。 3. 複数マーケットでのテストマーケティング いろんなマーケット(チーム)で先にテストマーケティングさせてもらっていたことが、メインリポジトリ導入において非常に大きな意味を持ちました。 効果 : 組織内での認知度が高まった 「使ったことがある」という人が点在していた 成功事例を知っている人が多かった 新しいツールへの抵抗感が大幅に軽減された いざメインリポジトリに導入するとなった時にも、多くの関係者はBeezyについて知ってくれていました。これは、説明コストを大幅に削減し、導入のハードルを下げる大きな要因となりました。 4. 既存の運用を尊重する姿勢 新しいシステムを導入する際、既存の運用を否定するのではなく、尊重する姿勢を貫きました。 リリースカンバン機能の実装 リリース履歴ダッシュボードの作成 JIRAとの連携維持 これらの機能は、技術的には必須ではありませんでしたが、ユーザーの信頼を得るために不可欠でした。 5. 丁寧なサポート体制 技術的に優れたシステムでも、サポートがなければ使われません。 詳細なドキュメント 企画担当者向けガイド ハンズオンセッション Slackチャンネルでのリアルタイムサポート Chrome拡張機能 特に、企画担当者向けガイドとChrome拡張機能は、技術者以外のユーザーにとって大きな助けとなりました。 組織全体への波及効果 メインシステム群での成功は、組織全体に波及効果をもたらしています。 ほかのチームへの展開 : 成功事例を見たほかのチームからも導入希望が相次いでいる ベストプラクティスの共有 : Slackチャンネルを通じた知見の共有 継続的な改善 : ユーザーフィードバックをもとにした機能追加や改善 開発者の声 開発者からの声 : 「ボタン一つで承認が終わるなんて!」 「タスクの進捗が自動で更新されるから楽」 「リリース忘れがなくなった」 「リリーサーを待つ必要がなくなった!」 企画担当者からの声 : 「GitHubは難しいと思っていたけど、ガイドがあるから安心」 「Chrome拡張機能のおかげで、承認が簡単になった」 「リリース状況が一目で分かるようになった」 リリーサーからの声 : 「定型作業から解放されて、より重要な仕事に集中できる」 「自動リリース機能のおかげで、リリース日の緊張感が減った」 「リリース履歴ダッシュボードで、過去のリリースも簡単に追跡できる」 今後の展望 さらなる進化に向けて メインシステム群への採用は、ゴールではなくマイルストーンです。私たちは今後も、以下の方向性で進化を続けていきます。 1. より多くのチームへの展開 : 全社的な展開 グループ会社も含んだLIFULLグループ全体への導入 2. 機能の継続的な改善 : ユーザーフィードバックをもとにした改善 新しい技術の導入 パフォーマンスの最適化 3. Developer Experienceのさらなる向上 : より直感的なUI/UX ドキュメントの充実 サポート体制の強化 まとめ 1年半のスモールスタートを経て、ついにメインシステム群への採用を実現できたことは、私たちにとって大きな達成感をもたらしています。 しかし、それ以上に重要なのは、この取り組みを通じて得られた「組織の変化」です。 技術者が創造的な仕事に集中できる環境 心理的安全性の向上 チームの幸福度の向上 これらは、単なる効率化では得られない、本質的な価値です。 私たちは「価値創造を加速させ続ける」ことをビジョンの一部に掲げています。今回のメインシステム群への採用は、そのビジョンに向けた大きな一歩だと確信しています。 「仕方がない」と思っているポイントこそ、変化の余地があるかもしれません。開発フローにおけるそれぞれの構成要素をあらためて見直し、最低要件を確認してみることで思わぬ改善の糸口が見つかる可能性があります。 今後も一歩ずつ改善を積み上げることで、リリースのさらなる加速化につなげていければと思います。 最後に、LIFULL ではともに挑戦し成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 https://hrmos.co/pages/LIFULL/jobs/010 https://hrmos.co/pages/LIFULL/jobs/010-9998
こんにちは、LIFULLの渡邉です。シニアエンジニア兼エンジニアマネージャー(EM)として、普段はLIFULL HOME'Sの流通領域のエンジニアチームにてマネジメントを担当しています。日々チームの開発生産性やDeveloper Experience(DX)の向上に取り組んでいます。 今回は、長年スプレッドシートで管理されてきた「開発チェックシート」を、GitHubリポジトリ + GitHub Sub Issues + GitHub Actionsで再構築した話をお伝えします。スプレッドシートで管理している運用ドキュメントをGitHubに移行するひとつのサンプルケースとして紹介させていただきます。 課題の背景と目的 開発チェックシートとは スプレッドシート運用の限界 具体的なアプローチ 設計方針:既存のフローを壊さない 技術選定 エンジニアが実際にやること Markdownで管理する意味 AI時代の開発プロセスとの融合 MarkdownのAI親和性 各プロセスへの導入 MCP化による情報アクセスの容易化 直面した壁と乗り越え方 合意形成と移行の進め方 GitHub Sub Issuesの制約 成果と今後の展望 得られた成果 今後の展望 まとめ 課題の背景と目的 開発チェックシートとは LIFULL HOME'Sの開発では、以下のようなプロセスで開発が進行します。 実装 → 実装レビュー → テスト仕様書作成 → テスト仕様書レビュー → テスト この実装前、もしくは実装後に「開発チェックシート」を複製してチェックする工程があります。過去に発生した障害やバグを事前に検知するためのもので、組織の学びが蓄積されたナレッジそのものです。 スプレッドシート運用の限界 従来はGoogleスプレッドシートでマスタを管理し、開発案件ごとに複製 → チェック → レビューという流れで運用していました。この運用自体は機能していましたが、いくつかの課題が顕在化していました。 マスタ情報の所在があいまい : 「最新版はどれ?」とスプレッドシートを探す手間が発生する AI活用との親和性が低い : スプレッドシートのデータ構造はLLMに読ませるには不向き 開発プロセスとの統合が困難 : チェックシートの確認が開発フローから切り離された「別作業」になりがち 本質的な課題は、チェックシートの情報が開発のコンテキストから分離していることでした。 具体的なアプローチ 設計方針:既存のフローを壊さない 重要だったのは、「スプレッドシートを複製 → チェック → レビュー」という既存の運用フローを崩さないことです。運用が定着しているプロセスを無理に変えると、チームの認知負荷が上がり、結果的に誰も使わなくなります。 そこで、以下の方針で設計しました。 既存の「複製 → チェック → レビュー」のフローはそのまま維持する ツールとフォーマットだけを、よりエンジニアリングに適した形へ置き換える 技術選定 従来 新 役割 スプレッドシート(マスタ) GitHubリポジトリのMarkdownファイル(mainブランチ) チェック項目の原本管理 スプレッドシートの複製 Issue Templateからepic issueを作成 案件ごとのチェックシート作成 各シートに記入 epic issueでのチェックをトリガにsub-issueが自動生成 詳細チェック項目の展開 手動チェック&レビュー 各sub-issue上でのチェック&レビュー チェック・承認フロー ─ GitHub Actions 自動化・AI連携 スプレッドシートの「複製」に相当するのが、Issue Templateからのepic issue作成です。epic issueで該当する項目にチェックを入れると、GitHub Actionsがそれをトリガに詳細なチェックリストを持つsub-issueを自動生成します。開発者は生成されたsub-issue上で一つ一つチェックを進めていく流れです。 エンジニアが実際にやること 全体の流れを図にすると以下のようになります。 sequenceDiagram participant 開発者 participant GitHub participant レビュアー 開発者->>GitHub: Issue Templateからテンプレート選択 開発者->>GitHub: 施策情報入力&該当項目にチェック GitHub-->>GitHub: sub-issue自動生成 開発者->>GitHub: 各sub-issueのチェックリストを埋める 開発者->>GitHub: 必要に応じてコメント記載 開発者->>レビュアー: レビュー依頼 レビュアー->>GitHub: epic issue・各sub-issueを確認 レビュアー->>GitHub: 親issueにレビューOKコメント レビュアー->>GitHub: 親issueをclose GitHub-->>GitHub: 全sub-issue自動close 具体的な手順は以下の通りです。 1. 新規チェックシートの作成 リポジトリの「New Issue」から対象のテンプレートを選択 施策名・実装者・対象リポジトリを入力 該当するチェック項目にチェックを入れてIssueを作成 チェックした項目に対応するsub-issueがGitHub Actionsにより自動生成されます。 2. チェックの実施 自動生成された各sub-issueのチェックリストを確認し、該当/非該当をチェック 必要に応じてコメント欄に対応内容や対応不要の理由を記載 3. レビュー & 完了 レビュアーが各sub-issueと親issue(epic)の内容を確認 問題なければ親issueにレビューOKのコメントを記載 親issueをclose → 全sub-issueが自動でcloseされる スプレッドシート時代の「複製 → チェック → レビュー」という流れがそのまま「Issue作成 → チェック → レビュー&close」に置き換わっている点がポイントです。 Markdownで管理する意味 チェック項目をMarkdown形式でリポジトリに格納したことで、以下の利点が生まれました。 Single Source of Truth : mainブランチが常に最新のマスタ。探す必要がない 変更履歴の追跡 : Git履歴で「いつ、なぜ、誰が」項目を追加・修正したかが明確 Pull Requestによる更新プロセス : チェック項目自体の追加・変更もレビューを経て反映される AI時代の開発プロセスとの融合 今回の移行で最も大きなインパクトがあったのは、AI活用との親和性の向上です。 MarkdownのAI親和性 スプレッドシートのデータをLLMに読ませる場合、セル構造の解釈やフォーマットの揺れに精度が左右されます。一方、Markdownは構造化テキストとして最もLLMが正確に理解できるフォーマットのひとつです。 この特性を活かし、開発プロセスの随所にチェックシートの知見を組み込めるようになりました。 各プロセスへの導入 [実装] → [実装レビュー] → [テスト仕様書作成] → [テスト仕様書レビュー] → [テスト] ↑ ↑ ↑ ↑ AI支援 AI支援 AI支援 AI支援 (チェック項目を (チェック項目を (チェック項目を (チェック項目を プロンプトに含む) レビュー基準に含む) 仕様に反映) 確認基準に含む) 具体的には以下のようなことが可能になりました。 実装時 : チェックリストの情報をプロンプトに含めることで、AIが「そもそも既知の障害パターンを回避する実装」を提案してくれる レビュー時 : レビュアー(人・AI問わず)がチェック項目を基準として参照できる GitHub ActionsによるAI自動レビュー : PR作成時に自動でチェック項目との整合性を検証 従来は「実装が終わってからチェックシートで確認」という事後確認型でしたが、開発プロセス全体に予防的にチェックの知見を浸透させることが可能になりました。手戻りが減り、生産性を最大化する方向に大きく前進したと感じています。 MCP化による情報アクセスの容易化 さらに、チェックシートの情報をMCP(Model Context Protocol)サーバとして提供することで、開発者がAIアシスタントを通じて自然言語でチェック項目を参照できる環境を整備しました。「この実装でセキュリティ面において気を付けることある?」と聞けば、関連するチェック項目が返ってくるイメージです。 直面した壁と乗り越え方 合意形成と移行の進め方 移行にあたっては、事前にエンジニアチャンネルで構想を共有し、関係各所との合意形成を行いました。肯定的な意見が多く集まり、スムーズに推進できました。 実際の移行では、以下を心がけました。 移行期間中は旧スプレッドシートも並行稼働 「まず1案件だけ新フローで試す」スモールスタート メンバーからのフィードバックを即座にマスタへ反映し、「自分たちが育てているチェックリスト」という当事者意識を醸成 GitHub Sub Issuesの制約 GitHub Sub Issuesはまだ比較的新しい機能であり、いくつかの制約もありました。UIの表示やフィルタリングなど、スプレッドシートの一覧性には及ばない部分もあります。ここはGitHub Actionsによる自動生成テンプレートで補い、手作業を最小限にとどめる工夫をしています。 成果と今後の展望 得られた成果 マスタ情報の一元化 : 「最新版どこ?」がなくなった AI活用による予防的チェック : チェックシート確認前に多くの問題が解消されるようになった 開発プロセス全体への浸透 : 特定のタイミングだけでなく、各工程でチェック知見が活用されている 自動レビューとの統合 : GitHub ActionsによるAIレビューにチェック項目を組込み属人化を排除 チェックシートの形を変えただけで、開発プロセスの質が全体的に底上げされるといった手応えを感じています。 今後の展望 チェック項目が「過去の障害やバグの記録」である以上、継続的に更新されていくものです。GitHubリポジトリで管理することで、障害対応のポストモーテムからそのままPRでチェック項目に追加する、というフローも自然に回り始めています。 技術的にはシンプルな構成ですが、「スプレッドシートで十分動いているもの」をあえてエンジニアリングの文脈に持ち込みました。AI時代の開発プロセスに自然に統合できる形に進化させられた事例として共有させていただきます。 組織の中で「なんとなくスプレッドシートで管理しているもの」があれば、Markdownでリポジトリ管理することを検討してみてください。AI活用という文脈で、想像以上の恩恵があるかもしれません。 まとめ 「スプレッドシートで運用しているものをGitHubに移す」という、一見するとシンプルな取り組みですが、その先に見えた景色は想像以上のものでした。 本質的な課題は、チェックシートの情報が開発のコンテキストから分離していたことでした。それをエンジニアリングの文脈に統合したことで、以下のような変化が生まれています。 AIが開発プロセス全体でチェック知見を活用できる状態 手戻りの削減による、技術者が創造的な仕事に集中できる環境 PRベースの更新フローによる、チーム全員がナレッジを育てている当事者意識 これらは、単なるツール移行では得られない、本質的な価値だと考えています。 「スプレッドシートで十分動いている」と思っているものこそ、変化の余地があるかもしれません。既存の運用フローを壊さずに、ツールとフォーマットだけを変えるアプローチであれば、チームへの負荷を最小限に抑えながら大きな恩恵を得られる可能性があります。 今後もチェック項目を継続的に育てながら、開発プロセスのさらなる改善につなげていければと思います。 最後に、LIFULLではともに挑戦し成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 https://hrmos.co/pages/LIFULL/jobs/010 https://hrmos.co/pages/LIFULL/jobs/010-9998
こんにちは。LIFULL HOME'S の CRM領域で開発を担当しているソンです。 LIFULL HOME'Sでは、賃貸の一部レコメンドメールに掲載するレコメンド物件に対して、LLMを活用した「推薦文」を自動生成しています。これは「なぜこの物件がお勧めなのか」を自然な日本語で伝える短い文章です。物件情報をもとにユーザーごとの関心に寄り添った説明を添え、物件理解の促進とメール経由の詳細閲覧率向上を目指しています。 この記事では、その推薦文の品質を守るために私たちが構築した「AI監視システム」にフォーカスし、どのような基準で文章をチェックしているのか、実際の検出事例を交えて紹介します。 1. 導入:AIが書く文章は「便利」のその先へ 2. 根拠のない「充実」は、ただのノイズ 3. 「日本一」や「最高」が法に触れる理由 4. わずか12文字の攻防:128〜140文字のルール 5. AIが「空気を読む」:スペック羅列を超えた文章へ 6. 2段構えの監視:システムのしくみ 7. 結び:誠実な言葉こそ、選ばれるマーケティング 1. 導入:AIが書く文章は「便利」のその先へ AIによる推薦文の自動生成は、私たちのサービスにおいて欠かせない存在になりました。ただ、AIが生成する文章にはコンプライアンス上のリスクもあります。 実はこの施策の立ち上げ当初から、推薦文の品質監視は重要な課題として認識していました。LLMの特性上、意図しない表現が生成される可能性は避けられません。初期段階では生成ログをもとに人が目視でチェックしていましたが、確認できる量には限界があり、監視の精度にも課題がありました。 そこで私たちは、監視の自動化に取り組みました。2026年4月現在、「推薦文不正文言AI監視システム」が日々稼働しています。このシステムは、日中のコアタイムに定期的に生成された全文章を精査しています。私たちの監視システムは、ルールベースの用語スクリーニングとLLMによる文脈判定を組み合わせた構成へと進化しています(詳細は6章で解説します)。 この監視システムが、どうやって問題のある表現を検出しているのか。そのしくみと、私たちが目指す「言葉の質」について、技術と規制の両面から紹介していきます。 2. 根拠のない「充実」は、ただのノイズ 監視システムのログを分析して最も多く検出されるのが、「根拠なし表現」による「警告」です。「充実した設備」や「買い物便利」といった言葉は、つい多用されがちな表現です。しかし、監視システムにとってこれらは、具体的な裏付けのない不十分な表現に過ぎません。たとえ近くにスーパーがあったとしても、単に「便利」と書くだけでは不十分なのです。 監視システムの指摘例 「買い物便利」:近隣にコンビニ(徒歩800m以内)はあるが、もう少し具体的な説明が望ましい。 「充実した設備」:具体的設備名が明記されていないため根拠不足。 「日当たり良好」:方角や採光面などの理由が併記されていない。 読み手であるユーザーは、形容詞ではなく「事実」を求めています。監視システムに定義された「OK例」は、そのままプロフェッショナルの記述作法となります。 NG : 買い物便利 OK : スーパー(100m)近隣のため買い物便利 NG : 設備充実 OK : 設備充実(床暖房/追い焚き/WIC) 「近さ」や「多さ」を主観で語るのではなく、数値や施設名という「根拠」を添える。結局、具体的な根拠があるかどうかが品質の分かれ目です。 3. 「日本一」や「最高」が法に触れる理由 不動産広告には、明確に「違反」と判定される表現もあります。それは「不動産公正競争規約」によって厳格に定められた、最上級表現や完全性を意味する用語の使用です。 「日本一」「No.1」「最高級」「完全」「絶対」。これらの言葉は、客観的かつ調査にもとづいた具体的なデータがない限り、消費者に誤認を与える不当表示とみなされます。この規約にもとづくルールが監視システムに設定されており、過度な装飾は瞬時に「違反」と判定されます。 また、意外な落とし穴が「新築」という言葉の扱いです。 「違反」判定の事例 「新築複数」:『新築』と表記できるのは建築後1年未満かつ未入居の物件に限られるため、複数物件をまとめて『新築』と謳うことは規約違反のリスクが高くなる。また、新築と呼ぶための根拠説明も欠如している。 「格安」「破格」:射幸心をあおる表現として排除対象。 「早い者勝ち」:不当なあおりとして排除対象。 監視システムを通じて、こうした表現がブランドの信頼を損なうリスクをあらためて実感しました。 4. わずか12文字の攻防:128〜140文字のルール 推薦文の品質を左右するのは、言葉の意味だけではありません。システムには、非常に厳格な「文字数」という物理的制約が課せられています。私たちの監視基準では、推奨範囲は「128〜140文字」と極めてタイトに設定されています。 1文字でも超えれば警告が出ます。141文字になった瞬間、「文字数違反」として検出されます。 監視ログの記録 「推薦文が141文字と140文字を超えています」 「183文字で推奨範囲128〜140文字を超過」 なぜ、ここまで厳格なのでしょうか。それは、ユーザーのデバイス上でストレスなく読める「情報の密度」を、表示幅やスクロール量をもとに社内で検討した結果、この範囲が最適と判断したためです。ユーザーが読みやすい情報量を検討した結果、この範囲に落ち着きました。 5. AIが「空気を読む」:スペック羅列を超えた文章へ 「3LDK、南向き、駅徒歩5分」。こうした事実の羅列は、間違いではありませんが、優れた推薦文としては評価されません。監視システムには「スペック羅列」という警告項目が存在し、情報の羅列に終始した文章を「品質が低い」と判定します。監視システムは単なるキーワード検索ではなく、「自然な日本語で物件の魅力を伝えているか」という文章としての自然さも判定しています。 品質基準の定義 自然な日本語で物件の魅力を伝える文章であること。 スペック羅列のみは不可。 たとえば、条件だけを並べて最後に「ゆとりある毎日を実現します」と付け加えただけの文章は、「説明が薄く、スペック羅列寄り」と判定されます。 求められているのは、そのスペックが実際の生活にどう役立つのか、という視点です。物件データを生活のイメージに変換する力こそが、私たち書き手が意識すべき役割だと考えています。 6. 2段構えの監視:システムのしくみ この品質管理を支えているのが、LLMを活用した「推薦文不正文言AI監視システム」です。本システムは、コアタイムに定期的なチェックを実行します。 AI判定の前段階では、まず「ルールベース」による完全禁止用語のスクリーニングが行われ、それを潜り抜けた文章のニュアンスにリスクがないかをAIが判定します。特筆すべきは、AIに対して高い推論精度を求める設定を施している点です。これにより、AIは単なる文字のマッチングを超え、文脈を踏まえて、表面的には問題なさそうな表現のリスクも判定します。 システムの3つの強み 即時性の担保 : 違反検出時は、即座に担当者へ通知され、即応可能です。 高度な推論 : LLMの深い推論能力により、「一見よさそうだが実は根拠があいまいな表現」も見逃しません。 継続的改善 : 定期的に結果がまとめられ、組織全体のコンプライアンス意識の向上にもつながっています。 このしくみによって、人的チェックでは見落としがちな表現もカバーできます。常に高い水準で広告品質を維持する。これが私たちの目指す広告品質管理の姿です。 7. 結び:誠実な言葉こそ、選ばれるマーケティング AI監視システムが導き出した「安全」な文章。それは、けっして個性を殺した無機質なものではありません。むしろ、誇張を取り除いた、物件本来の価値を伝える言葉です。 結局のところ、監視システムが問題なしと判定する文章とは、「嘘がなく、具体的で、相手の人生に寄り添った誠実な文章」にほかなりません。どれだけテクノロジーが進化しても、 信頼の土台になるのは、事実にもとづいた言葉の積み重ねです。 AIを活用して推薦文を運用する私たちは、常に自らこう問いかけるべきでしょう。「あなたのその言葉に、読み手が信頼できる根拠はありますか?」その問いへの誠実さが、ユーザーから信頼されるサービスへとつながると考えています。 この監視システムはまだ導入したばかりですが、すでに大きな収穫がありました。監視結果を分析する中で、既存の推薦文生成プロンプトや監視用プロンプトそのものにも改善の余地があると見えてきたのです。監視システムは品質を守るだけでなく、私たち自身のしくみを見直すきっかけにもなっていると実感しています。 最後に、LIFULLではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは、プロダクトエンジニアリング部の江口です。 私は普段 LIFULL HOME'S 賃貸マーケットの技術負債解消に取り組むエンジニアリングチームのリーダーをしています。 本記事では、賃貸マーケットで長年の課題だった「ユーザー行動ログ送信処理」の技術負債解消について紹介します。技術的な取り組みだけでなく、エンジニアとして技術負債にどう向き合っていくべきかを考えるきっかけにもなった経験をお伝えできればと思います。 何が問題だったのか なぜこれまで解決できなかったのか どうアプローチしたか 難易度を下げてから勝負する 依存先の調査 古いログへの依存を一つずつ断ち切る 実装・テスト・移行での工夫 プロジェクト推進の難しさ やり遂げて思ったこと:技術負債解消とROI 終わりに 何が問題だったのか 賃貸物件の詳細ページは過去にリニューアルされ、新システムへ移行済みでした。しかし、ユーザー行動ログの送信処理だけは旧システムに残ったままで、新システムから旧システムのエンドポイントを叩くことでこの処理を委譲していました。つまり、詳細ページを1回表示するたびに、バックエンドへのリクエストが実質2倍発生している状態です。 これまでの行動ログ送信処理 これによって、負荷が集中する繁忙期には、DBのパフォーマンスの低下も懸念されました。もちろん、私たちも新システム側でクローラー判定を行い旧システムへのリクエストを抑制したり、ログの生成に関係のないバックエンドへのリクエストを停止したりと、できる限りの負荷軽減策を講じてきました。しかし、これらはあくまで対症療法に過ぎません。この状況を根本から解消するため、私たちのチームがこの問題に決着をつけることになりました。 これまでの試行錯誤の歴史については、ぜひこちらの記事もご覧ください。 www.lifull.blog なぜこれまで解決できなかったのか 過去にもログ送信処理の移植は試みられてきましたが、以下の理由により断念されてきました。 膨大な移植コスト : 約10年前のレガシーなロジックが複雑に絡み合い、2〜3名で1年かけても終わらない規模 品質担保の壁 : 不動産会社が掲載効果を分析するためのレポート機能に関わるため、集計結果の変動を許容しづらい ログの完全一致が困難 : 旧システムと新システムでは物件情報データの取得経路に微妙な違いがある どうアプローチしたか 難易度を下げてから勝負する このプロジェクトで最も重要だった判断は、「難しい問題を頑張って解く」のではなく、「問題の難易度そのものを下げる」という方針を取ったことです。 具体的には、ユーザー行動ログに依存する周辺システムを、社内でデファクトスタンダードとなっているユーザー行動解析基盤であるTealiumへ先に移行させることで、古いログへの依存を一つずつ断ち切っていきました。 これにより、新システムへの移行時に保証すべきログの属性値(スキーマ)を大幅に削減し、「守るべき範囲」を意図的に狭めることで、テスト工数と不確実性を下げました。 依存先の調査 まず、ログが格納されたS3のバケットポリシーから、アクセスが許可されているアカウントやロールを洗い出しました。中には過去に使われていたと思われるAWSアカウントからの許可や、AWSアカウントレベルでの広いアクセス許可が残っており、具体的にどのシステムからのアクセスなのかがポリシーだけでは判別できないケースもありました。そうした許可については、CloudTrailで実際のアクセス有無を確認しながら整理を進めています。その上で、S3の接続情報をキーにGitHub上のリポジトリを横断検索し、該当するコードを地道に追っていきました。それでも埋まらない部分は、社内のConfluence・Jira・チャットログ・GitHub Discussionsを当たり、マーケットの垣根を越えて担当者に直接確認することで、一つずつ依存先を明らかにしていきました。 最終的に、ログに直接依存しているシステムは20以上にのぼり、さらにBigQueryにも連携されていたため、その先ではアナリストも分析に利用している状況でした。 この調査は、このプロジェクトで最も骨が折れたパートです。 アーキテクチャ図 古いログへの依存を一つずつ断ち切る 依存先が明らかになった後は、そのうち賃貸の物件詳細ページのログに直接関わるシステムについて、Tealium経由のデータに切り替えてもらう調整に入りました。しかし、これが一筋縄ではいきませんでした。レガシーなシステムであるがゆえに、主管部署の担当者自身がシステムの仕様を十分に把握できていないケースが多く、「何のデータをどう使っているのか」を一緒に紐解くところから始める必要がありました。 アナリストに対しては、BigQuery上のデータ切り替えについて告知を行いました。実態としては、アナリスト自身もどのデータを使っているか明確に把握しきれていない状況でしたが、データを外部に販売しているような重要度の高い用途については、個別にしっかりヒアリングを行い、影響がないことを確認しました。 また、依存先の洗い出しを促進するため、プロジェクトの進捗や影響範囲を社内に定期的に周知し、「自分のシステムも該当するかもしれない」と気づいてもらえるよう働きかけました。 実装・テスト・移行での工夫 テストでは、旧システムから出力されるログと新システムから送信されるログを突き合わせて比較する方針を取りました。完全一致しない項目については、後続のシステムで実際に使用されていないことを一つずつ確認しています(今後、使われていない項目は削除していく予定です)。 特に重要だったのは、不動産会社向けレポート機能への影響確認です。集計バッチの出力結果を旧ログ・新ログそれぞれで比較し、差分がないことを検証しました。ただ、テスト環境自体にパフォーマンスの課題やCI/CDの課題があり、動作確認を回すだけでもかなりの労力がかかりました。 移行は段階的ではなく、一括で切り替えました。二重にログを保持し続けるコストや、切り戻し時に古いログで後続システムを再実行する運用の複雑さを考慮し、この方式を選択しています。万が一の失敗に備え、リカバリー方針と関係者への対応フローを事前に策定しておくことで、リスクをコントロールしました。 プロジェクト推進の難しさ このプロジェクトは、技術的な難しさ以上に、推進そのものに大きな負荷がかかるものでした。 自チームでのログ送信処理の移行作業に加え、旧ログに依存する周辺システムについて、Tealiumへのリアーキテクチャのサポートとコードレビューを自ら担いました。各システムの技術スタックも事情も異なる中で、設計方針の提示からレビュー、問題発生時の判断までを一手に引き受ける形です。 さらに、主管部署の担当者がシステムの仕様を把握しきれていないケースでは、仕様の調査や整理から伴走する場面も少なくありませんでした。マーケットや部署の垣根を越えた調整を重ね、関係者全員が同じゴールに向かえる状態を作ることも、このプロジェクトにおける自分の重要な役割でした。 やり遂げて思ったこと:技術負債解消とROI この取り組みをやり遂げた今、「これは本当に事業に必要だったのか?」と自問することがあります。 バックエンドへの負荷が実質2倍という状態は健全ではなく、実際に繁忙期にはDBへの負荷が問題になっていました。解消すべき課題だったのは間違いありません。一方で、技術負債の解消にはそれなりのコストがかかり、その間ユーザーに直接価値を届ける開発に割けるリソースは減ります。そのバランスをどう取るかは、リーダーとして常に問い続けるべきテーマだと感じるようになりました。 この経験を通じて、技術負債解消は「エンジニアが気持ちよく開発するため」だけではなく、事業のROIを踏まえた上で優先度を判断すべきものだという考えに変わりました。今回のケースはDB負荷という差し迫った理由があったからこそ正当化できましたが、常にそうとは限りません。 今後は、技術負債の解消を特別なプロジェクトとして切り出すのではなく、日常の開発の中で自然に改善していける状態を目指したいと考えています。エンジニアとしての本分は、技術力でユーザーに価値を届け、事業の優位性を築くことにあるはずです。プロダクト開発に軸足を置きながら、健全なコードベースを維持していく——そのサイクルを回せるチームでありたいと思っています。 終わりに 本記事では、LIFULL HOME'S 賃貸マーケットにおける技術負債解消の取り組みについて紹介しました。 このプロジェクトの作業は泥臭いものの連続でしたが、それを完遂できたときの達成感は大きく、負債解消へのインパクトも確かなものでした。同時に、「技術的に正しいこと」と「事業として正しいこと」の間で考え続けることの大切さも学びました。 LIFULL では、こうした課題に一緒に向き合い、ともに成長していける仲間を募集しています。興味を持っていただけた方は、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
こんにちは、LIFULL QAエンジニアの木住野(きしの)です。 普段はQAエンジニアやUXリサーチャーチームのマネジメントを行っています。 2026年3月20日に開催された JaSST'26 Tokyo へ、QAエンジニア3名(星野、鐘、木住野)が参加しました。 本記事では、印象的だったセッションの紹介と、そこから得た学びを自社QAにどう活かすかについて考察します。 今回はビッグサイト開催 参加の目的 今回の参加目的は、生成AIが急速に普及する中でのテスト技術動向の把握と、自社QAプロセスへの還元です。 特に2026年は、AI駆動開発(AIDD)やLLMを活用した開発が本格化しており、QAエンジニアの役割や品質保証の在り方が大きく変わりつつあります。 この変化の波の中で、私たちが何を観測し、どう行動すべきかを学ぶことが今回の最大の狙いでした。 参加の目的 各メンバーが選んだ注目セッション 鐘:AIDD・SDD時代のQA対応 ―QAは何を品質として観測するのか― セッション概要 QAEとしての気付き 実務への適用案 星野:AIと品質保証のこれまでとこれから セッション概要 QAEとしての気付き 実務への適用案 木住野:Beyond Quality Assurance -AIと拓くQAの未来像- セッション概要 QAEとしての気付き 実務への適用案 セッションから見えたチーム内での振り返り 自社とのギャップ:現在の体制と比較した不足点や強み 今後の注力領域 まとめ 各メンバーが選んだ注目セッション 今回のJaSSTでは、AI時代のQAをテーマにした学びあるセッションが盛りだくさんでした! その中から、各メンバーが特に印象的だった1つをチョイスして紹介します。 鐘:AIDD・SDD時代のQA対応 ―QAは何を品質として観測するのか― セッション概要 登壇者:小川 椋徹氏(2WINS)、久保 雅之氏(ポールトゥウィン)、後藤 香織氏(ポールトゥウィン) AIが実装だけでなく設計やテストまで担う時代に、QAエンジニアは何を観測すべきか。このセッションでは、4つの議題を通じてAI時代の品質保証について議論されました。 1. 品質が保証されていることの意味 AIは次に来る単語を予測する性質上、必ず一定の割合で不具合を含むコードを生成します。AIがコードを書き、AIがテストしても、それだけで品質を担保することは困難です。95%の正解率を99%に引き上げるという考え方が重要で、そのためには上流工程の段階からしっかり設計しておく必要があります。 2. AIツールのできること、できないこと AIが日進月歩で進化する中でも、変わらず重要なのはドメイン知識やノウハウをちゃんと残すことです。 AIのできること:コード生成、コード解析など AIのできないこと:非機能要件、設計レベルのセキュリティ欠陥、環境依存の問題、ビジネスロジック 3. 品質のエビデンスの再定義 AIで開発スピードが飛躍的に上がっている今、「なぜこのような実装をしたのか」を追跡できるようにすることが重要です。 大規模・長期間プロジェクトでは仕様書が古くなり、小規模・短期間プロジェクトではエビデンスをスキップしがちです。AI開発が早すぎて仕様書が追いつかない問題を解消するには、 自動でエビデンスを残すしくみ が必要です。 4. QAエンジニアの役割の変化 下流はAIが得意ですが、上流はよく間違えます。QAエンジニアはAIツールを駆使して、コードから逆算した仕様の把握や、仕様書の作成・更新を自動化し、AIが苦手とする上流工程をもっと考える役割が求められます。 QAEとしての気付き AIはビジネスロジックやユーザーの利用シーンを考えにくいため、開発のベースである上流の設計をQAがレビューすることで、根本から欠陥を防ぐことが重要だと感じました。 実務への適用案 小規模開発・個人開発でエビデンススキップによる属人化が起きていますが、 「属AI化」 も起きているのではないでしょうか。AIに要件を伝えた後、AIが実装し、AIがテストし、開発者は何を実装したか詳細まで把握していない状態です。 対策として、開発後に必ずAIでドキュメント化させ、依頼した要件と照らし合わせて確認・更新することが必要だと考えています。 星野:AIと品質保証のこれまでとこれから セッション概要 登壇者:須原 秀敏氏(ベリサーブ)、松木 晋祐氏(ベリサーブ)、山﨑 崇氏(ベリサーブ) 台本なしのスペシャルトークセッションとして、AI品質保証の技術的変遷と今後の展望が語られました。 従来の検証技術の限界 LLMのプロダクトにそのまま適用するのはとても難しいと語られていました。 メタモルフィックテスティング :入力内容を変異させても出力に同じ関係性が維持されているかを検証する手法ですが、出力が多様化しているLLMではルールベースなどのシンプルな評価は難しい。 ニューロンカバレッジ :内部構造の網羅性に着目しテストデータが内部ロジック(ニューロン)を網羅した(発火させた)か評価する手法ですが、これもLLMに対しては巨大すぎるために適用させるのは難しい。 テストの在り方は変わるのか 実はあまり変わらないのかもしれません。日本の製造業で培われたのは 統計的 品質管理です。 かつてバラツキを制御して抜取検査で品質を評価してきたように、LLMを搭載したプロダクトには決定論的な正誤ではなく、確率的な精度で評価をする必要性があるだけです。 先進的な技術のキャッチアップだけでなく、古典として評価されているような技術書に立ち返り基礎となる考え方と技術を学習する必要性を再認識しました。 サービスの自由度を狭める必要性 サービスの使われ方が多様化しないよう、自由度を狭める必要があります。たとえばIRページにチャットbotを設置する場合、ハルシネーションは法的なリスクがあります。サービスが想定外の利用方法をされないように縛りが必要です。 フライホイール型のQAと継続的な監視 LLMを搭載したプロダクトの場合、リリース後にも精度が下がっていないことを継続的に監視する必要があります。テスト環境よりもコンテキストが明らかに広くなり、外部環境の変化によって使われ方や求められる出力も変化します。だして終わりではなく、フィードバックループを構築する技術が必要です。 QAEとしての気付き 仕様の引き算・制限することの重要性を能動的に広め、リスクヘッジが必要 LLMの精度を保ち続けるための監視(メトリクスの設計) 自身が社内に提供するツールや開発プロセスにLLMを活用する場合もこれらを意識しなければ、生産性や成果物の質に影響が出そう 基礎となる考え方は変わらない。品質保証の古典やソフトウェア工学についてあらためて知識と技術を深めることが重要 実務への適用案 「AIに何をさせないか」の意識を持つことが大切です。社内に配布するツールも同様で、意図しない用途での利用により問題のあるハルシネーションを起こす可能性があります。 木住野:Beyond Quality Assurance -AIと拓くQAの未来像- セッション概要 登壇者:池之上 あかり氏(LINEヤフー)、平田 香織氏(LINEヤフーコミュニケーションズ) AI導入におけるQA組織の現状と課題について、コーチングの技術を用いた組織変革の事例が紹介されました。 対策のアプローチ チームのAIに対する価値観(不安や恐ろしさ)を変える 新しい価値観をチームにインストール 余力による改善活動が増えたなどの効果が見え始めた QAEとしての気付き 私自身はAIを活用することを推進することに躊躇はなく、拡張するツールである認識でしたが、一方でこの発表のようにAIに脅威や不安を感じている人もいるということがわかりました。 組織横断的な改善も多いので、こういった考え方を知れたことが大きかったです。価値観・信念の摩擦といった言語化しづらい障壁についても知れたのが良かったです。 実務への適用案 AIに限らず新しい技術・思想、あらゆる事象は人によって受け入れること自体に障壁がある可能性もあるため、それを考慮してQAチーム、ひいてはLIFULLの開発組織によい変化を作っていきたいと考えています。 セッションから見えたチーム内での振り返り 自社とのギャップ:現在の体制と比較した不足点や強み 不足点・課題 以下の点については改善の余地があると感じました: エビデンス管理の自動化 :AI開発のスピードに仕様書が追いつかない問題に対して、自動でエビデンスを残すしくみが不足しています。 上流工程へのシフト :QAエンジニアがより上流工程に関与し、設計レビューを強化する体制が必要です。 組織的な心理的障壁への配慮 :AIに対する不安や恐れを持つメンバーへの配慮と、組織全体での価値観の共有が必要です。 リリース後の継続的監視 :LLMを活用したプロダクトにおいて、リリース後の精度監視とフィードバックループの構築が課題です。 今後の注力領域 各メンバーが挙げた「明日から変えたいこと」 AI開発後のドキュメント (鐘):AIで開発した後、必ずドキュメント化し、要件と照らし合わせて確認する習慣をつける AIに何をさせないかの意識 (星野):社内ツールでも、意図しない用途で利用されることを防ぐ設計を意識する 新技術受け入れの障壁への配慮 (木住野):新しい技術や思想を導入する際、人によって受け入れに障壁があることを考慮する まとめ JaSST '26 Tokyoを通じて、AI時代におけるQAエンジニアの役割が大きく変わりつつあることを実感しました。しかし同時に、テストの本質は変わらず、品質保証の基本的な考え方が今後も重要であることを確認できました。 本記事で紹介したセッションをベースにすると以下のような視点で学びがありました。 鐘 : 技術的視点 から、上流工程の重要性とエビデンス管理の課題を指摘 星野 : 検証技術の変遷と本質 から、テストの統計的性質とフィードバックループの必要性を強調 木住野 : 組織・人的視点 から、AIに対する心理的障壁とコーチング手法の重要性を学んだ 私たちが得た最大の気付きは、「AIの進化に合わせてQAも進化しなければならない」という危機感と、「基本を押さえていれば対応できる」という自信の両立でした。 JaSSTで得た外部知見を、自社の品質向上につなげていきます。 最後に、LIFULL では一緒に働く仲間を募集しています。 よろしければこちらのページもご覧ください! hrmos.co hrmos.co
LIFULL HOME'S不動産査定 ・ ホームズマンション売却 の開発をしている、ジョン ヨンソクです。 今、私たちのエンジニアリングの世界は大きな転換期にあります。生成AIの登場によって、開発のスピード感や求められるスキルセットが劇的に変化しているからです。 そんな中、私はチーム内の「生成AI活用」を促進するための活動に取り組みました。今回は一人のエンジニアとして、チームと向き合いながら、どのようにメンバーとAIの距離を縮めていったのか、その試行錯誤のプロセスを綴ります。 一方的な「レクチャー」を避けた理由 目標は「使いこなすこと」ではなく「親密度」 「親しくなる」ための設計 前半:「まず触れる」ための基礎固め 後半:「実務で使う」ための実践編 アンケートから「まだ使えていない領域」を見つける 「親密度」はどう変わったか 「とりあえず聞いてみる」が当たり前になるまで 次の「当たり前」に向けて 一方的な「レクチャー」を避けた理由 活動の起点となったのは、事業目標である利益(KGI)の達成です。その先行指標として「売却開発サイクルタイムの短縮」を掲げ、目標達成のための最重要成功要因(CSF)として生成AIの活用を定義しました。このCSFを具体化し、最終的なKGI達成へとつなげるための指標が、開発工程における生成AIの活用率(KPI)です。目指す姿は、全メンバーが一定水準以上でAIを活用し、開発工程全体でAIが担う割合を大幅に引き上げることです。 活動を開始した当初、チーム内には「すでに使いこなしているメンバー」と「まったく触れていないメンバー」の間に大きな差がありました。どのレベルのメンバーにとっても意味のある時間にしたい。そう考えたとき、「AIの使い方」や「サービスの比較」を一方的に教えるような、いわゆる「講習」形式は避けるべきだと感じました。 単なる情報の提供は、ともすれば受け身の姿勢を生んでしまいます。インターネットにはすばらしい情報が溢れていますが、同じ業務ドメインを持つメンバーどうしが対話を通じて生み出す活用例には、それを超える実践力があります。私がやるべきことは情報の横流しではなく、こうした知見を共有し合う 「文化」の土壌を整えること だったのです。 目標は「使いこなすこと」ではなく「親密度」 文化を作るために、まず定義したのが「AIと親しくなる」という状態です。KPIの数字を追う前に、まずはメンバー全員が 「日常的にAIに触れている」状態を作ること が最優先であると判断しました。 そこで、その状態を測るスモールステップとして設定したのが「アクティブ率」です。 「1ヵ月のうち、何日AIにアクセスしたか」を営業日数で割り、その比率が40%以上になることを第一の目標に掲げました(社内で利用しているAIツールの管理機能から、メンバーごとの利用日数を確認できます)。 「最初からうまく活用すること」よりも「毎日少しでも相談してみる」こと。この「親密度」を重視した設計が、結果としてメンバーの心理的ハードルを下げることにつながりました。 「親しくなる」ための設計 活動期間から逆算し、隔週を基本におよそ10回の構成としました(軽い共有は毎週開催することも)。この限られた機会の中で何をどう届けるか、活動の企画を一緒に担ってくれたメンバーと設計を進めました。 まず、活動全体を大きく2つに分けました。前半は基礎的なインプット中心、後半は実務活用中心です。最終的にはメンバー自身が活用事例を持ち寄り、互いに共有し合う場にしたいと考えていました。 前半:「まず触れる」ための基礎固め 社内で主に使用しているAIツールの導入と基本操作から始め、MCPを活用して社内の実務ツール(Confluence、Jira、データベースなど)と連携させる方法を扱いました。最後に、AI利用時の注意点やセキュリティについて共有しました。また、ほか部署でAIを積極的に活用しているメンバーをゲストに招き、実体験を語ってもらう回も設けました。 ただし、基礎的なインプットはどうしても一方的な講義になりがちです。そこで各回は、発表を10〜30分に抑え、残り30〜50分は実習・Q&A・ディスカッションの時間としました。実習で扱う内容は事前に共有し、必要な環境構築を済ませておいてもらうことで、限られた時間を「一緒に考え、試す」ことへ集中できるようにしました。 実習では、MCPを使って社内の情報にアクセスする方法など、 すぐに業務で役立つ内容を中心に据えました 。そして、この実習を通じて生まれた疑問や気付きを、そのままディスカッションにつなげていきました。同じ業務ドメインを持つメンバーどうしが議論することで、「自分ならこう使う」「この場面でも使えそう」といった具体的なイメージが互いに鮮明になっていく。この対話の時間こそが、単なるインプットを「自分ごと」に変える鍵だったと感じています。 後半:「実務で使う」ための実践編 前半がインプットと実習を織り交ぜた構成だったのに対し、後半は実際の活用にフォーカスしました。AIを活用したコードレビューの協業プロセスや、テストケース作成の効率化など、日々の開発業務に直結するテーマを取り上げました。 まずは私自身の使い方を共有するところから始めました。特にコードレビューでは、「PRをまるごとAIに渡してレビューして」と大きく投げるのではなく、作業を小さな単位に分解し、各ステップで人間が確認を挟む協業構造を提案しました。AIは確率ベースで動作するため、一度に任せるステップが長くなるほど精度は落ちていきます。短く区切って人間が介入するポイントを増やす——この「分解」の意識が、AI活用の精度を上げる鍵になります。「どう使えばよいか、少し感覚がつかめた」という声が聞こえてきたのは、この回でした。 そして当初の狙い通り、後半に進むにつれて発表者が私だけではなくなっていきました。たとえば、ある回で共有したAIツールのプランニング機能を、あるメンバーが日常的に愛用するようになりました。また、エージェントのカスタマイズ方法を共有したことをきっかけに、自分のローカル環境のエージェント設定を実際に改善するメンバーも現れました。知見を共有し合う文化の輪郭が、少しずつ見え始めたことが、この活動における一番の収穫だったととらえています。 アンケートから「まだ使えていない領域」を見つける 活動の方向性を決めるうえで活用したのが、社内で定期的に実施しているアンケートです。アンケートでは「実際に担当している業務領域」と「その中でAIを活用している領域」の2軸で回答を集めています。この結果を突き合わせることで、担当業務のうちAIを活用できている割合と、まだ活用方法のわからない領域が明確になります。活動ではこの分析を活用し、活用が進んでいない領域を優先的に共有会のテーマに取り上げていきました。たとえば、テスト領域でのAI活用が進んでいないと分かったため、テストにおけるAI活用の進め方をテーマにした回を設けました。 固定的なカリキュラムではなく、チームの状況に合わせて柔軟に内容を調整していく。この「活用シーンの具体化」と「共有の場」の両輪が、チームの変化につながりました。 「親密度」はどう変わったか 直近の計測データである2026年2月時点の結果をもとに振り返ります。 まず、アクティブ率の変化です。 Before(2025年10月) After(2026年2月) 変化 アクティブ率 40%以上 約60% 100% ↑約40% アクティブ率 100% 約40% 約75% ↑約35% アクティブ率 0% 約25% 0% ↓25% そして注目すべきは、アクティブ率だけでなく、AIとのやりとりの深さを示す総活動量(トークン使用量)にも変化が現れたことです。 たとえば、あるメンバーは活動開始前からアクティブ率は高かったものの、実際のトークン使用量はごくわずかでした。AIを起動はしていても、何を聞けばよいかわからず、深い活用にはいたっていなかったのです。それが活動を経て、トークン使用量は10倍以上に増加しました。また、アクティブ率0%だったメンバーも、起動頻度の増加に伴ってトークン使用量が着実に伸びていきました。 この変化は、「まずAIを開く習慣」が先行指標となり、「活用の深さ」が自然と後からついてくるという構造を示しています。 頻度を追うことで、結果として質も伴ってくる 。 「とりあえず聞いてみる」が当たり前になるまで 数字の変化の裏側には、メンバー一人一人の意識の変化がありました。 「何を聞けばよいかわからない」と戸惑っていたメンバーも、共有会での具体的な活用例を自分事としてとらえることで、徐々に「とりあえずAIに聞いてみる」という動きが習慣化していきました。最初は受け身だったメンバーが、やがて「こういう場面でも使えそう」と自ら提案するようになっていく。 「隣のメンバーがこう使っているなら、自分も試してみよう」 そんな小さな刺激の連鎖が、チーム全体のエンジニアリングを底上げしていく。 次の「当たり前」に向けて 約5ヵ月にわたる活動を振り返ると、エンジニアチームのAI活用に対する解像度は明らかに上がりました。 「何を聞けばよいかわからない」から「自分なりの使い方を持っている」へ 。その変化は、数字にも日々のやりとりにも表れていました。 一方で、次の課題も見えています。開発者の業務効率化だけでは、事業目標への貢献には限界があります。エンジニアがAIで開発を速くしても、何を作るかの判断はエンジニアだけでは完結しません。企画メンバーが持つドメイン知識の深さは、エンジニアには代替できません。その知識とAIを掛け合わせるためには、企画メンバー自身がAIという道具に親しくなる必要があります。 今回の活動で得たアプローチを、次は企画メンバーにも届けたい。それぞれが自分なりの活用法を持ったとき、チームの枠を超えた本当の変化が始まると信じています。 最後に、LIFULL では一緒に働く仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
生成AI初心者エンジニアが3ヵ月でAI駆動開発を習得するまで こんにちは。LIFULL HOME'S の CRMで開発を担当しているソンです。 2025年4月に復職してから、業務では生成AIをほぼ使ったことがない状態でしたが、社内ではAI活用や導入が活発に進み始めていました。エンジニアチーム内ではAI活用の開発手法を学ぶ社内研修が行われており、自分も参加して実際にAIを活用した開発を経験できていました。そしてAI活用開発プロジェクトの担当になったとき、本格的に生成AIを利用した開発を始めようとしていました。 この記事では、生成AI初心者だった私が試行錯誤しながら、本格的にAI駆動開発に取り組んだ直近3ヵ月(2025年12月〜2026年2月)の過程と、そこから得た学びを共有します。最初の1ヵ月は失敗続きでしたが、社内のサポート体制やナレッジ共有を活かすことで、月あたりのGitHub Contributionが約3.5倍に増加しました。担当プロジェクトではCTR・CTORの改善成果も得られました。同じように「AIを使ってみたいけど、どう始めればよいかわからない」という方の参考になれば幸いです。 生成AI初心者エンジニアが3ヵ月でAI駆動開発を習得するまで プロジェクト概要 開発したもの 最初の壁:「適当な」プロンプトの代償 期待と現実のギャップ 具体的な失敗例 失敗1:複雑すぎるコード 失敗2:AIも間違える——参照先の確認不足 転機:チームとサポートの力 職種を超えたAI活用の文化 全社共有の設定とツールの活用 keelaiチームの手厚いサポート 成果:数字で見る変化 アウトプット量の変化 コード品質の向上 学んだこと:3ヵ月の試行錯誤から 1. AIをどう使うかを考える 2. 設定と使い方を学ぶことが成功への近道 3. 生成AIは日々成長している。恐れず耳を傾けよう 4. チームとサポートの重要性 今後の課題と展望 AIへの依存度が高まる怖さ さらなる活用の可能性 終わりに プロジェクト概要 開発したもの シナリオメールという、問い合わせ(反響)を行ったユーザーに対して配信されるレコメンド物件メールがあります。このメールで推薦される物件に対して「なぜその物件がお勧めなのか」を生成AIで自動説明し、ユーザーの物件理解促進とCVR(コンバージョン率)向上を図るプロジェクトでした。 レコメンド物件は毎回ユーザーごとに変わるため、手動やロジックだけでは自然な推薦文を作ることが難しいという課題がありました。そこで、生成AIを活用して物件の特徴を自然言語で説明する方法を採用しました。 結果として、既存パターンと比較してCTR(クリック率)とCTOR(クリック・トゥ・オープン率)がともに改善しました。 最初の壁:「適当な」プロンプトの代償 期待と現実のギャップ 最初のプロンプトで作られたコードを見た感覚ではうまくやれば2日もかからず終わりそうだと思っていました。 開発を行ったリポジトリのアーキテクチャにも沿っているし、APIで必要な基本的な構造やチェック、テストコードもできていました。 しかし、詳細をチェックしていくと問題だらけでした。 具体的な失敗例 失敗1:複雑すぎるコード 生成されたコードは、一見すると「ちゃんと動きそう」に見えました。しかし、実際には以下のような問題がありました。 エラーハンドリングが過剰で、本来キャッチすべきでないエラーまで握りつぶしていた 不要な抽象化レイヤが追加され、コードが読みにくくなっていた パフォーマンスを考慮していない実装(毎回ファイルを開閉するなど) 結局、生成されたコードの一部では手作業で修正したり、AIに再度修正を依頼したりの繰り返しでした。「最初から自分で書いた方が早かったのでは?」と感じたときもありました。 失敗2:AIも間違える——参照先の確認不足 OpenAIのPrompt Caching機能を使った設計と実装を、AIコーディングアシスタント(Claude)に依頼したときのことです。OpenAIの公式ドキュメントのURLも参考資料として渡していました。 しかし、実際にはURLの読み込みに失敗しており、AIはOpenAIではなく自分自身(Claude)のPrompt Cachingの仕様に基づいたコードを生成していました。両者ではPrompt Cachingのしくみが異なるため、そのまま使えば動かないコードになっていたのです。PRから作成されるEphemeral Environmentでテストしたところ、改修内容が反映されていないことに気付き、もう一度ドキュメントを確認して原因が判明しました。 AIが「もっともらしく」回答しているときほど要注意です。前提となる情報源を正しく取得できているか、出力結果が意図した仕様に基づいているかを常に確認する必要があります。 それでも使い続けた理由は、これはAIの実力の問題というよりは使い方の問題であることがわかったからです。 転機:チームとサポートの力 職種を超えたAI活用の文化 社内のSlackでもさまざまなナレッジが共有されていますが、月1回の定例で行っているエンジニア組織の月次定例会でも生成AIを活用したナレッジ共有とワークも行っています。 そこで学んだ開発手法や共有されたプロンプトが大きな力になりました。 また、エンジニアチームだけでなく、CRMチームでは非エンジニアメンバーの間でも生成AIの導入と活用が活発に行われています。普段の会話の中でも自然にナレッジ共有ができており、職種を超えたAI活用の文化が根付いています。 全社共有の設定とツールの活用 社内では、MCP(Model Context Protocol)を使ったPrompt-serverが提供されており、開発関連のプロンプトが共有されていました。MCPとは、AIツールが社内のコードベースや開発ルールを参照できるようにするしくみです。 さらに、全社で生成AIを活用するための設定が共有されています。これにより、個人でゼロから環境を整える必要がなく、すぐに生成AIを活用できる基盤が整っていました。 周りから学んだナレッジを一つ一つ適用していくことで、少ない手順で目標の成果物へ近付けるようになりました。そしてナレッジを学んで適用していくのがどんどん楽しくなりました。 keelaiチームの手厚いサポート このプロジェクトで最も助けられたのが、社内のAI活用推進チームであるkeelaiチームのサポートでした。 開発中のPRをそっと見に来てくれて、性能改善に役立つコメントやリンクを教えてくれる Slackで企画メンバーと相談していると、まだメンションも投げていないのに現れて、理由や解決方法を教えてくれる まるでAIのような対応速度と的確さで、初めて生成AIを使う私にとって、これ以上ない心強いサポートでした。 成果:数字で見る変化 アウトプット量の変化 GitHub Contributionを見ると、変化は明らかでした。 2025年(4月〜12月) : 229 contributions 2026年(1月〜2月) : 186 contributions 2025年は9ヵ月間で229 contributions、月平均約25件。2026年は約2ヵ月で186 contributions、月平均約90件。contributionの数がそのまま開発速度を表すわけではありませんが、アウトプット量の変化を示す一つの指標として、月あたりの生産量で比較すると約3.5倍のペースになっています。 コード品質の向上 アウトプットの量の変化だけでなく、コードの質も向上しました。 コメントの充実 : AIでコードを生成することで、抜けがちなコメントが詳細に作成されるようになった 設計書の詳細化 : 仕様駆動開発(要件定義→設計→実装の順にAIと対話しながら段階的に進める手法)を取り入れ、要件と設計を明確にしてから開発するようになった。手作業では時間がかかるフロー図やシステム図の作成が簡単になり、記載漏れが減った テストケースの網羅性 : エッジケースを含めた包括的なテストケースを生成できるようになった 学んだこと:3ヵ月の試行錯誤から 1. AIをどう使うかを考える 最初の失敗から学んだ最も重要なことは、AIは 優秀 だがあくまでも アシスタント であることです。 AIは、与えられた情報の範囲内で最善の出力をしようとします。しかし、情報が不足していたり、参照先が間違っていれば、不完全な出力しか得られません。 大切なのは「AIをどう使えば効率的か」を常に考えることです。 2. 設定と使い方を学ぶことが成功への近道 プロンプトの書き方も大切ですが、それ以上に重要なのは、AIを使うための環境設定と基本的な使い方を理解することです。 社内で共有されているAIツールの共通設定を活用すれば、個人で試行錯誤する時間を大幅に短縮できます。MCPやPrompt-serverといったツールの使い方を学んだことで、AIの能力を最大限引き出せるようになりました。 良い設定と使い方の条件は、以下のようなものです。 再現性 : 誰が使っても同じ結果が得られること 共有可能 : チーム全体で活用できること 拡張可能 : 新しいユースケースに対応できること そして、設定や使い方自体もチームでレビューし、改善していくべきものです。 3. 生成AIは日々成長している。恐れず耳を傾けよう 生成AIの技術は日々進化しています。「以前試してダメだったから」と諦めるのではなく、常に最新の情報にアンテナを張り、新しい可能性に耳を傾けることが大切です。 私の場合、最初の1ヵ月は失敗続きでしたが、周りの情報やサポートに耳を傾けて、積極的に試してみることで、3ヵ月後には開発速度が約3.5倍になりました。 AIの進化速度は想像以上に速く、数ヵ月前には不可能だったことが今では当たり前にできるようになっています。恐れずに、まずは試してみることが重要です。 4. チームとサポートの重要性 一人でAIと格闘していたら、おそらく挫折していたと思います。 チームでプロンプトを共有し、レビューし合う文化 Prompt-serverのような、知見を蓄積・共有するしくみ keelaiチームのような、専門家のサポート これらがあったからこそ、短期間でAI駆動開発を習得できました。 会社でも積極的にAI活用を支援しているので、最近では非エンジニアの間でもAIを使うときのコツがよく共有されています。この流れは、今後さらに加速していくでしょう。 今後の課題と展望 AIへの依存度が高まる怖さ 最近、少し怖いと感じることがあります。 直接コードを書くことや、繰り返し行われる作業を見ると、ついついプロンプトを作ってAIに任せたくなるのです。 これは効率的である一方、基礎的なコーディング力が落ちるリスクもあります。AIに頼りすぎず、自分で考える時間も大切にしたいと思っています。 さらなる活用の可能性 今回のプロジェクトを通じて、AIの可能性を実感しました。 今後は以下のような活用も試していきたいと考えています。 設計段階でのAI活用の深化 : 仕様駆動開発(要件定義→設計→実装を段階的にAIと進める手法)を始めているが、要件定義の精度をさらに上げたい チーム横断でのプロンプト標準化 : 個人の知見をチーム全体の資産にするしくみづくり AIの出力品質の定量評価 : 生成コードの品質を客観的に測定する基準の確立 終わりに 生成AI初心者だった私が、3ヵ月のAI駆動開発で学んだことです。 「AIをどう使うか」を常に考える 設定と使い方を学ぶことが成功への近道 生成AIは日々成長している。恐れず耳を傾ける チームとサポートの力を活かす もしあなたが「AIを使ってみたいけど、どう始めればよいかわからない」と思っているなら、まずは小さく始めてみてください。 最初はうまくいかないかもしれません。私も最初は失敗続きでした。しかし、諦めずに試行錯誤を続ければ、必ず成果は出ます。 そして、周りの情報やサポートに耳を傾けてください。一人で悩むより、チームで共有し、専門家に相談する方が、はるかに早く成長できます。 AIを使った開発は、もはや「特別なスキル」ではなく、「当たり前のスキル」になりつつあります。この波に乗り遅れないよう、今日から一歩を踏み出してみませんか? 最後に、ともに開発フロー改善に取り組んでくださる仲間を募集しています。 hrmos.co hrmos.co
KEELチーム の相原です。 前回のエントリは「比較的安全にMCPサーバを動かす」でした。 www.lifull.blog 今回は信頼できる可観測性基盤を提供するべく、KubernetesクラスタにおけるPull型アプローチ由来のログ・メトリクス欠損と色々向き合った話を書きます。 Pull型アプローチとそのトレードオフ kubeletにログファイルを削除される前にFluentdに読ませたい eBPFでunlinkat(2)を遅延実行させる PrometheusがCounterのインクリメントをScrapeするまでPodを待機させたい SIGTERMを受け取ったら次回のScrapeまで待機するプロキシを挟む まとめ Pull型アプローチとそのトレードオフ まずPull型アプローチについて軽く触れておきます。 Pull型アプローチとは、ログやメトリクスをその持ち主がどこかに公開しておいて、FluentdやPrometheusなどの他の誰かに取得しに来てもらうアプローチを指します。 対となるPush型アプローチは逆に持ち主がログやメトリクスを直接対象に送りつけるというものです。 Push型アプローチはサーバ側で流量のコントロールが難しかったり、Rate Limit時などのリトライの責任がクライアント側に要求される一方で、Pull型アプローチはその点が単純という関係性にあります。 Kubernetesクラスタで素直にログとメトリクスを収集しようと思うと、大体Pull型のアプローチを採用することが多いのではないかと思います。 コンテナランタイムはコンテナの標準出力をファイルとして出力しているのでそれをFluentdやPromtailで収集し、メトリクスはPrometheus Exporterで公開してPrometheusがScrapeするといった感じです。 ここで考えたいリスクが、「 Podが削除される時までに本当にそのログ・メトリクスは収集されているのか 」というものです。 Kubernetes上でコンテナランタイムを司るkubeletは、Podの削除時にログのファイルを削除します。 Podが削除されれば当然Scrapeするためのエンドポイントも無効になるためメトリクスも収集できません。 削除直前に出力されたログやインクリメントされた Counter はどうなるのでしょうか。 恐らくそれらは欠損している可能性が高いです。 Fluentdは比較的すぐにログを読みますがそれでも読み込みが間に合わず欠損することはありますし、PrometheusのScrapeの間隔は一般に短くとも秒単位なので望みは薄いです。 kubeletにログファイルを削除される前にFluentdに読ませたい まずはログの欠損から考えていきましょう。 最初に思いつく対処はkubeletがログを削除するまでに遅延を入れたり、削除を無効化にするといったことだと思います。 それはこの辺のIssuesで議論されていますが、今のところこれといった方法はありません。(Grafana AlloyとかはKubernetes API経由でのログ取得にも対応していますが、こちらの削除タイミングも同様のはずです) github.com github.com かといって全てのPodにログ転送用のサイドカーをデプロイして送信というのも辛いのでどうにかプラットフォーム側で対処したいところです。 こんな時、eBPFはいつでも私達の銀の弾丸になってくれます。 (eBPFとは、という話は以前に書いたのでこちらをご覧ください) www.lifull.blog eBPFでunlinkat(2)を遅延実行させる アプローチとしては、eBPFでkubeletが発行するファイル削除のunlinkat(2)をhookしたら bpf_override_return でファイルを削除することなく終了コードを偽装して返し、裏でFluentdが対象のファイルを読み切ったことを確認出来たら実際の削除を行うというものです。 Fluentdは *.pos ファイルで読み込んだファイルのバイト数を記録しているため、これを見ればファイルを読み切ったことを確認できます。 まずはこんな感じにunlinkat(2)をhookしましょう。 bpf_override_return は kprobeの一部の関数 からしか利用できないことに注意してください。 // /sys/kernel/debug/tracing/events/syscalls/sys_enter_unlinkat/format SEC ( "tracepoint/syscalls/sys_enter_unlinkat" ) int sys_enter_unlinkat ( struct trace_event_raw_sys_enter *ctx) { u64 __pid_tgid = bpf_get_current_pid_tgid (); gid_t tgid = __pid_tgid >> 32 ; pid_t pid = __pid_tgid; struct task_struct *task = ( struct task_struct *) bpf_get_current_task (); u32 ppid = BPF_CORE_READ (task, real_parent, tgid); if (tool_config.this == tgid || tool_config.this == ppid) { return 0 ; } const char *pathname = ( const char *)ctx->args[ 1 ]; int flag = ( int )ctx->args[ 2 ]; // AT_REMOVEDIR // https://elixir.bootlin.com/linux/v6.10.6/source/include/uapi/linux/fcntl.h#L104 if (flag & 0x200 ) { return 0 ; } struct arg arg = { .pathname = pathname, }; bpf_map_update_elem (&args, &pid, &arg, BPF_ANY); return 0 ; } SEC ( "kprobe/" SYS_PREFIX "sys_unlinkat" ) int BPF_KPROBE (sys_unlinkat) { u64 __pid_tgid = bpf_get_current_pid_tgid (); gid_t tgid = __pid_tgid >> 32 ; pid_t pid = __pid_tgid; struct arg *argp = bpf_map_lookup_elem (&args, &pid); if (!argp) { return 0 ; } int zero = 0 ; struct event *eventp = bpf_map_lookup_elem (&unlinkat_heap, &zero); if (!eventp) { goto end; } eventp->tgid = tgid; eventp->pid = pid; eventp->uid = bpf_get_current_uid_gid (); eventp->pathname[ 0 ] = '\0' ; if ( bpf_probe_read_user (eventp->pathname, sizeof (eventp->pathname), argp->pathname) < 0 ) { goto end; } u8 directory[DIRECTORY_MAX]; if ( bpf_probe_read_kernel (directory, sizeof (directory), tool_config.directory) < 0 ) { goto end; } if (! filter_directory (directory, eventp->pathname)) { goto end; } bpf_override_return (ctx, 0 ); bpf_perf_event_output (ctx, &events, BPF_F_CURRENT_CPU, eventp, sizeof (*eventp)); end : bpf_map_delete_elem (&args, &pid); return 0 ; } bpf_override_return(ctx, 0); によって即座にkubeletに返るので、これでファイルの削除処理をスキップすることができます。 unlinkat_heap は PERCPU_ARRAY にしているのでnull byteを区切り文字にしています。 Kubernetesのノード上で実行することになり余計なunlinkat(2)も流れてくるため、 filter_directory でcontainerdのログディレクトリ以外のイベントは無視しなければなりません。 if (tool_config.this == tgid || tool_config.this == ppid) は、ファイル削除を遅延実行する関係上unlinkat(2)を自身も実行するため、無限ループ防止のために hostPID: true における自身のpidを this として受け取ってスキップしています。 あとは std::ffi::CStr::from_bytes_until_nul でユーザ空間から pathname を取得して、 *.pos ファイルと突合しながらFluentdが読み切るまで待機してファイルを削除するだけです。 そこそこ流量は多くなるので、mtimeを見て適当に *.pos ファイルはキャッシュしておきます。 while let Some (pathname) = unlink_rx. recv ().await { let current_mtime = std :: fs :: metadata ( & args.pos_file) . and_then ( | m | m. modified ()) . unwrap_or ( std :: time :: SystemTime :: UNIX_EPOCH); let needs_refresh = pos_cache. read ().await.mtime != current_mtime; if needs_refresh { let new_pos = parse_pos_file ( & args.pos_file); let mut cache = pos_cache. write ().await; cache.mtime = current_mtime; cache.entries = new_pos; } if let Some (offset) = pos_cache . read () .await .entries . get ( & pathname) . map ( | (offset, _) | * offset) { let path = std :: path :: Path :: new ( & pathname); if let Ok (metadata) = path. metadata () && metadata. len () != offset { let unlink_tx = unlink_tx. clone (); tokio :: spawn (async move { tokio :: time :: sleep ( std :: time :: Duration :: from_secs ( args.delayed_seconds, )) .await; if let Err (e) = unlink_tx. send (pathname. clone ()) { eprintln! ( "Failed to re-queue {}: {}" , pathname, e); } }); continue ; } } let result = std :: fs :: remove_file ( & pathname). or_else ( | e | { if e. kind () == std :: io :: ErrorKind :: IsADirectory { std :: fs :: remove_dir ( & pathname) } else { Err (e) } }); if let Err (e) = result { if e. kind () == std :: io :: ErrorKind :: DirectoryNotEmpty { if let Ok (entries) = std :: fs :: read_dir ( & pathname) { for entry in entries. flatten () { let entry_path = entry. path (). to_string_lossy (). to_string (); if let Err (e) = unlink_tx. send (entry_path. clone ()) { eprintln! ( "Failed to queue {}: {}" , entry_path, e); } } } let unlink_tx = unlink_tx. clone (); tokio :: spawn (async move { tokio :: time :: sleep ( std :: time :: Duration :: from_secs ( args.delayed_seconds, )) .await; if let Err (e) = unlink_tx. send (pathname. clone ()) { eprintln! ( "Failed to re-queue {}: {}" , pathname, e); } }); } else { eprintln! ( "Failed to remove {}: {}" , pathname, e); } } } kubeletが実行するGoの os.RemoveAll はファイルとディレクトリを区別せずにとりあえずunlinkat(2)してくるので、ユーザ空間側では中身を削除しながらディレクトリが空になるまで待機するようにしています。 本来は EISDIR を受け取ってからAT_REMOVEDIR付きのunlinkat(2)にフォールバックするんだと思いますが、今回はbpf_override_returnでEISDIRを握り潰してしまっているので、 os.RemoveAll 前提の気持ち悪さはありつつもこちらで削除まで責任を持ちます。 (ファイルのみが渡ってくる vfs_unlink を使えるといいんですが、 ALLOW_ERROR_INJECTION されておらずこちらは bpf_override_return が使えません) また一つだけ注意点があって、containerdは /var/log/containers 以下にログファイルを作成しますが、実際にはこれは /var/log/pods へのシンボリックリンクとなっているため、unlinkat(2)が呼ばれる pathname とFluentdの *.pos ファイルが指すファイルが異なる可能性があります。 私はFluentd側を修正せず *.pos ファイルを読む時についでにシンボリックリンクも解決してしまいました。 この辺もあって *.pos ファイルはキャッシュしています。 fn parse_pos_file (path: & std :: path :: Path) -> std :: collections :: HashMap < String , ( u64 , u64 ) > { let mut pos = std :: collections :: HashMap :: new (); if let Ok (file) = std :: fs :: read_to_string (path) { for line in file. lines () { let mut parts = line. split_whitespace (); if let ( Some (path), Some (offset), Some (inode)) = (parts. next (), parts. next (), parts. next ()) { let resolved_path = std :: fs :: canonicalize (path) . map ( | p | p. to_string_lossy (). to_string ()) . unwrap_or_else ( | _ | path. to_string ()); pos. insert ( resolved_path, ( u64 :: from_str_radix (offset, 16 ). unwrap_or_default (), u64 :: from_str_radix (inode, 16 ). unwrap_or_default (), ), ); } } } pos } これで晴れてkubeletの実行するunlinkat(2)が握りつぶされ、ユーザ空間で安全にFluentdのin_tailを待ってから遅延削除されるようになりました。 同じようなアプローチはPromtailなどでも有効なはずです。 PrometheusがCounterのインクリメントをScrapeするまでPodを待機させたい 次はメトリクスの欠損です。 Gauge(UpDownCounterの実装がGaugeなこともありますが、用途としてのGauge)などのMetric typeは割とどうでもいいんですが、Counterなどは意外と重要なケースもあってインクリメントが欠損してしまうと困ることがあります。 LIFULLでは大きめのKubernetesクラスタをマルチテナントで運用しているということもあり、PrometheusがScrapeする間隔は30秒程度が限界で、Podが削除されるまでの30秒間のインクリメントが失われてしまうという問題がありました。 もっと短い間隔で運用できるのであれば、Kubernetes 1.29から利用できるようになった KEP-3960: Introducing Sleep Action for PreStop Hook で雑にsleepしてもいいですが、問答無用で30秒も待ってしまうとPodのロールアウトが遅くなってしまうためそうもいきません。 なるべくロールアウトに影響を与えないよう、きっちりScrapeされるまでを待てると理想です。 SIGTERMを受け取ったら次回のScrapeまで待機するプロキシを挟む 素直にはScrapeされたことを検知できないと思うので、間にプロキシを挟ことにしましょう。 アイデアはシンプルで、以下のようなPrometheusとPrometheus Exporterの間に挟んでScrape時刻を記録するプロキシを作ります。 Prometheus ExporterはPod削除時に送られてくるSIGTERMでそのままGraceful Shutdownされてしまうので、終了直前のメトリクスを cachedMetrics に入れておいてSingleHostReverseProxyのErrorHandlerでPrometheus Exporterがシャットダウンして疎通しなくなったらそれを返すようにしています。 type CachedResponse struct { Body [] byte ContentType string } var ( lastScrape atomic.Value terminating atomic.Bool scrapeChan chan struct {} cachedMetrics atomic.Pointer[CachedResponse] ) targetURL, err := url.Parse(a.TargetURL) if err != nil { return xerrors.Errorf( "failed to parse target URL: %w" , err) } proxy := httputil.NewSingleHostReverseProxy(targetURL) proxy.ErrorHandler = func (w http.ResponseWriter, r *http.Request, err error ) { if cached := cachedMetrics.Load(); cached != nil { w.Header().Set( "Content-Type" , cached.ContentType) w.WriteHeader(http.StatusOK) _, _ = w.Write(cached.Body) return } http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable) } server := &http.Server{ Handler: http.HandlerFunc( func (w http.ResponseWriter, r *http.Request) { lastScrape.Store(time.Now()) if terminating.Load() { select { case scrapeChan <- struct {}{}: default : } } proxy.ServeHTTP(w, r) }), } そのためにこのプロキシはSIGTERMを受け取った時にPrometheus Exporterから最新のメトリクスを取得してからキャッシュし、 scrapeChan で待ち受けて次回のScrapeまで待機します。 SIGTERMの送信とEndpoint ControllerがEndpointを削除する処理は同時に行われるということは広く知られていて、LIFULLではこれへの対処のために全てのPodは終了時に数秒sleepするようにしています。 kubernetes.io 最新のメトリクスをSIGTERM時に取得する処理は、この設定とGraceful Shutdownの実装に依存している部分があることには注意したいです。 signal.Notify(quit, syscall.SIGTERM) <-quit ctx, cancel := context.WithTimeout(context.Background(), a.TerminationGracePeriod) defer cancel() t, ok := lastScrape.Load().(time.Time) if ok && !t.IsZero() { timeSinceLastScrape := time.Since(t) if timeSinceLastScrape > a.ScrapeWaitThreshold { if request, err := http.NewRequestWithContext(ctx, http.MethodGet, a.TargetURL, nil ); err == nil { if response, err := http.DefaultClient.Do(request); err == nil { defer func () { _ = response.Body.Close() }() if response.StatusCode < 400 { if body, err := io.ReadAll(response.Body); err == nil { cachedMetrics.Store(&CachedResponse{ Body: body, ContentType: response.Header.Get( "Content-Type" ), }) } } } } terminating.Store( true ) select { case <-scrapeChan: case <-ctx.Done(): } } } まとめるとこのプロキシは以下のように動きます。 常にPrometheusとPrometheus Exporterの間に入って最終Scrape時刻を記録しておく SIGTERMを受け取った時にScrapeWaitThreshold以内にScrapeされていなければ、Prometheus Exporterから最新のメトリクスを取得してキャッシュする 次回Scrape時にそのキャッシュからメトリクスを返して終了する これでPod終了直前にインクリメントされたCounterなどの値がPrometheusにScrapeされず欠損する問題を解決できました。 あとはPrometheus Operatorを使っているなら PodMonitor を、PodのアノテーションによるService Discoveryを利用している場合は metadata.annotations をこのプロキシに向けるだけです。 LIFULLではPodのアノテーションによるService Discoveryを利用しているため、 prometheus.io/wait: true と付与するとこのプロキシを注入するMutating Admission Webhookを開発して、このタイミングで prometheus.io/port もプロキシのポートに書き換えるようにしました。 これにより、利用者はPodアノテーションの付与をするだけで最小限のロールアウト遅延と引き換えに信頼性の高いメトリクスを得ることができます。 なお、KubernetesがSIGTERM送信後に諦めてSIGKILLを送るまでの spec.terminationGracePeriodSeconds のデフォルト値は30秒であるため、Scrape間隔が長いなどでこれを超えてプロキシが待機しなければならない場合はPodの spec.terminationGracePeriodSeconds を伸ばす必要もあります。 まとめ このエントリではKubernetesクラスタの可観測性基盤でよく採用されるPull型アプローチのトレードオフと、そのトレードオフへの対処を紹介しました。 一部コミュニティでは問題視されているものの、素直に利用していると意外と見落としがちな問題だと思っていて、お手元のKubernetesクラスタの監視を見直すきっかけになれば幸いです。 メトリクスはともかくログは欠損してしまうとそれなりに問題があるはずで、特にCronJobとかは実行ログを出力してから比較的すぐPodが終了することが多く、 successfulJobsHistoryLimit , failedJobsHistoryLimit を0にしていると直前のログはほぼ欠損していると考えてよいでしょう。 最近はトレースのSpanにログを持たせてしまうことも増えましたが、依然ログは重要な可観測性のシグナルだと思うので欠損がないように運用していきたいところです。 Fluentdのバッファはちゃんと設計しましょうとか、Prometheusの冗長化とか、Grafana Lokiは max_chunk_age の値に応じて送信が遅延してしまった同一ストリーム内の古いログを捨ててしまうので、fluent-plugin-grafana-lokiにパッチ当てて該当エラーの場合にUnrecoverableErrorを返すことでFluentdのsecondaryに流して、別ストリームとして送信し直すことで取りこぼさないようにしましょうとか、Pull型アプローチ由来以外の欠損を防ぐ話はまた別の機会に書きたいと思います。 ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
LIFULLは、国立情報学研究所(NII)が運営する情報学研究データリポジトリ(IDR)に、 LIFULL HOME'Sデータセット を提供しています。 本記事では、先日開催された IDRユーザフォーラム2025 のご報告として、LIFULL HOME'Sデータセットを活用した研究発表や、LIFULLとしての取り組みについてご紹介します。 IDRユーザフォーラム2025とは 2025年5月、新たにLIFULL HOME'Sデータセットを追加 LIFULL HOME'Sデータセットを活用した研究ポスター発表 不動産情報の俯瞰的閲覧を可能にするVR探索インタフェース 公示地価・人口動態予測データを用いた機械学習による将来賃料の予測 スタートアップセッションにおける企業賞の授与 住宅ローン税制は住宅購入者の利益になっているか LIFULLからの発表:不動産データのビジネス応用事例 おわりに 一緒に不動産データの可能性を広げるエンジニアを募集しています 前回および前々回のフォーラムの様子については、以下の記事でもご紹介していますので、あわせてご覧ください。 www.lifull.blog www.lifull.blog IDRユーザフォーラム2025とは IDRユーザフォーラムは、NIIが提供する研究データ基盤を活用した研究成果を共有し、データ提供者・研究者・利用者が一堂に会して議論する場です。 不動産、医療、交通、社会経済など、分野横断的なデータ利活用の事例が紹介される点が特徴で、年々参加者・発表内容ともに広がりを見せています。 2025年5月、新たにLIFULL HOME'Sデータセットを追加 2025年5月には、IDRにおける LIFULL HOME'Sデータセットの拡充が行われました。 これにより、より多様な分析・研究テーマへの応用が可能となり、学術研究と実社会をつなぐ基盤としての価値がさらに高まっています。 データセットの詳細は、以下のページで公開されています。 情報学研究データリポジトリ LIFULL HOME'Sデータセット LIFULLとしては、引き続き「実社会で蓄積されたデータを、研究を通じて社会に還元する」ことを重視し、IDRを通じたデータ提供を進めていきます。 LIFULL HOME'Sデータセットを活用した研究ポスター発表 IDRユーザフォーラム2025では、LIFULL HOME'Sデータセットを活用した研究発表が複数行われました。 ここでは、特に印象的だった2件のポスター発表をご紹介します。 不動産情報の俯瞰的閲覧を可能にするVR探索インタフェース 中山 裕紀 氏,大島 裕明 氏(兵庫県立大学) ポスター資料 本研究では、不動産情報をVR空間上で俯瞰的に探索できるインタフェースが提案されました。 LIFULL HOME'Sデータセットを用いることで、従来のリスト表示や地図表示では捉えにくかった空間的・構造的な特徴を、直感的に把握できる点が示されていました。 不動産情報とXR技術の融合は、住まい探しや都市理解の新しい可能性を感じさせる研究事例でした。 公示地価・人口動態予測データを用いた機械学習による将来賃料の予測 佐藤 豪栄 氏,秦野 亮 氏,西山 裕之 氏(東京理科大学) ポスター資料 こちらの研究では、LIFULL HOME'Sデータセットに加えて、公示地価や人口動態予測データを組み合わせ、将来の賃料を機械学習によって予測する手法が提案されました。 不動産市場の将来予測という社会的ニーズの高いテーマに対し、オープンデータと民間データを組み合わせた分析は、IDRならではの研究アプローチと言えます。 スタートアップセッションにおける企業賞の授与 今回のIDRユーザフォーラム2025では、スタートアップセッションも開催されました。 LIFULLは企業賞として、以下の研究発表を表彰させていただきました。 住宅ローン税制は住宅購入者の利益になっているか 河瀬 豊 氏(神戸学院大学) 発表資料 本研究は、住宅ローン税制が実際に住宅購入者の利益につながっているのかを、データに基づいて検証したものです。 不動産・住宅政策とデータ分析を結びつけた点、そして社会的インパクトの大きさを評価し、LIFULLとして企業賞を授与させていただきました。 LIFULLからの発表:不動産データのビジネス応用事例 データ提供者セッションでは、LIFULLからも発表の機会をいただきました。 speakerdeck.com このセッションでは、実際の不動産データがどのようにビジネスの現場で活用されているかを、具体的な事例と技術アプローチの観点から紹介しました。発表はデータ提供者セッションにて行われ、参加者のみなさまにも幅広い関心を寄せていただきました。 発表では、以下のようなトピックに触れました。 「おとり物件」の防止に向けた取り組み:不動産情報の信頼性向上を目的とした取り組みと技術的背景の紹介 不動産売却査定におけるLLM活用:大規模言語モデルを用いた査定支援サービスの事例 LIFULL HOME'Sデータセットの拡充とその活用可能性:2025年5月に追加されたデータの内容と、これを活かした応用事例の可能性 この発表を通じて、データ利活用が不動産ビジネスにもたらす価値を、研究者・実務者双方の視点から捉えていただくことを目指しました。 LIFULLでは、今後もデータ駆動型サービスの可能性と実装事例を共有し、研究コミュニティとの対話を深めていきたいと考えています。 おわりに IDRユーザフォーラム2025を通じて、LIFULL HOME'Sデータセットが多様な研究テーマに活用されていること、そして研究成果が社会課題の理解や解決に寄与しうることを改めて実感しました。 LIFULLは今後も、 データ提供を通じた研究支援 学術と実社会をつなぐ取り組み 不動産・住まい領域におけるデータ利活用の発展 を継続していきます。 研究者の皆さま、データ利用者の皆さま、そしてIDR事務局の皆さま、改めてありがとうございました。 一緒に不動産データの可能性を広げるエンジニアを募集しています IDRユーザフォーラム2025を通じて、LIFULL HOME'Sデータセットが研究・ビジネスの両面で多様な価値を生み出していることを改めて実感しました。 これらの取り組みは、エンジニアリング・データサイエンス・AI技術の積み重ねによって支えられています。 LIFULLでは現在、不動産データやAI技術を活用し、社会課題の解決に取り組むエンジニアを積極的に募集しています。 データ基盤、機械学習、LLM活用、プロダクト開発などに関心のある方にとって、実データを使いながら挑戦できる環境があります。 エンジニア向けの募集職種一覧は、以下の採用ページをご覧ください。 hrmos.co 研究コミュニティと連携しながら、実社会にインパクトを与えるプロダクトをつくりたい方、不動産・住まい領域のデータ利活用に興味のあるエンジニアの皆さまのご応募をお待ちしています。
はじめに こんにちは、基盤グループでインフラの運用管理を担当している布川です。 今年の10月28日にAWS目黒オフィスにて、堅牢で回復力に優れたシステムの構築について学ぶAWS Architectural Resilience Dayが開催されました。 本イベントには弊社から基盤グループのメンバー3名が参加しました。本記事では、その内容や得られた学びをレポートとしてご紹介します。 はじめに 高いレジリエンスの実現に向けた6つのステップ 1. システムの中でビジネスクリティカルな部分を明確にする 2. 個々のコンポーネントに具体的な目標を設定する 3. 実際に設計に落とし込む 4. 現在の設計で目標を達成できるか?テストする 5. 適切な監視体系を構築する 6. 定期的に振り返りを実施する 講義を終えて 弊社のシステムに置き換えた話 実務で意識したいこと おわりに 高いレジリエンスの実現に向けた6つのステップ 講義では、システムを停止させないこと、また停止した場合でも影響を最小限に抑えることを目的として、システムのレジリエンスを高めるための6つのステップが示されました。 また、ハンズオンを通じて、AWS上に構築したシステムでこれらのステップを実践するための具体的な方法について学びました。 1. システムの中でビジネスクリティカルな部分を明確にする サービスを構成するシステム全体を見たとき、すべてのコンポーネントが同じ重要度を持つわけではありません。 まずは、ここだけは止めてはならない、止まったとしても最優先で復旧すべき、といったビジネスクリティカルな部分を明確にすることが重要だと学びました。 たとえば、弊社が運用する不動産ポータルでは、最低限のサービスレベルとして、地図サービスなど外部依存部分を除き、物件検索・問い合わせ、物件更新等の基本機能が一通り動く状態を定義しています。一方で、SEOや読み物コンテンツなど、ユーザ獲得を目的とした機能はこの範囲から外して考えています。 2. 個々のコンポーネントに具体的な目標を設定する 次に、ビジネスクリティカルと定義したコンポーネントについて、レジリエンスに関する具体的な目標値を設定します。講義では、次のような観点から整理していました。 項目 High Availability(高可用性) Disaster Recovery(災害復旧) 対象とする障害 小規模で頻度の高いイベント まれだが影響の大きい障害 具体例 ネットワークの問題、負荷スパイクなど 自然災害、技術的障害、人的ミスなど 対処方法 自動緩和、自己回復 事前に備えた復旧対応 評価指標 通期の平均値 MTBF ÷ (MTBF + MTTR) など 単一イベントでの測定 RPO, RTO など RTO(目標復旧時間)やRPO(目標復旧時点)は、ビジネス上どこまでの損失を許容できるかを元に決定します。たとえば、あるECサイトで1時間あたりの売上が1,000万円、サイトダウン時に許容できる機会損失額を1,000 万円(年 1 回まで)とした場合、RTOは1時間という考え方になります。 ハンズオンではAWS Resilience Hubを用いて、CloudFormationで管理されているリソース群にRPO, RTOを設定し、現在の構成がその目標を満たしているかを評価しました。また、S3のバージョニング有効化やDynamoDBのバックアップ設定などを追加し、要件を満たすまでの流れを体験しました。 3. 実際に設計に落とし込む 復旧目標が定まると、自己回復しない障害が発生した際に、目標時間内に復旧するための設計を考えられるようになります。 設計における基本方針は静的安定性の確保です。静的安定性とは、「自己回復しない障害が発生した時、システムをこちらから操作・変更しなくても復旧してくれる性質」のことを指します。 障害は大まかに、発生頻度の高い順に以下のように分類できます。 コードのデプロイや設定ミス(デプロイ失敗、証明書失効など) コアインフラストラクチャの障害(データセンター障害、ホスト障害など) データや状態の問題(データ破壊) めったに起こらないシナリオ(自然災害、全インターネット障害、電力等のサプライヤー障害など) 今回の講義では、特に4のようなレアケースでも重要業務を継続できるよう回復力を確保する設計に焦点が当てられていました。そのための方針として、APIや管理画面といったコントロールプレーンの操作を前提とせず、データプレーンのみで自律的に切り替わる構成とすることが重要である、という説明がとても参考になりました。(参考AWSドキュメント: コントロールプレーンとデータプレーン ) この前提のもと、マルチAZやマルチリージョンといった構成を検討します。ただし、コストをかけるほど復旧は早くなる一方で、金銭・運用負荷・複雑性といったトレードオフも発生します。抑えたい損失と支払うコストを天秤にかけ、現在の事業フェーズに合った手段を選択することが重要です。 ディザスタリカバリ戦略 出典: クラウド内での災害対策オプション (AWSドキュメント) 講義では深くは触れられていなかったものの、1〜3のような比較的発生頻度の高い障害に対しても、静的安定性を意識した設計を行うことが重要だと感じました。 デプロイや設定ミスに対してはCI/CDの整備やCanaryリリース、設定のIaC管理等を行うことでリスクを低減でき、インフラ障害に対してはマルチAZ等の冗長な構成を採用すること、データ障害に対しては定期的なバックアップやガードレールの導入を行うといったことが対策として考えられます。このような取り組みによって静的安定性を確保しながら、障害による影響や発生自体を抑える環境を作ることが求められると感じました。 ハンズオンではマルチリージョン構成のもとで、CloudFrontのオリジン(S3)のフェイルオーバーや、Route53によるALBの振り分け先のフェイルオーバーを実際に試しました。 4. 現在の設計で目標を達成できるか?テストする 現在の設計が確実に復旧目標を達成できることを確認するために、本番相当の環境、もしくは実際の本番環境のうちの一部のトラフィック群に対して、レジリエンステストを実施することを学びました。 ここでは、回復力を測る対象となる障害を意図的にシステムへ注入し、想定通りの挙動によって定常状態を維持、もしくは目標時間内に復旧できるかを確認します。 AWSでは、Resilience Hubの機能の一つであるFault Injection Service (FIS)を利用することで、電源の中断やインスタンス障害など、通常は再現が難しい障害シナリオを安全にテストできます。 ハンズオンでは、この後に学ぶ監視体系の構築と合わせて、FISを用いたAZの電源中断シナリオやリージョン障害発生時のシナリオを注入し、これまでに学んだレジリエンス対策を施したサービスが、目標時間内に復旧できるかどうかを、Cloudwatch SyntheticsのCanaryを用いて確認しました。 5. 適切な監視体系を構築する 目標とするレジリエンスを達成するシステムを設計・テストし、運用に乗せた後は、ユーザ体験の把握や障害の検知・影響判断、原因調査や復旧を支援するための監視が必要になります。 ただし、過剰な計測はデータ疲れを招くため、ビジネス目標を踏まえ、アプリケーションにとって重要な指標に絞って監視することが重要であることを学びました。 講義で紹介されていた監視体系の一例を整理すると、以下のような情報をバランスよく収集することが有効であると感じました。 リクエストの文脈:いつ・誰が・どのAPI/機能で・どこのAZ/リージョンで・何をしようとしていたのか 成否と結果:レスポンスコードやエラーの種類・原因 レイテンシと内訳:全体の処理時間や、接続・キャッシュやDB上の処理・アプリ上の内部処理にかかった時間 リソースの使用状況:キャッシュヒット等のリクエスト単位で計測できるもののほか、CPU使用率等の継続的に測定できるメトリクス 6. 定期的に振り返りを実施する 最後に、運用中に実際の障害が発生した後、どのように振り返りを行うべきかについて学びました。講義で紹介された事例では、以下のような観点で情報が整理されていました。 障害の概要:障害の影響、経緯、対策等のハイレベルな情報 メトリクス:障害の影響や問題の特定に利用したメトリクスのグラフ 影響範囲:障害の影響を受けたユーザ数、時間や程度、ビジネスへの影響 タイムライン:障害中に発生したすべてのイベントや、実施したプロセスを時系列で整理 ラーニング:対応や分析を通じて得られた学び アクションアイテム:改善策を優先度・責任者とともに明確化 特に重要な点として、個人を非難せず、プロセスや仕組みにフォーカスすることが強調されていました。 弊社でも障害対応のナレッジを蓄積するスペースを運用しているため、この考え方は共感しやすい内容でした。 講義を終えて 本講義を通して、堅牢で回復力の高いシステムをどのように構築するかを、段階的・体系的に学ぶことができました。なお、細かな説明については一部省略している点をご留意ください。 これまでふわっとした理解にとどまっていたレジリエンスについての考え方や具体的な手段について、このタイミングで整理して学べたことはとても有意義だったと感じています。 弊社のシステムに置き換えた話 弊社には KEEL(キール) と呼ばれるKubernetesベースの独自のアプリケーション実行基盤があり、多くのアプリケーションがその上で稼働しています。 マルチAZ構成を前提としているため、自然災害に対する静的安定性が確保されており、この点は大きな強みだと感じました。 また、運用中のサービスが必要なレジリエンス要件を満たしているかを定期的に確認することも重要だと感じました。 弊社では、サイバー攻撃を含むリスクに備えたマルチアカウント構成の事業継続計画(BCP)を策定しており、災害時などの緊急時において、損害を最小限に抑えつつ主力事業の継続や早期復旧を可能とするため、手順・担当者・作業範囲などをあらかじめ定めています。こちらについて、現状の対応は主にバックアップとリストアが中心であり、パイロットライト構成などを検討する余地もあると感じました。 このように、ハードウェア・論理的構成の両面で適切なレベル・手段を選びながら、想定されるさまざまな障害への対応策を講じておくことで、より堅牢なシステムを実現できるのだと理解しました。 実務で意識したいこと 基盤Gでは、運用に必要なアプリケーションも含めて開発・運用を行っています。 ステップ3でも触れられていましたが、システムが持つ静的安定性を最大限に活かすためのアプリケーション設計には、意識して取り組む必要があると感じました。 また、基盤グループでのこれまでの経験から、障害の原因の多くは人為的ミス、たとえばデプロイの失敗や設定不備であることが多いということは明らかです。 そのため、十分に統合テストを実施すること、リリースにあたっては影響範囲を明確にしつつ関係者と合意を取り、動作確認を行う体制を整備すること、といった基本的なことを積み重ねた上で、今回のようなレジリエンス設計や障害対応の議論ができる状態を作っていくことが重要だと感じました。 おわりに 本記事では、AWS Architectural Resilience Dayで学んだ、堅牢で回復力に優れたシステム構築に関する考え方や、その実践的な内容についてご紹介しました。 この記事が、レジリエンス向上に向けた動き方を検討する際の一助となれば幸いです。最後までお読みいただき、ありがとうございました。 最後に、LIFULLではともに成長していける仲間を募集しています。ご興味をお持ちいただけましたら、ぜひ以下のページもご覧ください。 hrmos.co hrmos.co
1. 始めに こんにちは。LIFULLでエンジニアをしている稲垣です。 2025年10月の3日間、AWSが提供する「AI駆動開発ライフサイクル(AI-DLC)Unicorn Gym」の研修に参加しました。この研修では、6つのチームに分かれて、AI-DLCを活用しながら実際のプロジェクト課題に取り組みました。 私たちのチームが取り組んだのは、「サポートが終了したサービスの新基盤への移行計画」です。具体的には、Amazon Linux 2のサポート終了(EOL: End of Life)への対応として、既存システムを新しい基盤へ移行する計画の策定に取り組みました。 このようなOSマイグレーションでは、以下のような課題に直面します: 取り組むべき手順や優先順位が不明確 移行オプションの調査と比較に数日かかる リスクの洗い出しが担当者の経験に依存し、見落としが発生しやすい この記事では、これらの課題に対してAI-DLCがどのように解決策を提供してくれたのか、実際の開発プロセスと得られた学びを共有します。特に、AIがルーティンタスクを処理する間に、チームは問題解決や意思決定に集中できる「ダイナミックなチームコラボレーション」がどのように実現されたかをお伝えします。 1. 始めに 2. 研修の内容とカリキュラム AI-DLCとは AI-DLCの開発フェーズ 私たちのチームの課題 私たちのチームの取り組みの流れ 私たちのチームの取り組みの流れ図 3. AI-DLCを活用した開発プロセス AI-DLCの基本サイクル 当初の構想とAI-DLCによる方針転換 Inception Phaseでの実践 Construction Phaseでの実践 4. 直面した課題とAI-DLCでの解決 5. 研修を通じて得られた気付きや学び AI-DLCを使った開発スタイルについての気付きと今後の活用 チーム開発での学び OSマイグレーションという課題から得た学び 6. まとめ 2. 研修の内容とカリキュラム AI-DLCとは AI-DLC(AI-Driven Development Lifecycle)は、AIが開発プロセスを主導する開発手法です。単なるコード生成ツールにとどまらず、要件定義から設計、実装、テスト、運用まで、開発の各フェーズでAIがタスク分解や実装を主導し、人間がレビュー・承認を行います。今回の研修では、Amazon Q Developerを使用してAI-DLCを実践しました。 AI-DLCの開発フェーズ AI-DLCは大きく3つのフェーズで構成されています: Inception Phase(構想フェーズ) - 現状分析、技術選定、計画策定を行うフェーズ Construction Phase(構築フェーズ) - 実装、テスト、ドキュメント作成を行うフェーズ Operation Phase(運用フェーズ) - 本番環境へのデプロイとインシデント管理を行うフェーズ 私たちのチームの課題 研修では6つのチームがそれぞれ異なる課題に取り組みました。私たちのチームは「サポートが終了したサービスの新基盤への移行」という課題に挑戦しました。 この課題は、参加チームの中でも比較的珍しいものでした。AWSの担当者によると、「AI駆動開発ライフサイクル(AI-DLC)Unicorn Gym」では、これまで主にアプリケーション開発の課題が扱われてきましたが、OSマイグレーションという領域でAI-DLCを活用するのは初の事例とのことでした。 具体的には、以下の点でほかのチームとは異なる挑戦となりました: 活用事例が少ない :インフラ移行という領域でのAI-DLC活用は前例が少ない 技術的な複雑さ :既存システムの完全な理解と、複数のAWSサービスにまたがる変更が必要 リスク管理の重要性 :本番環境への影響を最小限に抑える慎重な計画が求められる この特徴が、AI-DLCの新しい活用方法を模索する良い機会となりました。 私たちのチームの取り組みの流れ 今回の研修では、このAI-DLCのフェーズに沿って、OSマイグレーション計画を進めました。以下は、私たちのチームが実際に取り組んだ内容です。 Inception Phase(構想フェーズ) 既存システムの構成調査とAWSインフラの棚卸し 移行方法の比較検討と技術的制約の分析 ユニット(AI-DLCで用いる作業単位)への分割と依存関係の整理 Construction Phase(構築フェーズ) 以下の作業を並行して実施(研修時間内では途中まで): リスク管理台帳の作成と対応策の検討 技術調査レポートや運用手順書の作成 ベースイメージの作成 私たちのチームの取り組みの流れ図 図1:私たちのチームの取り組みの流れ。(Inception PhaseからConstruction Phaseの途中まで実施) 3. AI-DLCを活用した開発プロセス 本章では、AI-DLCを実際どのように活用して開発を進めたかを紹介します。 AI-DLCの基本サイクル AI-DLCでの開発は、以下のサイクルを繰り返します: AIにプランを作らせる 人がプランをレビュー AIがプランを修正 AIがプランを実行 人が結果を確認 図2:AI-DLCの基本サイクル。このサイクルを繰り返して成果物を完成させる 当初の構想とAI-DLCによる方針転換 プロジェクト開始時、私たちはAmazon Linux 2のEOL対応として、Amazon Linux 2023へのOSリプレイスを検討していました。既存のAmazon EC2(仮想サーバー)環境を維持したまま、OSのみをアップグレードする方針です。この方針は、既存システムへの影響を最小限に抑えられるという理由から選択しました。 しかし、AI-DLCを活用して検討を進める中で、方針が大きく変わりました。AIが生成した技術調査レポートで複数の移行オプションを比較した結果、 Amazon ECS(コンテナ実行基盤)へのコンテナ化 が望ましいという提案がありました。 理由は以下の通りです: 環境の再現性(不変性)の向上により、デプロイやロールバックが容易になる 将来的なミドルウェアアップグレードの基盤となる 長期的な保守性と運用効率の向上が期待できる コンテナ化という選択肢自体は、チーム内で漠然と認識していました。しかし、AI-DLCが生成したレポートを見るまでは、その具体的なメリットや実現可能性が明確ではありませんでした。AIが各オプションのメリット・デメリット、工数、コストを整理してくれたことで、チームでの議論が活性化しました。「環境の再現性(不変性)の向上」という観点や、「将来的なアップグレードの基盤」という長期的な視点は、AIの提案によって初めて明確になった部分です。 チームでの議論を経て、最終的にコンテナ化の方針で Construction Phaseを進めることに決めました。これは、AI-DLCが単なる作業支援ツールではなく、技術的な提案を行い、プロジェクトの方向性の決定に良い影響を与えてくれました。 図3:AI-DLCによる技術選定の変化。OSリプレイスからコンテナ化へ方針転換 Inception Phaseでの実践 Inception Phaseでは、現状分析と技術選定を行いました。 AIと人間の役割分担 AI-DLCでは、AIがルーティンタスクを処理することで、人間は問題解決や意思決定に集中できます。 AIが担当: 既存システムの構成情報の収集と整理 複数の移行オプション(OSリプレイス vs コンテナ化)の比較レポート生成 各オプションのメリット・デメリットの洗い出し 人間が担当: 移行方針の最終決定(ECSコンテナ化を選択) ビジネス要件との整合性確認 技術的な実現可能性の判断 Construction Phaseでの実践 Construction Phaseでは、計画策定とリスク管理を行いました。 AIと人間の役割分担 AIが担当: ユニットへの分割案の生成 依存関係図の作成 リスク項目の網羅的な洗い出し リスク管理台帳の初稿作成 人間が担当: タスクの優先順位付け リスクの重要度評価と対応策の決定 実装スケジュールの調整 たとえば、依存関係図の生成では: 人間がシステム情報を提供 AIがドキュメントを分析し、依存関係図を自動生成 人間が図をレビューし、不足部分を指摘 AIがフィードバックを反映して修正 チームが図を見ながら移行順序を議論 Mob Construction(いわゆるモブレビュー/モブ作業。チーム全体でのフィードバックと問題解決)の実践: Mob Constructionは、AI-DLCにおけるチーム開発の手法で、AIが生成した成果物に対してチーム全員でレビューとフィードバックを行い、より良い解決策を議論する取り組みです。 リスク管理時には、AIが洗い出したリスクをチームでレビューしました。「このリスクは優先度が高い」「この対応策では不十分」などフィードバックを行い、チームでリスク対応策をブレインストーミングし、実装の優先順位を議論して決定しました。 AIがリスクの洗い出しや台帳作成を処理している間に、チームメンバーは技術的な実現可能性の議論、過去の経験からの知見共有、より効果的な対応策の検討に集中できました。これにより、作業効率が向上しただけでなく、チーム全体の技術力向上にもつながりました。 4. 直面した課題とAI-DLCでの解決 課題1:技術選定の複雑さ Amazon Linux 2023への直接移行とECSコンテナ化、どちらを選択すべきか判断が難しい状況でした。 AI-DLCの活用: 複数の移行オプションを比較した技術調査レポートを生成 各オプションのメリット・デメリット、工数、コストを整理 チームでの議論の材料として活用 結果: 長期的な視点でECSコンテナ化を選択する判断ができました。 課題2:リスク管理の網羅性 OSマイグレーションには多くのリスクが潜んでおり、見落としがないか不安でした。 AI-DLCの活用: 技術的なリスクを網羅的に洗い出し リスク管理台帳の初稿を作成 リスク評価マトリックスを生成 結果: 30個以上のリスクを識別し、優先順位をつけて対応策を検討できました。 課題3:ドキュメント作成の負荷 移行計画書、技術調査レポート、運用手順書など、多くのドキュメントが必要でした。 AI-DLCの活用: ドキュメントの初稿を自動生成 フォーマットの統一 情報の整理と構造化 結果: ドキュメント作成の時間を大幅に削減し、内容のレビューと改善に時間を使えました。 5. 研修を通じて得られた気付きや学び AI-DLCを使った開発スタイルについての気付きと今後の活用 AIは技術的な提案も行う 当初はOSリプレイスを検討していましたが、AI-DLCが生成した技術調査レポートでECSコンテナ化を提案され、最終的にその方針を採用しました。AIは単に指示されたタスクをこなすだけでなく、より良い選択肢を提示することもあると実感しました。 今後の業務では、新しいプロジェクトの技術選定時に、AIに複数のオプションを比較させることで、より客観的な判断材料を得られると考えています。 プロンプトの重要性 AIに何を依頼するか、どのようにコンテキストを与えるかで、成果物の質が大きく変わります。効果的なプロンプトを書くスキルが、今後ますます重要になると感じました。 今回の研修で効果的だったプロンプトの要素: 役割の明確化 : 「あなたは熟練したクラウドエンジニアです」のように、AIに期待する専門性を明示 具体的なタスクの指定 : 「aidlc-docs/inception/migration_plan.md ファイルにステップを記載してください」のように、成果物の形式と保存場所を明確に指定 作業プロセスの指示 : 「計画を作成したら、私のレビューと承認を求めてください」のように、レビューのタイミングを明示 制約条件の設定 : 「独自の判断や決定は行わないでください」のように、AIが勝手に判断しない範囲を明確化 日常業務では、ドキュメント作成や技術調査の際に、これらの要素を含めたプロンプトを作成することで、AIの支援を最大限活用できます。 レビューの重要性 AIが生成した内容をそのまま使うのではなく、必ずレビューして修正する必要があります。AIの提案を批判的に評価する能力が求められます。 コードレビューと同様に、AIが生成した成果物のレビューを習慣化することで、品質を担保しながら効率化を実現できます。 チーム開発での学び 役割分担の明確化 AIが得意なタスクと人間が得意なタスクを明確に分けることで、効率的に作業を進められました。 AIが得意なタスク: 情報の収集と整理(既存システムの構成情報、移行オプションの比較) ドキュメントの初稿作成(技術調査レポート、リスク管理台帳) 網羅的な洗い出し(リスク項目、依存関係) 定型的な作業(タスク分割、フォーマット統一) 人間がやるべきタスク: 最終的な意思決定(移行方針の選択、優先順位の決定) ビジネス要件との整合性確認 技術的な実現可能性の判断 AIが生成した成果物のレビューと修正 チーム内での議論とコンセンサス形成 この役割分担により、AIがルーティンタスクを処理する間に、人間は問題解決や意思決定に集中できました。 OSマイグレーションという課題から得た学び 活用事例が少ない領域でのAI活用 一般的な開発タスクではない領域でも、AI-DLCは有効に活用できることがわかりました。特に、複数の移行オプションを比較する技術調査レポートの生成や、30個以上のリスクを網羅的に洗い出す作業では、AIの支援が大きな価値を発揮しました。 段階的なアプローチの重要性 大きな移行プロジェクトを複数のユニットに分割し、依存関係を整理することで、リスクを管理しながら進められることを学びました。 6. まとめ この研修を通じて、AIがルーティンタスクを処理する間に、チームは問題解決や意思決定に集中できる「ダイナミックなチームコラボレーション」を実践的に学ぶことができました。 また、OSマイグレーションという活用事例の少ない領域でも、AI-DLCは有効に活用できることを実証できました。 LLMは、単なるコード生成ツールではありません。AI-DLCという開発手法を通じて、LLMを開発のライフサイクル全体で活用することで、チームの生産性と創造性を高めることができます。今後の業務でも、この経験を活かして、より効率的で質の高い開発を実現していきたいと思います。 最後に、LIFULLではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co