イベント
イベントを探す
本日開催のイベント
明日開催のイベント
ランキング
カレンダー
マガジン
マガジンを読む
マガジン
技術ブログ
書籍
動画
動画を見る
グループ
グループを探す
グループを作る
イベントを作成・管理
学生の方はこちら
ログイン
|
新規会員登録
TOP
グループ
株式会社メルカリ
ブログ
トップ
イベント
マガジン
ブログ
株式会社メルカリ の技術ブログ
全270件
2023/10/23
【書き起こし】フロントエンドチームの技術課題評価システム改善の取り組み – tokuda109【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 フロントエンドチームの技術課題評価システム改善の取り組み 」の書き起こしです。 @tokuda109:それでは、「フロントエンドチームの技術課題評価システム改善の取り組み」というタイトルで発表します。 まずは自己紹介です。@tokuda109といいます。2019年にフロントエンドエンジニアとしてメルペイに入社し、さまざまなプロダクト開発を担当してきました。プロダクト開発以外では、技術評価システムの改善などに携わっています。 今日お話しする内容は、四つのセクションにわかれます。一つ目が、フロントエンドチームの採用プロセスについて。二つ目が、技術課題。採用プロセスの一つが、技術課題です。三つ目が本発表のメイントピックで、技術課題を評価するときに使う評価チェックシートについて紹介します。そして最後がまとめです。 これが基本的な採用プロセスで、全部でこれだけのステップがあります。技術課題は、採用プロセスの2番目のステップで、候補者に簡単なアプリケーションの実装をお願いしています。 候補者が課題を提出すると、評価者が2人アサインされ、評価システムに沿って評価をしていきます。 技術課題は、上記の通りです。このスライドで記載されている内容は、公平性を担保するために、採用ページに記載されているものから引用しています。 まず、候補者に求められる必須条件として、HTMLとCSSを用いた堅牢なUIを実装できること。次に、JavaScriptに関する知識があり、UIライブラリやフレームワークを用いた開発経験があること。これらを満たしているかを、技術課題を通して判断しています。 次に課題内容として、「Web技術全般に関する高度な知識と技術力で、プロダクト開発に貢献できるかどうか」を判断するために、簡単なアプリケーションの実装をお願いしています。 評価では、独自の評価システムを使っています。技術力を評価するための方法は、外部サービスとして使えるものからフレームワークとして提供されているものなど、さまざまなものがありますが、私たちは独自の評価システムを使っています。 独自路線になった経緯はわかっていませんが、単純な点数だけを評価しているわけではないからだと個人的には考えています。基本は技術力を評価しますが、ソースコードから読み取れる候補者のカルチャーフィットやチームにジョインした後、バリューを発揮して業務できる方かを総合的に見ており、技術課題の点数は評価の一部でしかありません。 ただ、独自のものを使ってうまく機能させるためには、やってみると意外と大変で、さまざまな問題が発生しました。技術課題の評価をするにあたって課題となったことが二つあります。 一つ目が、提出物の評価に時間がかかること。評価システムが体系化していないことで、時間が思ったよりかかったり、細かく見すぎていて評価に時間がかかるということが多々発生していました。 次に、一定の評価基準で評価することができないこと。評価者によって重要視する項目が異なることで評価基準が一定にならず、評価が割れることが多々発生しました。 これらの解決になったのが、ペア評価と評価チェックシートの二つです。ペア評価は二人で画面共有しながら、一緒に技術課題を評価する方法です。一人がアプリケーションを起動し、画面共有しながらペアとの評価を主導し、ペアは議論した内容をメモするという役割分担です。 評価チェックシートは、確認すべき評価観点をリスト化したものです。それを基に提出された課題を評価すれば、一時間で評価が完了する仕組みになっています。評価者によって重要視する評価観点が異なることを防ぎ、個人の恣意的な評価を平準化します。また、評価漏れを防ぐ目的もあります。 評価チェックシートの内容について、細かく見ていきます。この図は今回のイベント用に作成したもので、実際の評価観点とは中身が異なりますが、基本的なフォーマットは同様です。 このチェックシートは、技術課題の評価と総合的な判断の二つのセクションで構成されます。まず技術課題の評価ですが、一つの行が一つの評価観点になっていて、現時点で全部で40個ほどの評価観点があります。 一番左に評価観点があり、「◯◯を使った品質の高いコードになっているか」「◯◯対応ができているか」のような大きなくくりとして、何を評価するのかが分類分けされています。 次に、B列の採点方法ですが、評価ポイントと採点の二つが記載されています。評価ポイントは、「どのような箇所を確認するのか」「どういう実装していると評価するのか」などの確認ポイントが記載されています。それをもとに確認し、記載されている採点基準に当てはまる点数を元に、スコアを付けます。 最後に、D列の採点時のメモですが、ここはペア評価時にペアの方がメモをしていくためのスペースです。これを上から順番に行い、全て評価が終わると点数が算出されます。その採点をもとに、総合的な判断のセクションに進みます。 ここでは、レジュメや採点、作業内容をもとに、「候補者がカルチャーフィットするのか」「チームにジョインしたときに、バリューを発揮して業務をできる方なのか」を評価者同士で議論し、次のインタビューに進めるかどうかを判断しています。 次に、評価チェックシートの変遷です。評価チェックシートは最初からあのフォーマットになっていたわけではなく、何回もアップデートを繰り返したことで、現在のフォーマットに落ち着きました。 それまでに三つのフェーズがあり、フェーズ1では評価観点が体系化されておらず、共通評価の共通認識ができていないところからスタートしました。評価に時間がかかる問題や、評価基準が安定しない問題が発生したのも、このフェーズです。 評価観点を体系化し始めて共通認識を揃え始めたのが、フェーズ2です。ここで評価チェックシートの原型ができあがりましたが、改善点はたくさんありました。 具体的には「〇〇が設定されているかどうか」のような単なるチェックリストのようになっており、実装内容を評価する評価観点はまだほとんどありませんでした。 次に、定期的にミーティングをすることで、共通認識を評価観点に落とし込めるようになったのが、フェーズ3です。2年ほど定期的にこれを続け、最近になってこのフェーズに到達できました。 まだ改善点はたくさんありますが、ただのチェックリストから実装内容を評価することができるところまで改善できたことは、大きな進歩だと思います。 次に、例として「評価観点:TypeScript」を紹介します。 最初は、TypeScriptで実装されているかどうかという評価観点で、これでは「TypeScriptを使っているからいいのか」「TypeScriptを使って、型安全な実装できていればいいのか」がわからず、評価者によってばらつきが出ます。体系化を始めたときに一番議論が紛糾したのが、この観点です。 まず出されたのは、「TypeScriptで実装されていない時点で、全体的に品質の高いコードではない」と言えるという意見。次に、「TypeScriptで実装されていた方がいいが、テストを書いたりうまく設計することで補い、他の観点も踏まえて品質が高いかどうかを判断すればいいのではないか」という意見でした。 この二つの意見を「『TypeScriptを使っていない』は、一つの評価観点が全体に与える影響が大きすぎる」「『別の観点で補えているか』は、別の観点を独自に当てはめて評価している」と整理しました。 元々がTypeScriptで実装されているかという評価観点でしたが、TypeScriptを使うことで、何を解決したいのかを評価観点としてチェックできるように、チェックシートを更新しました。 TypeScriptで解決したい問題として「型があることで、アプリケーション内の処理で型安全を担保できる」という点があると思います。APIデータやイベントハンドリングなどのアプリケーションの外側から渡されるデータを適切に型付けしない場合、どのようなデータ型も許容してしまいます。 最終的にはそのような点を評価観点として記載し、APIデータやイベントハンドリングなどの箇所を重点的に見るように、評価項目として記載しました。 評価チェックシートを何年もかけて更新してきました。最初はただのチェックリストでしたが、徐々に改善され、メルペイ・メルコインで活躍できる方であると判断するための仕組みとして機能するものになりました。 もし、メルペイ・メルコインの開発に興味があれば、採用ページを見てみてください。 Software Engineer, Frontend / ソフトウェアエンジニア (Frontend) – Merpay Software Engineer, Frontend / ソフトウェアエンジニア (Frontend) – Mercoin 以上です。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】発行枚数100万枚を支えたメルカードGrowth施策の裏側 – kazuya / ksoichiro / mikael【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 記事は、「 発行枚数100万枚を支えたメルカードGrowth施策の裏側 」の書き起こしです。 @kazuya:「発行枚数100万枚を支えたメルカードGrowth施策の裏側」のセッションを開始します。セッションは3名の異なる職種のメンバーでお送りします。よろしくお願いいたします。 @kazuya:私はKawashimaと言いまして、メルペイでPMをしています。 @ksoichiro:メルペイバックエンドエンジニアのKashimaと申します。2019年にメルペイに入社し、Growth Platformチームでプロダクト開発を担当しています。よろしくお願いします。 @mikael:iOS Tech LeadのMikaelです。2019年に入社しました。今までメルカリアプリの支払いタブなどを開発しました。よろしくお願いします。 @kazuya:私がメルカードプロジェクトのPM、@ksoichiroさんがバックエンド、@mikaelさんがiOSエンジニアです。今回は3名でお送りします。 @kazuya:セッションのタイトルにもあった「メルカード」について、私から説明します。 メルカリアプリに「メルペイ」というスマホ決済サービスが追加され、メルペイの中には、メルペイスマート払いという、あと払いのスマホ決済サービスを展開していました。 2022年11月に、「メルカード」というメルカリが発行するクレジットカードをリリースしました。メルカードはメルペイスマート払いと同じ与信を使っているので、すでにあったメルペイあと払いを拡張したサービスとなります。 メルカードは、2022年発行で、比較的後発であるからこそ、メルカリとしてどういったクレジットカードがいいのかを、いろいろなメンバーと議論してサービスを設計しました。その中での大きな特徴として、「メルカリでのお買い物においてお得」ということは非常に重要です。 メルカリ内でアクションをとると、お買い物がお得になっていき、最大4%還元までレベルが上がっていく設計です。 続いて、メルカードの特徴について説明します。 Point1として、本人確認をすでに終えている方が1000万人以上いらっしゃいます。彼らはとても簡単にアプリ上で申し込みが完了します。 Point2としては、アプリ前提のクレジットカード体験を、ゼロから設計しています。例えば、スマホ決済と同じく、決済後すぐに通知が飛ぶ設計になっています。 クレジットカードの場合、アプリはあるけど、明細に反映されるのが数日後になり、利用状況がタイムリーにわからないこともあると思います。その点、メルカードはクレジットカード・iD決済・コード決済のあらゆる決済ですぐに通知が来て確認できるというシームレスな体験を実現しています。 Point3は、使った金額をいつでも清算できることです。例えば3800円のお買い物をしたときに、翌月末まで待つのではなく、今の時点で支払いたいときは支払いを済ませて管理をしやすくすることが可能です。 Point4は、AI与信です。クレジットカードを日本で作ろうとすると、年齢、職業、会社の勤続年数、年収などの情報が必要だと思うんですけれどもメルカリやメルペイの利用実績に基づいてAI与信をすることで、そういった属性情報の入力が大幅に省略できます。 11月の発表後、約半年で100万発行を達成しました。これは国内のクレジットカードとしても、トップに入る規模発行数になっておりますので、その点に関してはうまくいっているかなと思います。 参考記事: 「メルカード」、提供開始から約半年で発行枚数100万枚突破 ここで、メルカリ/メルペイのカルチャーについて紹介します。メルカリでは、社内外の方に対して多様性を大事にしたいと思っており、メルカードという言葉にもその意味を込めています。 また、リサイクルPVCというエコな素材を用いていたり、色が変化するメルカリのHologram logoを載せたりと、ダイバーシティ&インクルージョンという考え方でデザインされています。 ここで、本題である「グロースをどのようにエンジニア含めて実現したか」という話に入ります。 一番大事なのは、メルカリが発行したクレジットカードなので、メルカリを使う中で自然と「メルカードを作ろう」と思っていただける体験です。 例えばホーム画面やチェックアウトのフロー、商品詳細で訴求をすると言ったように、メルカリの機能に対してもインテグレーションしました。キャンペーンも実施し、マーケティングとプロダクトが連携しながら進めてきました。 参照 メルペイ、「メルカリ」や「メルカード」などの利用でおトクな特典を受けられる「メルカリご利用特典」を提供 メルペイ、「メルカード」の新規入会で「メルカリ」でのお買い物が最大半額になるご利用特典と新TVCMが6月1日より開始 @ksoichiro:私からはグロース施策における体制について説明します。 まず一つ目に、必要に応じてメルカリとメルペイを横断して体制を組んでいます。 続いて、プログラム体制です。メルペイ内部の開発体制は、プログラム体制というバーチャルな組織体制が採用されています。一つ一つの箱がプログラムと呼ばれており、主要なカスタマージャーニーの単位で分けられたJourneyの他に、Foundation、Enablingなどの組織に分けられています。これとは別に通常の組織図に基づいたレポートラインもありますが、そもそもPM組織・エンジニアリング組織とわかれているので、実際の開発はこれらが一緒になって、チームやプロジェクト体制が組まれていきます。 プログラム体制におけるプログラムには複数のチームが含まれ、開発スケジュールが競合するとリソースの調整が発生してしまいますが、プログラム体制においてはまず、プログラムの中で調整するのが基本的な手法です。 メルカードのグロース施策に特に関わりが深いのは、Loyality Program / Payment journeyとGrowth Platform。この場にいる3名においても、2人はLoyality Program / Payment journeyに属していて、私はGrowth Platform所属です。 Loyality Program / Payment journeyには、メルカードそのものや各種決済における体験後は使っており、Growth Platformはグロース施策に必要となるポイント還元やキャンペーン訴求のための仕組み、メルカードにおける還元率の管理などを扱っています。 マーケティングの施策では、OKRをもとにそれぞれ締め切りが設定されてきます。基本的にはそれに基づいて開発スケジュールを計画・進行します。プロダクト開発のメンバーが複数の施策に関わっていくこともありますので、スケジュールが競合し、技術リソースの調整が必要になることもありますね。 これらに関わるメンバーは、特定の職種だけでなく、PMやマーケター、デザイナーなど、総動員で関わってきます。以上が推進体制の基本的な説明です。 @kazuya:メルカリ/メルペイと会社をまたいだり、メルペイの中でもいろいろなプログラム体制があったり、マーケットも協業してしていたりするという説明でした。 @mikael:メルカード関連でよく使ったツールを紹介します。JIRAとBrazeです。 JIRAは、私たちの会社で使用しているプロジェクト管理ツールです。私たちのチームでは、全員が全ての機能を見られるように使用しています。 もし、プロジェクトマネージャーが新しい機能を開始したい場合は、EPICを作成します。さらに、新しい機能における各メンバーごとのタスクを作成します。これにより、バックエンドエンジニア、モバイルクライアントエンジニア、そしてデザイナーも、現在の機能の状態を追跡することが可能になります。 JIRAのようなツールでは、多くの自由があります。私たちがこれらのツールを使用する際のアプローチは、使いやすく読みやすいようにシンプルに保つことです。 例えば、サブタスクの作成は避けます。また、EPICが大き過ぎるか、時間がかかる場合は機能を複数のEPICに分割して、誰にとっても管理しやすくします。 Brazeは、お客さまに表示する内容を変更できるようにするためのツールです。私たちの場合、Brazeはマーケティングをキャンペーンのエディタとして活用しています。マーケティング担当者やプロジェクトマネージャーがWebポータルを通じて、複雑なキャンペーンを簡単に作成・編集できます。 AndroidやiOSでこのようなキャンペーンを実施するためには、バックエンドエンジニア、デザイナー、PMと協力して、私たちのニーズに答えるものを作成する必要があります。最新のキャンペーンでは、商品価格をベースにしてクーポンなどの特別のオファーをお客さまに提案することができます。 SwiftUIで作成されたUIのセットアップ等をカスタムBraze枠によって、マーケティング担当者は情報の提示方法や計算方法を選択できます。例えば500円引きという固定された割引だけでなく、ある限度額までの商品価格に対するパーセンテージを提示することもできます。 @kazuya:マーケターが、キャンペーン中であっても、訴求をA/B Testできたり、様々な運用しやすくするためにもこういったツールを活用しています。 ツールを活用していくわけなんですけれども、Kashimaさんからは、バックエンドチームとして、さまざまなタスクがありながらキャンペーンなど、グロースを支えるための機能を作っていくというところの話をしていただこうかなと思います。 @ksoichiro:ここからは、バックエンド開発について説明します。グロースに関わる開発は、いろいろなものが並行して動いています。私はGrowth Platform チームの一部でTech Leadを務めていますが、それでも全部に関われている訳ではありません。そのため、この場では私が関わったものについて、具体的な事例をいくつかお伝えします。 一つ目はキャンペーンのための開発で、特定のキャンペーンスキームに合わせて対応するときの開発です。二つ目はプラットフォームの開発で、これは私が所属するGrowth Platformのメインの領域です。ポイント還元やキャンペーン訴求などのグロース施策を実行する上で必須になるような仕組みを作るというところです。 一つ目のキャンペーンのための開発も、何度も使うことが想定されているものであれば仕組み化が求められます。 最後はプロダクトのコア体験を作る開発です。例えば還元率がどのように上下するのかを決める仕組みは、細かい仕様が広い範囲の体験に影響しますし、キャンペーンなどの施策がなくても、日々改善して提供していく基本的な部分なので、別の枠として整理しました。 その上で自分が担当してきたことについて、関係するPMの方とどう関わってきたかにも触れつつ振り返ります。 スライドに載せているのは、私が関わった開発の事例の一部です。 一つ目のお得枠は、メルカリアプリの支払いタブの中にあるキャンペーン訴求を表示するエリアのことです。この部分にマーケターや、PMが運用できるような仕組みというのを用意しています。この前身となる類似の仕組みを数年にわたって運用してきてたので、私も担当のPMも知見を持っていて、その上で今後の利用予定をある程度見据えながら設計して準備しました。 二つ目は、入会特典の1000ポイントの付与です。メルカードを作ると1000ポイントもらえるという施策がリリースの当初からあります。 「ポイント付与精度の向上」は当たり前じゃないかと思われるかもしれません。ですが、このタイミングで新しい仕組みを使うという取り組みがあって、そのためにエンジニアリング的な努力が必要になりました。これはその後の大型キャンペーンの運用にも生きる取り組みだったのかなと思っています。 三つ目の特典ページはメルカードのために作られた還元率や特典を確認できるページのことです。私はその開発の初期から関わっていて、ここに関わるPMは1人ではなく、それぞれの施策担当する方と仕様検討しながら進めてきました。初期から数えるとおそらく7、8人は関わっています。 最後の還元率の管理についてですが、メルカードのリリースに向けて開発した新しい取り組みなので、トラブルもありました。メルカードを使い始めたお客さまにおいては、還元率がサクサク上がる体験をおそらくしていただけているんじゃないかなと思います。しかし、逆に意図せず還元率が落ちてしまう悪い体験も起きていて、それを防ぐための対策をとってきました。 こういうときに実際のデータを見ながら、発生しているパターンや件数を細かく分析するのですが、中には判断が難しいものもあり、そのときはPMと相談してステークホルダに説明することが必要になりました。 以上が私が関わった開発の一部です。振り返ってみると、リリース前から仕込んできたものの役割が大きいなと思います。計画的に積み重ねてきた土台があるからこそ、低コストで運用ができて、結果として新しい施策にも手を出せるという状況になっているのかなと思います。これはGrowth Platformチームの成果とも言えるのかなと思っています。 それからPMとの連携というところに関しては、バックエンドエンジニアは基本的には担当するマイクロサービスに対し長く関わっているので、該当の機能についてPMと同じかそれよりも詳しいこともよくあります。 それを踏まえてなるべくPMの目線を理解しつつ、一緒に自分事として関わっていくのか大事だと思います。 それから、体制の説明でも触れましたが、結構な数の施策が並行して進んだり、期間が短くても仕様を変えなければならなかったりします。 その中で変更のサイクルを早く回すには、エンジニアが技術面だけでなく体験面にも関心を持って仕様に口を出したり、インシデントが起きないようにエッジケースも注意しながらコミュニケーションを取ったり、ボールが落ちないようにプロジェクトマネジメントにも積極的に関わったりするのも重要だったんじゃないかなと思っています。 @kazuya:最後に、質問しつつ3人で話していきたいなと思います。 まず、グロース施策を行うときは、数字を達成するために急ぎのタスクが発生することもあります。そのときに、エンジニアとしては他のことをしていることもあると思うんですけれども、どのように受け止めていますか。 @mikael:そうですね。クライアントエンジニアから見ると、バグのfixやリファクタリングをしたいです。一方で、OKRを考えなければならないので、OKR関係のタスクを高いプライオリティにしなければならないと思います。バグのfixやリファクタリングのタスクがあれば、別のOKRを作って対応します。 @kazuya:会社全体の目標(カンパニーOKR)を掲げて皆さんが日々コミュニケーションを取っていることが一つの要因になっているのかなと思いました。 @ksoichiro:エンジニアリングの目標も並列にありますが、ビジネス目標は優先しなければならないので、エンジニアリングの目標は後回しにしなきゃいけないこともありますね。 エンジニアリングのOKRを一緒に立てて並べて、どっちを優先するみたいなのをクォーターごとに決めることで、うまく成り立っています。 @kazuya:続いて、自分たちがやりたいことがある中でもビジネス目標があるという状況で、どのようにモチベーションを維持していますか? @mikael:開発者として開発をする際にテクニカルチャレンジがあるときに、楽しい気持ちになるので、それを大切にしています。 例えばメルカード関係のフィーチャーを作るときに、お客さまを考えながら作りますね。PMが全て決めることでなく、エンジニアも考えないといけないことがたくさんあるので、そこでモチベーションが上がります。 @ksoichiro:一つ目の話にも関係しますが、クォーターの最初で、計画が全部決まっていることはなくて、途中で変わることもあるので、やりたいことができないときもあります。でも、私自身いろいろな施策に関わり、プロダクトの成長に直接的に貢献できているということ自体がモチベーションにはなっています。 @kazuya:以上、こちらのセッションは、3人でお送りいたしました。皆さん、ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルカードの常時ポイント還元開発の裏側 – keitaj【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルカードの常時ポイント還元開発の裏側 」の書き起こしです。 @keiitaj:こんにちは、メルペイバックエンドエンジニアのKeita Suzukiと申します。「メルカードの常時ポイント還元開発の裏側」というタイトルで発表します。 最初に、自己紹介です。2015年からOrigamiPayというサービスを提供していた株式会社Origamiに入社し、スマホのQRコード決済や銀行連携の開発に携わりました。 2020年、Origamiのメルカリグループ参画に伴いメルペイに入社し、現在はメルペイのGrowthに向けたプロダクト開発を行っています。 今回のアジェンダはこちらです。 常時ポイント還元とは、メルカリが提供しているメルカードというクレジットカードでお買い物すると、ご利用金額に応じて最大4%のポイントが還元される施策です。 現状では、メルカリでのお買い物は1〜4%の還元率で、コンビニやスーパーマーケットなど、メルカリ以外の店での還元率は1%で固定となっています。還元率は、お客さまの取引実績に応じて変動します。 この施策の主な機能はポイント還元と付与予定ポイントの表示です。メルカリでお買い物した翌月の請求に対して、清算したタイミングでポイントを即時還元しています。 また、メルカリの商品詳細画面や決済時メールやプッシュ通知、決済履歴に、付与予定ポイントを表示しています。 ポイント還元は、アプリから見えないところで非同期で処理されます。それに対して付与予定ポイントの表示は、アプリから見えるところにリアルタイムで同期的に行われます。 そのため、Pub/SubとAPIの開発が行われました。 同期か非同期かの大きな違いですが、ポイント計算や還元対象判定など共通のロジックは多いです。お客さまの還元率を決定した上で、ご利用金額に応じてポイントを計算します。 還元対象かどうかの判定も行っています。お客さまのカードステータス判定や請求の決済単位で、対象加盟店かどうかの判定を行います。例えば電子マネーのチャージなど、一部対象外となる加盟店もあります。 これらの常時ポイント還元の前提を踏まえ、開発の話に移ります。 まずシステム構成の話をします。関連マイクロサービスはこちらです。 本セッションの主役のサービスはSantaです。キャンペーンの管理ポイント関連がサービスの責務となります。常時ポイント還元の関連サービスは主にこの三つです(他にもありますが、割愛します)。 関連サービスの責務はそれぞれこのような役割を持っています。 loyaltyサービスのステージ管理について、お客さまのメルカリで売る・買う・支払うのアクションによってステージが上がるので、そのステージの管理をここで行っています。 SantaやこれらのサービスはgRPCやPub/Subを通じて情報の受け渡しを行います。各マイクロサービスにはオーナーシップを持つチームが存在しており、私が所属するGrowth PlatformのチームではSantaとloyaltyの開発と運用を担当しています。 ポイント関連のシステム構成とプロセスについて説明します。 メルカードの清算が完了すると、defpayというサービスからPub/Subメッセージが発行されます。このPub/Subメッセージをサブスクライブすることが処理の起点となっています。 Pub/Subメッセージから清算済みの請求情報を取得し、ポイント還元対象かを判定します。対象判定のため、各マイクロサービスからメルカードのステータスや決済加盟店の情報を、gRPC APIを通じて取得しています。 また、お客さまのステージを取得し、変動する還元率を決定し付けた上で、ポイントの計算を行っています。 そして、最後にポイントの付与を実行しています。これがポイント還元の一連の流れです。 次に、付与予定ポイント表示のシステム構成とプロセスについて説明します。付与予定ポイントは、メルカリの商品詳細画面やプッシュ通知、決済履歴で表示されているのですが、今回は時間の都合上、メルカリの商品詳細画面のケースでのみ説明します。 APIによる処理で同期的にアプリに付与予定ポイントを返す必要があるため、gRPCサーバーを立てています。 アプリからgateway-api、item-detailという商品詳細に責任を持つマイクロサービスを通じて、商品金額が渡ってきます。 ポイント還元のプロセスと同様、還元対象と判定するために、メルカードのステータスの情報をgRPCAPIを通じて取得し、またお客さまのステージを取得し、還元率を決定づけた上でポイントの計算を行っています。 最後にレスポンスとしてポイントを返却し、アプリ上で表示できるようにしています。 次に、Santaサービスのバックエンド開発にフォーカスを当てて説明します。 Santaサービスは、Cloud Spannerのスキーマと接続し、キャンペーンやポイント付与のデータを持てるようにしています。メルカードの常時ポイント還元については、Campaignsテーブルの中でデータ定義されています。 キャンペーンによってポイント還元率は変動するので、CampaignStageRatesという親子関係のテーブルを作ることで、一つのキャンペーンに複数の還元率を定義することを可能にしています。 loyaltyサービスから取得したお客さまのステージの値によって還元率を決定しています。 データのイメージはこのような形になっています。メルカリでの購入の場合、還元率が0.1%ごとに変動するようレコード定義しています。 フィルターにはJSON形式の文字列が格納され、セットしたフィルターの内容に応じて対象判定が行われます。 キャンペーンによってフィルターは変わりますが、常時ポイント還元ではメルカードのステータス判定やメルカリ外決済、対象外加盟店を判定しています。 以降は、開発で工夫したところをいくつかピックアップして発表できればと思います。Loyaltyサービスは、この機能で新規ローンチしたマイクロサービスだったのですが、ポイントの還元率をLoyaltyサービスとSantaサービスのどちらで持つべきかという議論がありました。 現状ではLoyaltyをSantaの還元率管理のために使用していますが、今後、Loyaltyを他のマイクロサービスに展開していく将来性を考え、Loyaltyにはあくまでお客さまのステージの管理のみを責務とし、ステージに合わせた還元率など、お客さまへの対応は各マイクロサービスに委ねる方針をとりました。 次に、ポイント還元の付与予定ポイント非表示のユースケースについてです。還元対象判定や還元率に応じたポイント計算など、振る舞いはほぼ共通しています。しかし、非同期処理と同期処理という大きな違いがあり、求められるSLOは異なります。 そのうちの一つの指標がLatencyです。メルカリの商品詳細画面は何千RPSというリクエストが流れており、売り上げに対するインパクトも大きいため、Latencyが高まることはサービスにとってとても致命的です。そのため、ポイント計算のCalculatorは、還元上限を考慮するものとしないものに分けています。 還元上限を考慮するものは過去の付与実績をクエリした上でポイントを計算するため、多少負荷が高く、非同期処理のみで使用するようにしています。 また、決済手段によって加盟店IDが異なる場合があり、単一の加盟店IDで判定不可能なことがあります。Paymentでは、通常よく起こり得る問題かと思います。 今回のケースでは、メルカリ上のApple Payが当てはまります。この決済手段の場合、他社パートナーさまが加盟店管理を行っているため、加盟店IDがメルカリのものとは異なり、対応を見逃すとメルカリ以外で発生した決済とみなされてしまいます。 メルカリとメルカリ以外の買い物での還元率を変えているので、メルカリ上のApple Payは、メルカリで発生した決済であることを特定しなければなりません。加盟店管理を行う他社パートナーさまから決済加盟店の情報を連携いただき、特定することで、この問題を解決しています。 最後に、より開発現場の空気感を知っていただきたいので、現状どのようなことをしているかと、今後の展望について話せればと思います。 最近では、メルカードの普及促進に向けたキャンペーンの開催を行っています。 毎月8日にお買い物をするとお得になるキャンペーンやメルカードの入会特典などです。これらは先ほど発表した内容と同様のスキームで、SpannerのCampaignsテーブルにキャンペーンのレコードを追加することによって実現しています。 還元上限に合わせて対象判定のフィルターを変える、そのフィルターの追加開発が発生することもあります。 日々運用改善も行っています。Loyaltyでは、お客さま体験をより良くするためのステージ遷移ロジックの改善や、Santaではマニュアルオペレーションが多い引当金連携の自動化、加盟店マスターと連携して決済手段ごとに異なる加盟店IDをマスター判定する取り組みを行っています。 今後の展望として、メルペイ単独ではなくメルカリグループ全体のプロダクトと組織を横断して連携を強化する方針があり、グループのGrowth基盤であるエンゲージメントプラットフォーム(EGP)を拡張し、今日発表した内容も含めて、そちらに統合する計画を進めています。 EGPに関しては、@Rupeshのセッション「拡張性を備えたソフトウェア設計」をご覧ください。 【書き起こし】拡張性を備えたソフトウェア設計 – Rupesh Agrawal【Merpay & Mercoin Tech Fest 2023】 発表は以上です。ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルペイ加盟店売上精算の仕組み – Takumi Shibazaki【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルペイ加盟店売上精算の仕組み 」の書き起こしです。 @shiv3:本セッションでは、「メルペイ加盟店売上精算の仕組み」についてお話しします。 最初に自己紹介です。Shibazakiと申します。社内ではSlackネームである@shiv3と呼ばれています。現在、メルペイでソフトウェアエンジニアをしており、2021年9月に入社し、加盟店精算領域の開発を担当しています。現在はそこのチームでテックリードをしています。 アジェンダは、この通りです。主に加盟店精算についての概要と、加盟店精算の仕組みについてお話しします。 加盟店精算は、コード決済・ネット決済のメルペイ加盟店さまが、お客さまから決済を受けたときに、それを月1回および月2回の頻度で入金するために金額を集計して、入金日に合わせて事前に入金指示を行います。 加盟店精算における精算は、クリアリングとセトルメントの二つのステップで行われます。クリアリングは、加盟店さまの未精算の売上や手数料など、過不足なく正確に計算し、最終売上を確定させる処理になります。 セトルメントは、確定した売り上げを加盟店さまに実際に振り込み、もし返金などで、当月中の売上金の赤残が発生する場合、その金額を確定させて、加盟店さまへ請求するというフローです。 メルペイではお客さまには個人と加盟店さまの2種類があり、それぞれのお財布・決済アカウントを管理しています。ここでは加盟店精算で用いる加盟店さまのお財布・決済アカウントのみを紹介します。 まず内部のアカウントとしては、決済をするたびに売上がたまる未精算売上口座および、精算のプロセスが完了した後で確定された売上が入る精算済み売上口座があります。また、売り上げが債権として精算される場合は、精算済み債権口座に入ります。 マイクロサービス全体での精算処理がこのようなフローで行われます。加盟店精算のリクエストが決済サービスに来ると、決済処理を担当するサービスが決済処理を行い、精算サービスは決済サービスからそのイベントを受け取り、イベントをもとにリアルタイムで手数料を発生させ、その後月1回・2回で最終的な売上を確定する精算サイクルです。 次に各ステップを詳しく見ていきます。 精算サービスは、決済イベントを受け取るとリアルタイムで決済サービスにメルペイの決済手数料をリクエストします。 その後、精算サービスは、手数料の決済時イベントも決済サービスから受け取り、清算対象にします。ここで、手数料自体の決済に対しては、再度手数料をかけることしないようにしています。加えて精算サービスは、どの決済に対して手数料を発行を行うか、もしくは各加盟店のためにどういう加盟店やどういう決済に手数料をどうかけるかという設定も管理しています。 次に、決済イベントのデータをもとに、精算用のデータを作成・保存するステップに移ります。 加盟店精算用のデータは、加盟店さまから、および加盟店さまへを対象に、お金の動きをToとFromで管理しています。お客さまから加盟店さまに決済として売上があった場合は、Toの方に加盟店さまのIDを設定し、決済手数料では、Toの方にメルペイ、Fromの方に加盟店さまのIDを設定してします。返金および手数料の返金に関しては、その逆のフローです。 次に、保存した精算用のデータが正しく保存されているかを、他のマイクロサービスと突合を行うリコンサイルという処理を行います。先ほどのステップで保存した取引データを1件ずつ会計帳簿サービスのデータと突合し、突合済みのデータとして更新します。 その後にリコンサイルの取引データを対象に、日時の集計を行います。ここでは、リコンサイルの結果を基に、Xという加盟店が10月3日の売り上げとして300円になったという日次精算のデータを保存しています。 また、集計時に入金集約というパターンが存在します。複数の加盟店の売り上げを一つの振り込み先に集約させるフローで、集計元の加盟店さまの売り上げは、入金先の加盟店さまに対しての一時精算データとして集計します。ここでは子パートナーa・b・cの100円ずつの精算を、親パートナーAの精算金額として保存しています。 その後、月1回・2回の精算サイクルで入金額の集計を行います。ここでは、月1回の精算サイクルで集計する場合を紹介します。 10月1日から10月31日までの日次精算の1ヶ月分のデータを合計し、10月分の売上データとして保存します。ここではSalesSummariesという名前のデータとして保存しています。その後、データを用いて入金額の集計を行います。ここではPayoutsというテーブルに集金額を入れています。 ここで前回の入金が失敗した場合や、繰越設定があった場合は、入金額に前回の分を合算します。 精算サイクルごとに精算データを作成した後は、売上金のクリアリングを行います。未精算売上口座から精算済み売上口座にお金を動かす際、加盟店売上金クリアリングリクエストを決済サービスにリクエストし、精算済みの口座にお金の移動を行います。 ここでは、未精算売上口座にあった5000円を、精算済み売上口座に加算しました。 返金などで当月中の精算サイクル締め期間の売り上げがマイナスになった場合は、赤残と呼んでいます。 精算済み売上金口座にクリアリングを行いましたが、赤残が発生した場合は清算済み債権口座にお金を動かすためのリクエストを発行します。例えば売上金がマイナス2000円になってしまった場合、その2000円は精算済み債権口座に移動させます。 クリアリングのステップの最後に、債権口座と売上口座の相殺処理を行います。ここでは債権口座に2000円、売上金口座に5000円ある場合、それを相殺して精算済み口座に3000円が入る状態にします。 最後に、加盟店さまの入金日に合わせて、売上金のセトルメントと振り込みを行います。クリアリング時に作成した入金金額のデータをもとに、入金日に合わせて決済サービスを通じて、銀行接続サービスから振込リクエストを行います。 入金結果を銀行接続サービスが入金日の後に入金結果を取得し、精算サービスはデータを決済サービス経由で受け取り、入金状態を更新します。ここでは12000円振り込んだので、その金額の結果をPayoutsに保存しています。 最後に、課題についてです。 課題は二つあり、一つ目は加盟店の手数料発行と精算処理が密結合していることです。精算データの作成処理の手数料の発行処理とほぼ同じタイミングで行っている都合上、精算処理のドメインとしては、手数料発行は異なりますが、それぞれの処理が密結合しています。これは、データの作成部分や処理のフローを分離することで対応しようと思っています。 二つ目はリコンサイル時に会計帳簿に依存しており、会計帳簿サービスと決済処理サービス間のリコンサイルに不整合や遅れが発生した場合に、精算に影響が出る可能性があることです。 こちらについてはリコンサイルのためにProcessing Tracingというサービスの導入を進めており、それによって会計帳簿サービスへの依存を減らす方針で進めています。 以上で、今回のセッションを終わりにしたいと思います。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】gRPC Federation を利用した巨大なBFFに対するリアーキテクチャの試み – goccy【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるEngineeringを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 gRPC Federation を利用した巨大なBFFに対するリアーキテクチャの試み 」の書き起こしです。 @goccy:それでは「gRPC Federation を利用した巨大なBFFに対するリアーキテクチャの試み」というタイトルでメルペイ Engineer ProductivityチームのGoshimaが発表します。よろしくお願いします。 初めに自己紹介です。@goccyというアカウントで活動しています。2012年に新卒で株式会社MIXIに入り、ウェブやアプリのフロントエンドからバックエンドまで技術領域を問わずいろいろなものを作ってきました。 2012年や2013年にYAPC::Asiaで自作のPerl処理系に関して登壇したり、5年くらい勤めた後に転職し、ゲーム系のベンチャー企業でテックリードを務め、3年くらい働いた後、2020年にメルペイに入社しました。OSS開発が好きで、最近はGoのOSSをよく書いています。夢は1万スターを達成することで現在5000スターを超えたくらいです。写真は我が家の愛犬です。 今日のアジェンダです。最初にメルペイでのBFFの変遷です。メルペイが今までBFFをどのように扱い、これからどう扱っていきたいかを話します。 また、その中で課題が出てきたので、それを解決するために、弊社で使っているgRPC Federationについても解説します。 最初に、メルペイでのBFFの変遷についてです。 はじめに、BFFの役割とメリット・デメリットについて話します。BFFは「Backend for Frontend」の略です。文字通り、フロントエンド、つまりクライアントに特化したレスポンスを返す専用のサービスです。 BFFのメリットは、クライアントがBFFとのやり取りだけを考えて通信すればいいので、他のバックエンドサービスを意識せずBFFに集中できることです。一方、バックエンドからもクライアントを意識せずにレスポンスを好きに返すことができ、BFF側でレスポンスをいい感じにクライアントに合う形に集約して返すので、バックエンドを楽に実装できるという特徴があります。 一方、多数のチームが一つのBFFを開発する体制になりがちです。そのため、保守しにくい巨大なモノリスになりやすいというデメリットがあります。多数の人が関わることで、責任の所在が曖昧になりやすいことも課題です。 参考記事: Pattern: Backends For Frontends 続いて、メルペイでBFFをどのように扱ってきたかを解説します。 メルペイではAPI Gatewayの直下にBFFとしてMerpay APIというサービスが存在します。Merpay APIは、多数のマイクロサービスの結果を集約して、クライアントに最適化された結果を返します。 GatewayとMerpay APIのようなBFFを一つにして管理している会社はたくさんありますが、Merpay APIが巨大なため、弊社では責務をそれぞれGatewayとMerpay APIで明確に分けるためにサービスとして独立させ、別のチームが責任を持ってメンテナンスしています。 メルペイのリリースから4年以上が経ち、Merpay APIに多数のチームが機能を追加していくうちに、徐々にオーナーシップが不明確になっていくという課題が出てきました。 現在では応急処置として特定のチームがMerpay API全体の責任を持つ状態になっていますが、Merpay APIが巨大すぎて、保守するコストが無視できないレベルになってきました。 この図のように、Merpay APIに対して多くのチームが機能開発をしていますが、メンテナンス・運用するチームが少数のため、負担が大きくなっています。 これを解決するために、今年「Merpay APIリアーキテクチャプロジェクト」がスタートしました。 Merpay APIが持つ全てのAPIに対して、ひとつずつAPIに責任を持つチームを明確にし、Merpay APIを複数のBFFに分割することで管理するプロジェクトです。 Before(図の左側)のように、Merpay APIに対していろいろなチームが開発している体制から、Merpay APIのAPI一つ一つに、どのチームの持ち物なのかを明確にし、チームの持ち物に対して新しくBFFを切り、チームとBFFを一対一で対応させ、責任を明確化する構成を作ります。 このプロジェクトによって、複数のBFFを作ることになりました。これによってチームとBFFの対応関係が明確になるので、対応チームの「BFFの開発・保守に割くコストを低くしたい」という要求がどんどん高まることが考えられます。 一方で、BFFは責務がシンプルなため、多くが定型作業になると予想されます。そのため、自動化などの恩恵を受けやすいことを踏まえ、BFFを低コストで開発運用する何らかの仕組みが求められていると考えています。例えば、GraphQL FederationのようなFederated Architectureを使う、定型作業の自動化を進める、などの方法が考えられます。 そこで、GraphQL Federation(Apollo Federation)を検討しました。これはGraphQLを用いたFederated Architectureを構築する仕組みで、近年いろいろな会社で採用されています。 導入を検討したものの、今までgRPCだけで巨大なサービスを運用しており、新しくGraphQLを導入するコストが高すぎるという課題がありました。 各マイクロサービスに対応する形でGraphQLサーバーを導入する際のコストが高い、バックエンド開発者全員にGraphQLの知識を新しくインストールする必要がある、GraphQLに対する運用監視の知識が新しく必要になるなどの課題があり、結果的に採用を見送ることにしました。 では、どうするのか。Federated Architectureを構築するためにgRPCを使う方法がないなら、作ればいいんです。そこでgRPCを用いたFederated Architectureを構築する仕組みを開発しています。それをgRPC Federationと呼んでいます。 その仕組みを使って、gRPCサーバーであるBFFを自動生成します。BFFは今まで通りgRPCロトコルを用いて、配下のサービスと通信します。 それでは、gRPC Federationについて説明します。 gRPC Federationは、gRPCを用いたFederated Architectureを構築する仕組みです。Protocol Buffersのオプションで振る舞いを記述します。結果として、自動生成によってgRPCサーバーを作ることができます。 ものによってはProtocol Buffers上だけでは表現できない複雑なロジックを持つ場合もありますが、その部分についてはGoで書くことが可能です。Protocol BuffersとGoのハイブリッドで記述するイメージです。 BFFのように自身でデータを持たず、マイクロサービスの呼び出し結果を集約して返すサービスで有効ではないかと考えています。 最初にgRPC Federationを作るにあたっての設計思想について簡単に触れます。 Protocol Buffers上のレスポンスに注目して開発しました。レスポンスに相当するmessageを取得するために、gRPCメソッドを呼び出すと考えます。普通はgRPCメソッドを呼んだ結果がレスポンスになるので逆になるのですが、考え方としてmessageに注目したかったので、レスポンスに着目しています。 もう一つは、全てのmessageにはそれを取得するためのgRPCメソッドが必ず存在すると考えることです。message と gRPCメソッドは、必ず1対1に紐づけ可能であるという前提を置いて作っています。 gRPC Federationで「どんな体験を提供したいか」も最初に考えています。 一つは「BFFを構築する上で必要な、典型作業を自動化したい」ということ。具体的にはBFFと依存先のサービス間の大量の型変換を自動化したり、サービスの依存関係をProtocol Buffersの解析だけで把握できるようにしたいと考えています。gRPC Federationが想定している使い方をしてもらえれば、メソッド単位の依存関係もわかるようになると考えています。 「BFFと依存先サービス間の型変換を自動化したい」というモチベーションについて説明します。まず、BFFを構築する上で、依存先のサービスにあるmessageを返したいときに同じmessageをBFF側にも作る必要があります。 これをしないと、BFFの呼び出し元が依存先のサービスを常に意識する必要があるため、設計としてBFFを置いている意味がなくなってしまいます。 ただ、このような設計にすることで、BFF側の立場としてはパッケージを跨いだ同じ型の変換作業が大量に発生してしまいます。gRPC Federationでは、これらの対応関係を記述することで、変換処理を自動生成したいと考えています。 もう一つ、サービスの依存関係をProtocol Buffersの解析だけで把握できるようにするモチベーションについて説明します。 マイクロサービスアーキテクチャにおいて、サービス間の依存関係を把握できるといろいろなメリットがあります。メソッド単位での依存関係がわかることで、パフォーマンスの理論値を算出したり、リファクタリングの影響範囲を把握したりと、いろいろなことができるようになります。 gRPC Federationが提供する専用のGoのライブラリや、Protocol Buffersのリフレクション機能などを利用することで、依存関係を機械的に取得できるようになり、いろいろな用途に使えると考えています。 簡単にgRPC Federationに付属しているツールの一部を紹介します。 Protocol Buffersのプラグインとして動作させるように、protoc-gen-grpc-federationというツールがあり、protoc-gen-goやprotoc-gen-go-grpcといったプラグインと組み合わせて使うことで、gRPCのBFFサーバーを自動生成します。 linterはスタンドアローンのツールで、Protocol Buffersのコンパイルをした上で、gRPC Federationの記述ミスを指摘してくれるものです。静的解析ではなくコンパイルするので正確に解析できます。 他にもlanguage-serverを最初から用意しており、gRPC Federationのオプション記述を支援してくれるので、linterによるエラーや補完がエディタ上ですぐに利用できます。 続いてgRPC Federationの具体的な使い方を説明します。 Post ServiceとUser Service、それからBFFとして作るFederation Serviceという三つのサービスを使って説明します。 図のように、Federation Serviceという今回作るサービスにpost idが送られたら、それをPost Serviceに渡すことによってPost messageを取得し、Post messageに存在しているuser_idというフィールドの値をもとに、それを使ってUser Serviceに問い合わせし、User messageを取得します。postとuserという二つのmessageを合成して、postの中にuserが含まれるmessageにした上で返すサービスを考えていきます。 続いて、各サービスのProtocol Buffersの定義についてです。 一番左側がFederation Serviceに相当するProtocol Buffers内容です。GetPostというメソッドがあり、中身には Post messageが入ります。Post messageには User messageが直接入る構成です。 右側二つはPost ServiceとUser Serviceの内容です。それぞれGetPost / GetUser と自身が管理する message を返すメソッドを一つずつ持ちます。Post message にはuser_idというフィールドがあります。これらを使って説明していきます。 gRPC FederationのProtocol Buffersのオプションについて簡単に説明します。Protocol Buffersのsyntaxのservice、message、fieldそれぞれに合わせてオプションを用意しています。 serviceに対してはgrpc.federation.serviceが、messageに対してはgrpc.federation.messageが存在します。それぞれについて説明します。 まず、grpc.federation.serviceというオプションです。これはgRPC Federationの自動生成対象となるサービスを指定するために利用します。機能として、dependenciesというセクションがあり、どのサービスに依存しているかを定義できます。 この例であれば、Federation Serviceにgrpc.federation.serviceというオプションをつけると、dependencieを用いてPost ServiceとUser Serviceに対して依存関係があることを定義できます。 grpc.federation.messageオプションは、一番重要なオプションです。大きくresolverとmessagesにわかれています。message自身の各フィールドに割り当てる値自体を取得するための定義を書くオプションです。 resolverはgRPCメソッドを呼び出すための定義です。この定義によってmessageとメソッドが一対一で紐づきます。resolverだけでは自身のmessageに割り当てる値を取得しきれないことがあります。そのときにmessagesを用いて他の message への依存関係を定義できます。 messages は複数指定することが可能です。 この二つを組み合わせることで、必要な値を手に入れます。 最初に、resolverから見ていきます。左側がFederation Serviceの定義で、右側がPost ServiceのProtocol Buffersの定義です。赤枠で囲われたresolverというセクションについて話します。 最初に、resolverはgRPCメソッドを定義します。methodというフィールドに対して呼び出すメソッドの名前をFQDNで指定します。今回であればPost messageを作るためにGetPostというPost Serviceのメソッドを呼び出したいので、この形で指定します。右側のPostServiceの赤くハイライトした部分が対応している部分です。 続いて、メソッドを呼び出すためには、リクエスト時の値を指定する必要があります。赤枠のrequestという箇所でそれを指定しています。右側のPost ServiceのGetPostRequestというmessageに対応しており、GetPostRequestの中身を埋めていく作業になります。fieldにフィールド名を書いて、byでpost_idフィールドに対する値を指定します。 最後に、呼び出した結果のうち、どの値をどのような名前でgRPC Federation中で参照していくかを定義するために、response を定義します。これはPostService側のGetPostReplyというmessageの内容と対応しています。 次にそれぞれのフィールドについて説明します。nameで、取得したレスポンスをどういう名前で参照するかを定義します。ここでresという名前をつけているので、この名前でGetPostReplyのpostフィールドの値を参照するという意味になります。 次にfieldです。そのレスポンスのうちにどのフィールドを採用するかを指定します。ここではpostというフィールドを指定しているので、GetPostReplyの中のpostフィールドの値だけを使うという意味です。 最後に、「autobind: true」について説明します。 レスポンスの各フィールドと同じ名前・同じ型のフィールドがBFF側にも存在するならば、フィールドのバインディングをできるだけ省略した方がいいという考え方のもと、右側のPostService側のPost messageにあるid・title・contentというフィールドと同じ名前・同じ型のフィールドが左側のFederationService側にも存在するので、それらの値を自動的にバインドするという機能です。これによって option の記述を大幅に省略することができます。 次にmessagesのセクションについて説明します。Post messageを作る上でresolverだけでは足りません。肝心のuserの値はまだ取得できていない状況です。 最初にmessagesの中で、nameに着目します。これは依存するmessage、今回であればFederation Service側のUser messageに依存したいので、User messageに対して、取得したときにどういった名前で扱うかを指定します。 ここではuという名前を付けているので、この名前でUser messageを参照していきます。 次に、参照するmessage自体を書かないといけないので、messageにUserと書くと、右側の赤枠で囲われた User messageを指すという意味になります。 次に、一番重要なargsについてです。右側のUser messageを見てください。こちらにもgRPC Federationのオプションが書かれていて、中ではGetUserメソッドを呼び出し、userを取得して自身のフィールドにバインドするということが書かれています。 GetUserメソッドを呼び出すためにuser_idが必要です。この値を User message に渡すことを考えなければなりません。これを実現するためにargsを利用し、依存messageを取得する際に必要になるパラメータを指定します。このパラメータを、gRPC Federationでは「メッセージ引数」と呼んでいます。 argsの中にはnameがあります。ここでは、messageに対する名前を指定することができ、依存先のmessage、この場合User message側でこの名前に「$.」というプレフィックスをつけることで参照できます。 では、引数の値はどうやって指定するのでしょうか。これは、byで指定できます。byで指定する値自体はどうやって受け取るのかというと、resolverでレスポンスに対してつけたresという名前を参照し、レスポンスのuser_idフィールドを参照することを示すためにres.user_idと書くと指定できます。これにより、User message側にGetPostメソッドのレスポンスにあるuser_idの値が渡ります。 最後に、grpc.federation.fieldというオプションについて説明します。messageオプションによってフィールドのバインディングに必要な情報が集まりました。 最後にfiledオプションで定義した名前や、自身のmessageに対するmessage引数などを参照しながら値をフィールドに紐付けます。Protocol Buffersの定義にあるように、messagesで書かれているUser messageに対して「u」という名前をつけていますが、この名前を使ってgrpc.federation.field のbyという機能を使って4番目のuserフィールドにUser messageの値を紐付けています。 最後にレスポンスにオプションを追加して完成です。最初に設計思想でレスポンスのmessageに着目したいという話をしました。 今まで作ってきたPost messageを作っただけだと、まだgRPCメソッドであるGetPostの全実装を完成できていません。 レスポンスのmessageであるGetPostReplyに対してオプションを追加し、レスポンスの実装が完成していることを示すことが必要です。 特殊な仕様として、レスポンスのメッセージ引数に相当するものは、gRPCメソッドのリクエスト側のmessageの各フィールドになるというものがあります。GetPostReplyというmessageを作るためにオプションを書いていきますが、grpc.federation.messageというオプションの中で、リクエストに対応するGetPostRequest messageの各フィールドを参照できるので、$.id でリクエストの内容を参照できます。 その結果取得した Post messageに対してpという名前をつけているので、pをgrpc.federation.fieldというオプションで参照して、自身の1番目のpostフィールドに紐付けて完成になります。 他にもいろいろな機能が実装されています。他のパッケージに定義されている messageを参照することでgRPC Federationの資産を再利用したり、複雑なロジックを定義したい場合は、messageやfieldオプションの中で「custom_resolver = true」と記述すると、その部分だけGoで実装することができます。 他にもgrpc.federation.methodというオプションでメソッドレベルの制御ができるようになり、例えばタイムアウトを設定できます。また、oneofに対しては専用のgrpc.federation.oneofというオプションを用意し、oneof内で条件分岐を定義できるようにすることも考えています。 実はgRPC FederationはOSSとして公開していまして、grpc-federationというリポジトリで、誰でも利用することができるようになっています。 現在アルファバージョンですが、今年中に社内の本番環境で活用できるように改善を続けている状態で、随時更新しています。 Federated Architectureを構築する上で、GraphQLに代わる一つの解として gRPC Federation を選択できるように頑張っていこうと考えています。 現時点ではプルリクエストは受け付けておりませんが、機能要望や、改善案、使用感などのフィードバックはウェルカムですので、issueやTwitterのコメントで反応してくれると嬉しいです。 grpc-federation: https://github.com/mercari/grpc-federation 最後に、発表のまとめです。マイクロサービスアーキテクチャにおけるBFFの重要性とメリットデメリットについて触れました。 メルペイでは、巨大なBFFのオーナーシップ問題を解決するために、いくつかのBFFに分割することを考えています。各BFFの開発を効率的に行うためにgRPC Federationという仕組みを作っています。gRPC Federationを使ったシンプルなBFFの構築例を示しました。こちらはOSSになっており、誰でも使えるようになっているため、ぜひ使っていただいてフィードバックをお待ちしています。 それでは本発表を終わります。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルコイン決済マイクロサービスのトランザクション管理を支える技術 – Shota Suzuki【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルコイン決済マイクロサービスのトランザクション管理を支える技術 」の書き起こしです。 @susho:それでは「メルコイン決済マイクロサービスのトランザクション管理を支える技術」というタイトルで、Merpay Payment Platform Teamの@sushoが発表します。よろしくお願いします。 僕の名前は、Shota Suzukiです。社内では、@sushoというアカウントで活動しています。所属は、株式会社メルペイのバックエンドエンジニアです。2018年にメルペイに入社し、その後iDやコード決済のマイクロサービスを開発し、現在はメルコインの決済や会計のマイクロサービスを開発しています。 本日のアジェンダです。最初にメルコイン決済マイクロサービスについて説明し、次にトランザクション管理、リコンサイル、最後にまとめです。 最初に、メルコイン決済マイクロサービスについてです。 これは、お客さまの決済処理を担うマイクロサービスで、主にスライドのようなユースケースが存在しています。 次は、マイクロサービスのトランザクション管理の話です。 一般的に、マイクロサービスを跨いだトランザクションでは、マイクロサービスはデータベースをそれぞれ持っているため、依存先マイクロサービスのデータベースのロールバックを実行できないと思います。 また、2フェーズコミットなどに代表される分散トランザクションでは、リソースの状態をロックする必要があるため、サービスの可用性が下がる可能性があります。 そのため、実行した操作を取り消すビジネスロジックを 補償トランザクション として実装し、それらを最後まで順次実行する結果整合性というアプローチを取っています。 次に、Sagaについてです。これは、結果整合性を使ったアーキテクチャの一つと言われています。弊社でもこれを採用していて、トランザクションを複数のトランザクションに分割し、それらを順次実行します。 途中でリトライ不可能なエラーが発生したら、逆処理となる補償トランザクションを順次移行していくことを指します。自分たちで開発しているマイクロサービスでもこのアプローチを採用してトランザクションの設計をしています。 トランザクション管理がどのようなものかを、メルコイン決済マイクロサービスの「暗号資産購入」というユースケースに絞って説明します。 左上から見ていくと、決済マイクロサービス自身で状態を管理したいので、自分たちのDBにリソースを書き込みます。その後、購入に利用するメルカリポイントの減算処理を実行するのが次のトランザクションです。 それが成功したら、メルコイン残高のJPYを減算します。続いて、加算した分のBTCの残高を加算処理し、自身のリソースを更新します。最後にEventとして、リソースの状態をPublishします。この計六つのトランザクションとなっています。 補償トランザクションの定義は、スライドの通りです。例えばBTCの加算処理を失敗した場合、JPYの減算処理の逆処理となるJPYの加算処理を補償トランザクションとして提起し、メルカリポイントの減算処理の逆処理となる加算処理を次の補償トランザクションとして定義し、その後リソースの更新、EventのPublish処理を定義しています。 続いて、各処理で失敗したときの実行順序を見ていきます。例えば、BTCの加算処理が失敗した場合、JPYの加算処理、メルカリポイントの加算処理リソースの更新、PublishEventの順に実行していきます。 もしJPYの減算処理で失敗した場合には、一つ前の逆処理となるメルカリポイントの加算処理から逆順に補償トランザクションを実行します。 次に、メルカリポイントの加算処理に失敗した場合には、リソースを更新してEventをPublishするという補償トランザクションの実行順になります。 このようにトランザクションの設計をすることで、途中でリトライ不可能なエラーになったとしても、安全にロールバックできます。 これらをどのように実装するかを検討したところ、弊社ではクラウドサービスとしてGCPを利用しているため、オープンソースのプロダクトかGCPの製品が候補として挙がり、スライドにある2つを検討しました。 一つ目は、 GCP Workflows です。これは、各トランザクション処理をHTTPのAPIのエンドポイントとして実装する必要があるので、開発時にユニットテストがしづらいという懸念があります。 またオープンソースの製品である Cadence や Temporal は、弊社が利用しているCloud Spannerに対応していないため、自社で開発するのが良いという結論に至りました。 続いて、自社で開発したWorkflow Engineのアーキテクチャの概要を説明します。基本的にWorkflow Engineは、アプリケーションサーバーと同じポットやサーバーでデプロイされることを想定しています。 Goランタイムで動くようになっていて、SDK・Libraryのような使い方で利用していくことを想定しています。 アプリケーションはWorkerと呼ばれるものを、ライブラリのインターフェース経由でアクセスします。主に二つのインターフェースを使ってコミュニケーションをします。 一つ目は、Register Workflow Functionです。トランザクションは、Goのコードなので、エンジン側にどのようなWorkflowを使うかを登録します。そのためのインターフェースがこれです。Workerは登録の要求が来たら、自分たちのインメモリのRegistryに格納し、実行するときは、リフレクションを使って実行します。 もう一つが、Workflowを実行するインターフェースです。これが呼び出されると、Workerは、まず最初にEngine Serverと呼ばれる、Spannerで、WorkflowやActivityの実行状態を管理する単純なプラットのgRPCのサーバーなのですが、どのようなインプット・functionネームで実行するかをWorker側がEngine Serverに書き込みます。その後、WorkerはChannelにWorkflowが開始したというEventをPublishします。 するとWorker側はそのEventをSubscribeして、Goのreflect.ValueOf.Call()関数を使って実行します。それが完了したら、WorkerはEngine Serverに実行結果を保存するためにWorkflowのコンプリートのリクエストを投げ、ChannelにcompletedEventを投げます。 その後、Workflowの実行結果を、アプリケーションで確認したい。アウトプットを受け取って、クライアントなどにレスポンスを返したいという要件もあると思うので、Workerは非同期に、アプリケーションが待ち受けている処理にレスポンスを返します。 途中で失敗してコンプリートを呼べない場合も想定されます。その場合はリカバリーWorkerというものが動作し、Engine Serverに対してコンプリートになっていないWorkflowやActivityをリストし、リトライします。このようにして、アプリケーションのWorkflow Engineを実行管理しています。 続いて、それぞれの用語についてまとめました。 Workflowは、複数のActivityを使ったビジネスロジックと定義しています。先ほど説明した、「全体のトランザクション」をイメージしていただければ良いかなと思います。Activityがビジネスロジックの最小単位です。「それぞれのトランザクション」をイメージしてください。 次に、Workerです。Workerはアプリケーションサーバーから要求に従ってEngine Serverへコミュニケーションします。また、ChannelからEventをSubscribeして、Eventの種別に沿った処理を実行します。 リカバリーWorkerは、Workerとほとんど役割が同じですが、完了していないワークの一覧を取得し、トライするものです。 アプリケーションから渡されたGoのコードをインメモリの構造で管理しているのが、Workflow Function Registryです。 続いて、Channelです。これは、WorkflowやActivityの状態遷移Eventハブとなります。 現状では4種類のEventが存在していて、WorkflowStarted、WorkflowCompleted、ActivityStarted、ActivityCompletedの4種類です。StartedはWorkflowを実行するためのEventでこれを受け取ったら、Workerはリフレクトを使って関数を呼び出します。その後Completedが、このEventハブに届くので、完了した後に、アプリケーションレスポンスを返すためのEventです。 ActivityStarted・ActivityCompletedは、Workflowとほとんど同じ利用用途です。 Engine Serverは、Workflowの状態を管理するシンプルなCRUDのgRPCサーバーです。WorkflowやActivityの渡されたインプットやアウトプットも保存しています。 これにより、途中で失敗してリトライするときに、以前まで実行していたActivityのアウトプットが保存されているので、再度実行せずにアウトプットをただ返して冪等に処理することが可能です。 続いて、先ほどの暗号資産購入のトランザクションを、Workflow Engineを使うとした場合の構成を見ていきます。 全体として、「暗号資産購入」というWorkflowを定義し、それぞれのトランザクションをActivityとして定義します。同様に補償トランザクションもActivityとして定義し、これらをどの順序で実行するかをGoのコードで書きます。 コードサンプルを見ていきます。appという構造体を用意し、初期化処理の中で、実行に使うWorkflow、Activityを事前に登録しておきます。 RunSayHelloというメソッドが呼び出された場合を見てみると、これはWorkflowとしてSayHelloを実行して、レスポンスを受け取るシンプルなコードです。 これによってWorkerでSayHelloの関数が実行され、レスポンスを受け取れます。SayHelloの中身を見ると、このSayHelloはHelloというActivityを実行して、そのレスポンスを待ち受けています。 これによってWorkflow SayHelloが実行されて、そのSayHelloは、ActivityHello を実行するようにアプリケーション側で定義されているので、その順番で成功するまでリトライし続けられ、完了します。 このようにして、先ほどメルコインのユースケースで紹介したWorkflowをGoのコードに落とし込んで実行することで、トランザクション管理をしています。 次はリコンサイルを説明します。 リコンサイルとは、依存先マイクロサービスと整合性が取れているかを突合して検証するプロセスです。 サービスの特性上、お客さまの資産を預かるため、マイクロサービス間で不整合が起きていないことを、トランザクション管理とは別プロセスで検証したいという目的があります。 また、自分たちのマイクロサービスだけではなくて、依存している全てのマイクロサービスで検証しその結果整合性が取れていることを確認した上で、会計処理を実施したいという目的のもと、実行していきます。 そこで開発したのが、Processing Tracerというマイクロサービスです。これはマイクロサービスのリコンサイル処理をフックし、リコンサイル状況の監視・アラートするためのマイクロサービスです。 概要を見ていきます。こちらも、暗号資産購入の場合を想定しています。このときにOrder、Payment、Balanceが、マイクロサービスがこの暗号資産購入の取引に依存しているとします。 Orderがこのトランザクションのエントリーポイントとなるので、まず最初にOrderがProcessingIDというものを生成し、その後Paymentにリクエストを投げるときに、そのProcessingIDをつけます。 その後、PaymentはBalanceにリクエストを投げるときにのProcessingIDをつけます。そうすることで、この三つのマイクロサービスでProcessingIDが伝播されます。 OrderはProcessing TracerにRegister ProcessingIDというAPIを呼び出して、生成したProcessingIDを登録します。 Processing Tracerは、CronJobによって、このProcessingIDがOrderから登録されていることがわかるので、Orderサービス専用のPub/Subトピックに対して、リコンサイルのEventをPublishします。 するとOrderサービスは、トピックに紐づいたサブスクリプションを作成し、リコンサイル処理を実装します。Eventが呼び出されたら、リコンサイル処理が実行されることになります。 中身としては、Paymentに問い合わせてリソースの状態を突合し、OKだった場合は、Processing Tracerにリコンサイルレポートという形で、gRPCのリクエストを投げます。 このとき、OrderはPaymentに依存しているので、レポートの中にPaymentという識別子を付加してレポートを投げます。 そうすることで、Processing Tracerは新しくこのProcessingIDはPaymentに依存しているとわかるので、CronJobによってPaymentのPub/Subトピックに、Eventを投げてPaymentはBalanceと突合します。 その後レポートにBalanceという識別子を含めて投げることで、Processing Tracerは、後でBalanceにPub/SubのEventをPublishして、全体としてリコンサイル処理が伝播されます。 もしBalanceなどがリコンサイルできていなかった場合は、それを補足してSlackにアラートを飛ばす仕組みがあります。 それぞれの用語について説明します。 まず、ProcessingID。これは、リコンサイル処理を一意に識別するためのIDです。基本的に処理のエントリーポイントとなるマイクロサービスが生成し、ユニーク性担保のために生成には専用のSDKを利用します。 Register ProcessingIDは、ProcessingIDを登録するもの。Reconcile Eventは、ProcessingIDが登録され、一定期間後に、マイクロサービスそれぞれのPub/Subトピックに向けてEventを発行するものです。 Report Reconcileは、各マイクロサービスがリコンサイル処理を実施して成功したレポートを送信するものです。アラートは、リコンサイルされていないProcessingIDについて、そのマイクロサービスのオンコールChannelにメッセージを投稿するものです。 最後に、メルコインマイクロサービスのリコンサイル処理について、軽く説明します。 Processing TracerからReconcile Eventを受け取ったら、Paymentは、ProcessingIDから自身のリソースを見つけて、PaymentやBalanceにリクエストを投げます。 このときに自分の状態と依存しているマイクロサービスの状態を突合し、OKだったらレポートを投げます。 最後に、まとめです。 まずトランザクション管理についてです。複数のマイクロサービスを跨いでトランザクション処理を実行するために、Sagaを採用したWorkflow Engineを開発し利用しています。 リコンサイルでは、サービスの特性上、リコンサイルすることで、最終的にその処理が想定通り実行されているかを確認する必要があります。それをProcessing Tracerというマイクロサービスを開発することで処理の共通化をしています。 以上です。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】Merpay & MercoinにおけるLLM活用の取り組み – Yuki Ishikawa / Daisuke Torigoe / Noriaki Utsunomiya / hmj【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、Productやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 Merpay & MercoinにおけるLLM活用の取り組み 」の書き起こしです。 @nu2:みなさん、こんにちは。早速ですが、「Merpay & MercoinにおけるLLM活用の取り組み」についてセッションを始めます。現在、世界中のFintech企業も何かしらの投資対象として注目している。LLM技術について、メルカリグループで取り組んでいる内容をお伝えするセッションです。 Merpay & Mercoin Tech Fest 2023の最大の見どころの一つと言っても過言ではないと私は思っていて、非常に楽しみです。昨日もちょうどGoogle Cloud様が、LLM withビジョンという、テキストメッセージに対して、画像検索の形で応答するデモを公開されていまして、これはメルカリの学習データを提供して実現しており、タイムリーな話題になっています。 まずは自己紹介です。私は@nu2と申します。本日は、進行役を務めます。 私は5月に入社するまで、15年ほどWeb検索の領域に関わってきましたので、ここまでLLMが飛躍的な進化を遂げるとは正直思っていませんでした。今回はメルカリからVP of Generative AI/LLMの@mazeさんをお招きしておりますので、ディープダイブした内容を伺いできればと思います。 @maze:こんにちは、メルカリの@mazeです。現在は生成AIの担当役員をやっています。直近では、ソウゾウの代表をやっていました。今は120%生成AI関連にコミットしています。ソウゾウ立ち上げ前はメルペイにおり、メルペイの立ち上げや、金融の与信周りに携わっていました。今日はよろしくお願いします。 @tori:みなさま、はじめましてよろしくお願いします。Torigoeと申します。私は、2018年にメルペイに機械学習エンジニアとして入りまして、あと払いや不正対策の機械学習の応用に携わりました。メルペイの機械学習全体のマネージャーと、LLMや新しい技術を使って価値を出すチームのマネージャーも兼任しています。 今日は半年くらいいろいろ取り組んできたお話の経験を基にできるだけ楽しくお話できればと思います。よろしくお願いします。 @maze:まず、簡単にメルカリグループ全体の生成AIの取り組みを紹介します。 今年の5月に メルカリで生成AI/LLM専任チー ムを作りました。 ミッションとしては二つあります。生成LLMの技術を用いて、新しくお客さま体験を作ることと、それによる事業インパクトの最大化を一つ目のミッションとしています。 二つ目のミッションは、メルカリグループ全体として2000人以上従業員がいるのですが、従業員の生産性を劇的に上げることです。なるべく専任チームを作って、機動的に動ける形にしています。 チームでは、EnablingとBuildingの二つを掲げて進めています。 生成AIの技術は特定のチームに閉じるべきじゃないと思います。できればメルカリの従業員2000人全員が、十分に使えるという状態にしていければなと思いますので、なるべく推進できるようにする活動も僕らのチームとしてEnablingとしてやっています。 もう一つ、僕らはなるべくものを作れるチームで、Buildingでやっております。 Enablingについて、具体的にやっていることとしてまず挙げられるのが、ガイドライン策定です。 メルカリはこれまでもずっとAIに投資していまして、MLエンジニアも多数在籍しています。生成AIはAIの民主化的側面もあり、一般のソフトウェアエンジニアの方でも、気軽に触れるようになったと思います。皆さんが安心してAI開発できるように、各所と連携しながらガイドラインを作っています。 また、みんな「気になっているけれど忙しい」ということもあるので、ハッカソンの機会を作っています。3ヶ月おきに開催しており、頻度は高いです。 次はBuildingの一例です。僕がチームで初めに行ったのが、メルカリ社員専用のChatGPTを作ることです。Open AI社のChatGPTは、入力した情報が学習に使われてしまうので、メルカリ社員専用の業務内容を入れてもいいChatGPTを作りました。 それだけでは面白みがないので、メルカリ社員であれば無料でGPT4が使えたり、Googleのモデルにも対応していまして、同じプロンプトで出力がどう変わるかも試していただける形で作っております。 僕らが今注力したのはこちらで、既存のプロダクトにLLMを入れていくことに注力しています。グループ全体として、いろいろなFunctionチームがあり、そこと連携しながら、プロダクト開発を進めています。 進め方は、僕らLLMチームが企画から実装まで全部行うパターンと、各種Functionチームにリードをお願いして、プロンプト周りやどのモデル・ツールを使うのかといった細かい相談のみこちらで対応するパターンの2つがあります。 メルカリには、MLエンジニアを持っているチームも多数あるので、その場合は2つ目の「共創」のパターンで、発見を共有し合いながら進めていきます。 施策内容としては、既存プロダクトへの適用だけでもかなり幅が広いです。Fintechとまとめて書いていますが、いろいろな使われ方があります。それ以外に社内ツールの実装や、生成AIを生かして新規事業を考えることも含めていろいろ試しています。 生成AIの専任チームなので、技術の探索もあわせて行っています。モデルの選定について、ビッグテックが出しているLLMのAPIをどう使うのかという話や、OSSのモデルを利用するという話をしています。内製の基盤モデルを作るのも、選択肢としては一応あると思います。 LLMの進展に伴い、非常にいろいろなツールが充実しています。 実際にでてきたら触って、それがどう生かせるかを考えています。毎日何か新しいものが出てくるので、いろいろ試しつつ、メルカリではすぐにプロダクトに活かして、実際に本番環境でどうなるかを見れる、フィードバックをもらえるので面白いと思います。 @nu2:実際にSlackでドックフーディングのように、エンジニアの方たちがいろいろいじったり触ったりしているのを側から見ていて、本当にすごいなと思います。一方でFintechにおけるLLMの導入を進めかたは、メルカリとは違うところがあるのですが、@toriさん、いかがでしょうか。 @tori:Fintechでは、最初にLLMの波がきたときに、当然MLエンジニアが、各々独自に探索する動きはあったのですが、途中で専門でフォーカスしないと世の中に遅れてしまうなと思い、@mazeさんとほぼ同じタイミングで専門チームを立ち上げました。 それ以降、最初の3ヶ月間は、2つのアプローチを取りました。エンジニア自身が企画も含めて考えて、PoCするというアプローチと、MLエンジニアだけだと、どう使えばいいのかが悩ましかったので、LLMを使ったコンテスト(ぐげん会議)を行い、社内のいろいろな人のアイディアを借りるアプローチです。 最初は技術をキャッチアップしながら、どういう使い方をするのかをエンジニアがボトムアップで考えつつ、皆さんのアイディアも借りながら会社全体でどれがいいかを考えてきたところです。 ぐげん会議には、@nu2さんにも出ていただきました。 参考記事: LLMを活用してなにがつくれるか?——「ぐげん会議」開催から見えてきた、AI活用の新たな可能性 @nu2:ぐげん会議や、実用化を目的としたハッカソンを開催されていましたが、実用化したユースケースはありますか。 @tori:今まさにいろいろ仕込み中ですが、新しくPoCして取り組んで、結果としてそれをぐげん会議に出して、入賞したというユースケースがあるので、それについてチームメンバーからプレゼンテーションを用意しているので、ご覧ください。 @hmj:今回はLLMを活用した文章構成の取り組みについて発表します。 私は、@hmjといいます。株式会社メルペイで、機械学習を担当しております。 2018年より株式会社メルペイにて機械学習や、自然言語処理を中心とした与信モデルの設計開発を行い、その後不正検知の領域の機械学習のモデルや、システム開発に携わっていました。2023年4月より、LLMなどの新しい技術をキャッチアップするチームに所属しており、こういった取り組みをしております。今回はこちらの取り組みを紹介します。どうぞよろしくお願いします。 本日のアジェンダはこちらです。初めに概要を紹介し、その後課題や解決策の話をし、最後にツールの紹介と、簡単にまとめをしたいと思います。 では、はじめて行きたいと思います。 まずメルカリではステークホルダーの方とのタッチポイントがこの図の形でいっぱいあります。例えばお客さまに対するアプリ内での通知やキャンペーン情報、CMなどで日常的に多くの場所でメルカリに関する言葉が届けられます。 コーポレートやプロダクトの枠を超えて、数々のメディアや、アプリ内のお知らせでそういったタッチポイントが多くあるのでとても言葉には影響力があります。 そのため、社内の文章であってもしっかりとしたワーディングに関するチェックがとても大事になってきて、チェックをする仕組みが必要になってきます。 今回は文章校正チェックにLLMを活用できないかということでツールの開発を行いました。今回はそちらの取り組みについて紹介したいと思います。 では実際に課題感と、どう解決したかをご紹介したいと思います。 解決したい課題の一つは、ワーディングルールが全ての方に浸透していなくて、活用できないという場面があることです。また二つ目としては、チェックをしてワーディングルールを見ながら行うんですけど、非常に数や量が多くて、人の手でチェックをするのに限界があるということです。そこで求められていたのは、誰でも簡単に短時間でチェックを行える仕組みです。 その中で今回機能として求められていたのは、このようなところにあります。単純に校正した文章を出して終わりではなくてこの三つが求められていることが、社内議論する中で見えてきました。 一つ目は、指摘箇所が文章中でわかるようにすること。文書の中で、どの部分がチェックに該当するのかがわかるようにしたいということです。二つ目は、指摘の理由がわかるようにすること。ある言葉がチェック入ったときに、それがなぜチェックされているのかがわかるように、どのワーディングルールに該当するかを利用者にわかるようにしたいということです。最後に、指摘をして修正した文章を、アウトプットとして取得できるようにしたいということがありました。 続いて、求められていることについて、どういった社内ツールを作ったかをご紹介します。 デモツールの実際に作った画面の一部を抜粋しながら説明していきます。 全体的にデモではあまり説明を入れずに使っていただけることを意識しています。最初に表示するテキストに例文が入ってるんですけれども、ここに校正したい文章を入力するとその下に結果が出てくるというシンプルな仕組みになっています。 特徴的なのは、会社ごとにチューニングされたワーディングルールがあるので、どの部分を活用したいかを利用者の人が選べるようなUIも作っています。Submitボタンを押すと処理が実行されます。 結果はこういった形になっていて、少し入り組んでいるので、少しずつご紹介したいと思います。 1個目がAnnotatedによる指摘です。これは、文章中でどこを指摘したかがわかりやすいように色付きで表示されるようになっています。また、色ごとに理由のカテゴリーが分かれています。 2個目に、指摘の解説です。指摘されている箇所がどういった理由で指摘されているか、どういったワーディングルールに基づいてるかを表示しています。 最後にSuggestion、これは全体の指摘を修正した文書が出力される場所となっています。利用者の方が、指摘がそのGPTによるモデルが合っているとは限らないので、利用者の方が、「絶対違う」というのがあったら、「採用しない」という選択肢も選べるようになっています。 次に裏側のロジックを簡単に紹介します。校正は簡単に三つのステップで成り立っています。 一つ目が、誤字・脱字・誤植や文法ミスのチェック。二つ目は、会社独自のワーディングルールに照らし合わせたチェック。最後に、内容が間違っている、あるいは最新の情報ではないなどのチェックです。 それらを実装するために、今回作成したフローは、こういった形になります。利用者の方が、インプットしてアウトプットするという流れに対して、それぞれ誤字脱字、ワーディングルール、公開情報とのチェックを行います。 全てLLMではなくて、自然従来の自然言語処理を使いつつ、OpenAIの Chat completions API のプロンプトで、柔軟に工夫しています、公開情報とのチェックについては外側からデータを入れ、どこが間違ってるかをチェックするという活用の仕方をして、フロー作りました。 最後にまとめに行きたいと思います。 今回のまとめとしては、LLMをGPT-3.5のモデルを活用して社内の文章校正ツールを作りました。文章の生成や修正理由の指摘はLLMが得意なところだったのでLLMに任せました。 逆にLLMでなくてもできるところは従来の技術や他の方法を使って棲み分けることで実現できました。 私自身MLエンジニアですがLLMという学習済みのモデルをどう使うかが、今までとは少し仕事の内容が違ったので、今後そういった取り組みを踏まえながら、どこでバリューを発揮できるかを考える機会になりました。今回とても面白いチャレンジングな取り組みができたんじゃないかと思います。 @nu2:ありがとうございました。先ほど、@toriさんからあったぐげん会議で私もスポンサードさせてもらったのが、障害報告書を自動生成するものでした。 そのような活用方法がデフォルトで考えうる使い方だなとは思います。FintechにおけるLLM応用の特殊性について、着々と実用化の準備が進んでいるとのことですが、Fintech事業ならではの応用について特殊なことってありますか。 @tori:一つ明確にあると感じるのは、金融商品は法律や自主規制など、いろいろな前提の上に乗っかっているもので、お客さまに伝えたいことも難しくなってしまうんですよね。 これに対して、ルールベースでいろいろコミュニケーション取ることはできますが、どうしても単調でわかりづらく、伝わらないこともあると思います。 こうした課題に対して、LLMは単調ではなく柔軟にしたり、固い表現を温かみのある表現にしたり、難しいものをわかりやすく変換して、よりプロダクトや金融商品とお客さまの距離を近くしてくれるアプローチに使える可能性があると思います。まさにLLMじゃないとできないポイントだと思います。 また、社外のお客さまとの接点だけでなく、社内にも全く同じ問題がありました。内部的なリスクチェックや省庁への報告などをエンジニアやリスク管理など、専門性をまたぐようなコミュニケーションに対して、同じ日本語を扱ってるんですけど、相互に理解したり、同一の文書にまとめたりするところが難しいです。 こうした社内のコミュニケーションやドキュメントをスムーズにして、結果として質の高い金融サービスをお届けするという点でも、可能性を感じます。 @nu2:障害報告書でもアウトプットに高い品質が求められると思うのですが、品質管理については今後どのように取り組んでいくかを聞かせてください。 @tori:正直言うと、悩みながらやっています。走りながら同時に道路を作っているようなイメージです。 Fintech関係なく、様々なドメインでそれぞれ共通的に気にするポイントがあるので、@mazeさんと連携しながら、社内の集合知としてガイドラインの形で作っています。ハルシネーションや、個人情報保護の観点、制度品質の担保などにフォーカスしています。 ただ、システム単体で見るというよりは、誰に対して向けているものなのか、お客さまとの間で取り決めするポリシーすらも変数として、総合的に必要な品質を考えるべきだと思います。 @nu2:もう少し応用性をちょっと深掘りして、ドメイン問わずお伺いしていきたいなと思います。私も今まで出てきたものにも触ったりしてるんですけれども、そんなに誰もが利用したいと思えるツールがChatGPT以外があんまり見当たらないなと感じています。 実際に現場で苦労しながら、取り組んでる点やどのような価値の創出や出し方が考えられていますか。 @mazu:ドメインを問わずで言うと、いくつか今入れてるところを抽象化して考えると、人が本来あまりやらなくて良いところや、機械化されることで人が解放されたり、クリエイティビティが発揮されるところに時間をより使えたりするところなど、何かにおまかせしたい仕事という部分がフィットするパターンが多いと思います。 クオリティ・精度を考えると、人手で時間をかければ90〜100%の精度でできるところも、スピードが重要で、60%の精度で良いところにLLMを使ってショートカットすべきところについては有効だと思います。 LLMを使わなくてもできるエリアでも使うことはあります。例えば、SEOのロジックにLLM使っていい感じのmetaタグ作ってみたり、分析のRAWデータを入れて、1人で分析するのではなく、GPTに分析してもらうことも、前処理的に入れるとかなり時間を短縮できるなという印象はあります。 @tori:ぐげん会議では、開発期間が1ヶ月もなかった中でとても良いプロトタイプが出せまして、これは一面でいうと成熟した技術をしっかり丁寧に使えば100点取れますが、LLMで60-80点のものを過去にないスピードで作れる長所が活きたということだと思います。 例えばテキストのポジティブネガティブ分析は、LLMでも準備なくとても良い精度のものが出せるので、これは典型だなと僕は思います。 @maze:おっしゃる通り、NLPを今ままでやってきた人にとって大変な作業が、すごい速さで実現できます。 @nu2:あとは、一般の方たちがどう使うかという問題もあると思います。我々はプロンプトエンジニアリングの観点で、コンテキストを突き詰めて、パフォーマンスを引き出す術を、ある程度もっています。一方で、一般のお客さま様・消費者は、何を聞いていいのかがわかりません。ハイコンテキストをローに落とすという変換が大事だと思います。 最後に、今後の方向性についても、お伺いできればと思います。 @maze:メルカリグループは非常にグループ間の敷居が低く、僕もメルペイに以前在籍をしていて、その後ソウゾウに行って今またメルカリに所属しています。引き続き各社グループ会社と連携しながら、それぞれが得た発見をなるべく共有していけるといいと思います。 プロダクト面については、メルカリグループにあるデータを活用して、お客さまの体験を便利にしていきたいです。解くべきIssue自体はこれまでと変わらないので、新しい手法で解決しに行くこと進めていけたらと思います。 社内の生産性の観点で言うと、生成AIを使える方をとにかく増やしたいです。なるべく社員が生成AIを使う機会を用意し、使いこなせるようにするサポートも引き続き進めていければと思います。生成AIを使いたいと思われてる方は、メルカリグループにジョインするとチャンスがあるんじゃないかと思います。 @tori:日々技術が進化していくので焦る気持ちもありますが、シンプルに長く使われる、かつLLMにしか解決できなさそうな問題に対してのプロダクトをリリースしていきたいです。 @nu2:メルカリ生成AI/LLMチームは、絶賛優秀な方を募集しています。スライドのQRコードを読み込んで、応募いただければと思います。 本日はご視聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルカリのカスタマージャーニーにおける不正防止の取り組み – codechaitu 【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルカリのカスタマージャーニーにおける不正防止の取り組み 」の書き起こしです。 @codechaitu:みなさん、こんにちは。Merpay & Mercoin Tech Fest へようこそ。本日は、メルカリ・メルペイのシステムにおいてカスタマージャーニーでの不正防止の取り組みについてお話しします。 まずは、自己紹介します。私のニックネームは、@codechaituです。大学を卒業して2018年にメルカリに入社しました。その後、CRM関連のツールを社内で構築するプロジェクトなどいくつかのプロジェクトに関わりました。2022年11月に不正取引についてもっと学ぶため、メルペイへ異動しました。 トピックに入ります。メルカリのカスタマージャーニーとはどういう意味かを理解するにあたって、タイムラインを見ていきましょう。まず、お客さまがいます。 次のステップとして、アプリの登録を行います。 同じルートを皆さんがたどることになります。ここでは、新規のお客さまや既存のお客さまからの不正を防ぐために最大限の注意を払っています。 次のステップでは、私たちは不審なお客さまか普通のお客さまかをチェックします。では、見ていきましょう。 すでに利用制限がかかっている不審なお客さまが、ある商品にいいねをしたがっていますが、このときに制限がかかっています。同様に、コメントを入力しようとすると、やはり制限がかかっています。 同じように、もしこの人が商品を購入しようとしても、購入は制限されています。 続いて、普通のお客さまについてです。 普通のお客さまがホームページで何か商品を購入したりいいねをしたりしようとすると、それが実行できます。商品を購入することも可能です。制限はありません。 そのお客さまが不審だと思った場合だけチェックをして、不審ではないと判断されれば、彼らはその後、任意の取引を行えます。 次は、取引を実行するステップに進みます。 この取引は、商品を購入することや商品を販売すること、いいね!として登録することなどを意味しています。 ここでは、お客さまが取引を実行すると、一連のステップがさまざまなマイクロサービスを経由して行われます。私たちのマイクロサービスまたは私たちのチームTrust&Safety(TnS)チームに通知されます。 それでは、次に私たちTnSチームのシステム概要を紹介します。 ここでアーキテクチャと、どのようなステップを踏むのか、お話をします。ここには四つのステージがあります。では一つ一つずつ説明をしていきます。 まず、最初のステップ・Sourcesです。これは、change data caputure(CDC) や他のマイクロサービスからデータを受け取ります。 例えば、お客さまが商品を見ようとしていいねを押しました。これは、イベントとなります。コメントした場合、また別のイベントとなります。全てのイベントのストリームがあります。これはCDCプラットフォーム上で実行されます。 他のマイクロサービスからのデータを見ることもできます。いいね!を管理するサービスやコメントを管理するサービスなどです。また、3rd partyのデータも使用します。これはTnSチームになります。 二つ目の段階です。データの前処理を行います。なぜこれが必要なのでしょうか?それは、膨大な量のデータが、さまざまなマイクロサービスや他のチームから来るからです。しかし、処理をするためにはこのフォーマットを私たちが処理可能な形式に変更する必要があります。 そのため、前処理を行っていきます。複数のインプットからのデータを処理します。 ここで二つ、チームで開発された機能で私が最も気に入っているものがあります。 まず一つ目は、あんしん支払い設定、英語に言い換えると、Safe payment settingsです。 この機能について見ていきましょう。 これはダミーの例です。メルカリのお客さまが、フィッシングサイトとは知らず、攻撃者が開発したサイトにIDやパスワードを入力してしまった場合です。メルカリのお客さまは、フィッシングサイトであるということを知らないので、お客さまは認証情報を入れてしまいます。攻撃者はその認証情報を使って実際のWebサイトにログインします。 これが新しいデバイスからであれば、メルカリは実際にお客さまであるかどうかを確認します。そのときにOTP(One Time Password)を送信します。攻撃者は、フィッシングサイトでも同じOTP画面を表示させようとします。お客さまがフィッシングサイトにOTPを入力すると、攻撃者がOTPを取得し、実際のメルカリアプリに侵入します。このように、メルカリへの不正アクセスが可能となります。 これを防ぎ、メルカリのお客さまに金銭的な損失を与えないようにするために、ある種のロジックを用意しています。 簡単な例で見ていきましょう。新しいお客さまのログインがあった場合です。ここで新しいデバイスからかどうかをチェックします。新しいデバイスの場合には、あんしん支払い設定のお客さまオプションを有効にします。このときお客さまは支払不能となりますが、後であんしん支払い設定を無効にできます。 新しいデバイスでなければ、あんしん支払い設定は発動せず何も変更されません。お客さまがフィッシング攻撃によって金銭的な影響を受けないことを保証しています。これがあんしん支払い設定機能です。 二つ目の機能は、 3D Secureです。 メルカリのお客さまがクレジットカードを使ってメルカリで「商品を買いたい」とリクエストします。メルカリは、クレジットカード発行会社にリクエストを出します。これが実際のお客さまのものであれば、カード会社はこれは低リスク取引と判断します。 しかし、他の悪質な行為者が、クレジットカードを盗み、メルカリで購入しようとした場合、メルカリは、悪質な行為者が使用したカードを認証するために送信し、ある計算に基づいてリスクをチェックします。 悪質な行為者がOTPやパスワードを扱おうとしても、メルカリ側で、ハイリスクであると判断されれば取引が拒否されます。 お客さまの購入取引がある場合、それが正しいかどうかをチェックし、問題がなければ取引を継続します。もし不審な取引であれば、3D Secure機能を利用することになります。 3D Secureの認証によりその取引がSecureと判断された場合、取引は続行され、そうでない場合は取引が拒否されます。 次のトピックは、Rule Engineです。複数のソースからのデータを処理し、チームがデータを利用して結果を得ることができます。これが不審なトランザクションがどうか、その発見に使用します。現在は、Rule EngineとしてSplunk Cloudを使用しています。 システムには、多くのルールがあります。それを使って、疑わしい取引かどうかをチェックします。次のセクションで例を挙げます。 現在私たちは、バッチ処理でSplunkを使用しています。最近では、リアルタイムの不正検知を行うようになり、そこではApache Flinkを使っています。 なぜApache Flinkを使うのか、お話しをします。 私が個人的に検討した二つのオプションを比較します。一つはGoogle Dataflow、もう一つはApache Flinkです。 Google Dataflowの主なメリットは、フルマネージドサービスであることです。高負荷時には自動スケーリングが有効になります。これは本当に良いオプションです。 しかし、デメリットもあります。デベロッパーサイトではチェックポイントを実装できません。また、Flinkが提供している高可用性オプション、Dataflowでは99.9%のSLAはありません。 そして、私たちにとってかなり高額になるからです。そこで私たちは他の選択肢を探しApache Flinkを見つけました。 ApacheFlinkのメリットは、Check PointingやSave Pointingができることです。OSSなので、Kubernetes上にジョブをデプロイでき、デバッグも簡単にできます。また、社内でFlinkに取り組んでいるチームがありますので、必要に応じて彼らがサポートしてくれます。 デメリットは、全てのリソース管理をしなければならない点です。これらの選択肢のメリット・デメリット・他のいくつかのパラメータを勘案し、Apache Flinkの採用を決めました。 これは、TnSでのアーキテクチャの概略図です。 他のバックエンドのマイクロサービスからPub/Subへ、ほとんどのインフラはGCP上にあります。インプットPub/Subトピックから前処理に行き、FlinkとトピックPub/Subへリアルタイムでデータ処理を実現したいので、事前処理されたデータはKubernetes上のFlinkに送られます。 Flinkには、ルールや実行すべき定義されたロールが含まれています。このFlinkがデータを処理し、アウトプットPub/Subトピックに送信をし、データは他の下流のサービスで使われます。 例を挙げましょう。 あるお客さまが6時間以内で100万円以上使った場合、疑わしい取引であるとみなされます。 以前のマイクロサービスと違う事として、小さな変更を変えました。Cloud Schedulerを使って、ある時間枠内にイベントを送信するようにしました。 すでにデプロイされており、ジョブマネージャー、タスクマネージャーが動きます。クラウドSchedulerを作成し、FlinkSQLと命名し、毎分実行されます。 実行後、Pub/Subトピックが置き換えられ、データを取得ができます。この例のテストデータでは、ユーザーID「1234」を使用しており、総購入額が収録されており、100万円を超過していることがわかります。 ここでは、処理するべき多くのルールがあります。開発時に開発環境にデプロイして出力結果が期待通りかどうかをチェックするのは、簡単な作業ではありません。そのため、デプロイを行う前に、ローカルでデバッグを行います。 全ての手順はGitHubにあります。サンプルデータを提供していますので、ご自身のローカルマシンでFlinkの使い方を試してみてください。 次は、ローカルでデバッグするための例です。 SQLのゲートウェイを使って、Flink SQLのジョブのデバッグをします。最初のステップは、SQL クライアントの初期化でFlinkで実行しています。init scriptを実行しています。これで、必要なSQLの処理を実行できるようになりました。Flink SQLのクライアントも起動しています。 user_transaction_sourcesというテーブルを作成しました。これは前の例でCloud Schedulerが全てのデータを送信するソースデータとなります。しかし、今回はローカルのテストデータを使うので、ユーザーID、商品ID、購入金額、購入時間など、いくつかのパラメータだけを取って、その他のいくつかのフィールドにデータを入力します。 もう一つのテーブルには疑わしいユーザーIDとそのお客さまが6時間以内で使った合計金額が表示されます。100万円に達した場合のみ、フィルタリングされます。 ここまでで不審なお客さまのテーブルが前のステップで作成されました。合計金額が100万円を超え、かつ6時間以内であれば、疑わしい取引であるとみなされます。この情報は、他の下流サービスにも送信されます。このデバッグステップでは、ロジックの正当性を確認します。 insert.SQLを使います。テストのデータを見ると、四つのレコードがあります。私が最も注目しているのは、ユーザーID 1234です。3回の購買があり、過去6時間以内で100万円を超える支出をしています。このお客さまの取引は、疑わしいと考えられるでしょう。 さらに、insert.SQLを取り、コピーをし、Flink SQL クライアントで実行すると、ユーザーID1234が選択され、予想通り100万円を超えている状況です。Flink SQLクライアントでジョブIDの出力を確認できます。ジョブID、「541完了」となっています。完了すると、 データの出力先が表示されますが、ここではexample directryとなっています。ここでも、ユーザーID1234、100万円を超える購入金額が見れます。 もし万が一エラーが発生した場合、ログのセクションでなぜエラーが発生したのかというステートメントがありますので、これを使ってデバッグできます。これが、リアルタイムで不正検知を行うために、Apache Flinkで実装したステップです。 次に、出力処理です。これが私たちのチームでは最後のステップです。ブロック単位として考えた場合、ここではお客さまの取引が疑わしいか否かを、マニュアルでチェックします。 疑わしいと判断された場合、社内のカスタマーサポートチームが判断した上で、そのお客さまに対して疑わしいというマークをつけ、その後、お客さまに何らかの制限をかけるステップが取られます。 例えば、何日以上は売ってはいけない、何万円以上は買ってはいけないといった制限です。これは、取引ごとに変わります。出力データに基づいても変わってきます。 さらに、GCPのMemorystoreを、重複するイベントをフィルターするためにキャッシュとして使用しています。 これは、ApacheFlinkが疑わしい取引を見つけた場合や大きなアプリケーションのウィンドウを使用する場合、複数のイベントが発生してしまいます。それらにフィルターをかけるために、GCPのMemorystoreを使用します。 最後に、このような活動をする大きな理由は、メルカリの不正取引を防止し、全てのお客さまに安全な環境を提供したいからです。わずかな時間のご説明となりましたが、私たちは全てのお客さまにとってより良い場所をつくるために日々努力をしています。 お客さまが安全な取引を続けることができれば、お客さまの満足度・信頼度が上がるでしょう。それが私たちのミッションでもあります。 以上です。ご清聴ありがとうございました。ぜひ、Apache Flinkをお試しください。
株式会社メルカリ
2023/10/23
【書き起こし】Building a Global environment at Merpay: India & Japan – Robert Jerovsek / Keigo Andrade / Sumil Panicker【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 Building a Global environment at Merpay: India & Japan 」の書き起こしです。 @robert:皆さんこんにちは。本日はセッションにご参加いただいてありがとうございます。「Building a Global environment at Merpay: India & Japan」というタイトルのディスカッションです。 @robert:私はRobertといいます。ヨーロッパ出身です。過去にはいろいろな国で仕事をしておりまして、メルペイには5年ほど前に入社しました。元々はバックエンドエンジニアをしておりました。今はエンジニアリングマネージャーをしています。 @keigoand:私はブラジル出身のKeigoと言います。私はわりと早くコンピューティングエンジニアリング、ソフトエンジニアリングを始めました。ドイツに引っ越し、インドオフィスのチームと仕事をしていたこともあります。メルカリに入社したのは2021年で、エンジニアのマネジメントを数年前から務めております。 @Sumil:私はSumilと申します。私はエンジニアリングマネージャーとしてメルカリのインドオフィスから関わっております。メルカリインドには2023年2月に入社し、Growth Platformで仕事をしています。メルカリに入る前は、Amazonで5年ほど経験を積み、10年ほどCiscoで仕事をしておりました。 3人ともインドのオフィスからライブで参加しています。このトピックに大変わくわくしております。 @robert:昨年のMerpay Tech Festに参加した方もいらっしゃると思います。その当時私たちはグローバルなプランについてお話ししました。 インドのCenter of Excellenceを開設 するということで、当時は何が起きるのか、誰が関わるのか、どういう課題があるのかもわかっていませんでした。 しかし、メルカリのバリューである「Go Bold」を元に勇敢に進め、1年ほどいろいろな経験を積みました。今日は、その進捗を共有します。 参考記事: 【書き起こし】 Building an inclusive multicultural environment at merpay: Past, Present and Future – Tim、Robert【Merpay Tech Fest 2022】 メルカリは、「Marketplace」と「Fintech」にわかれています。Marketplaceは、フリマアプリ「メルカリ」で誰でも安心して簡単に売り買いが楽しめるプラットフォームを提供し、FintechはiD決済などのメルペイ、アプリ内で完結するクレジットカード「メルカード」などさまざま金融サービスを提供しています。日本国内の開発で、「Marketplace」と「Fintech」はお互いに連携しています。 インドオフィス設立時、どこの開発を担当してもらうかを考えました。日本国内の開発と同様、「Marketplace」と「Fintech」の開発両方に関わってほしいという気持ちはあるものの、「Fintech」の開発は難しい部分がありました。日本の金融サービスということで、セキュリティや言語などについての検討が必要です。そこで、「Fintech」領域ではそこまで金融特有の課題が少ないGrowth Platformの開発に関わってもらっています。 @keigoand:マーケティングもグロースの一つです。いろいろなツールやサービスがキャンペーンに使われています。例えばバナーやランディングページ、通知、インセンティブなどでお客さまとコミュニケーションをとります。 Growth Platformのエンジニアリングはメルペイに所属しています。日本リージョン全体に提供するもので、影響力がたくさんあります。 また、いくつか決定的な瞬間がありました。1年ほど前、10月にバンガロールのオフィスを訪問しました。当時すでにいくつかのチームメンバーがインドのオフィスに参加していて、メンバーの選考やオンボーディングをしました。10月は、このチームにとっては大変決定的な瞬間で、インドのオフィスでは重要なタイミングでした。選考した人たちが今も在籍しているので、それは良かったと思います。 そして1月には、開発プロセスをよりよくするためにスクラムの改善を検討・調整しました。 2月にマネージャーとしてSumilが入ったことで、コラボレーションをさらに強化できました。それまでは、多くの人たちが入社して問題も多かったのですが、メルカリの10周年の頃に落ち着いてきました。 @Sumil:私は2023年2月頃に入社しました。 3月に、日本オフィスを訪問する機会がありました。オフィスに訪問するまでは、まだまだまとまっておらず、うまくいったことも改善しなければならなかったこともたくさんありました。どこを調整すべきなのかを直接お話しする、良い機会となりました。 その副次効果として、お互いの関係をチームの中で構築できたことはよかったと思います。そして、お互いに安心できるようになりました。以前のコミュニケーションはオンラインだったので、直接会ったのが良かったと思います。 当時の方向性として組織が考えていたのは、インドチームを自律的にしようということです。そして次の四半期の責任やロールを検討し、インドからテックリードのロールを持つというのが一つの方向性として決まりました。 それ以降、「自律性を持つ」という方向性に基づいて、4月頃にインドチームが日本オフィスをサポートし、より自律できるようになりました。それ以降、日本人がインドオフィスを訪問してきました。これによって、さらに絆を深めることができたと思います。 @robert:続いて、どのような課題があったのか、どう乗り越えたのかをお話ししたいと思います。 @keigoand:この写真は10月に私がバンガロールに来たときの写真です。ホワイトボードでの打ち合わせを行い、対応すべき課題が見えてきました。例えば、当時はやらなきゃいけないこと・やりたいことはありましたけれども、そのプロセスがあまり明確ではありませんでした。 またカルチャーも異なっており、それも課題だったと思います。カルチャーは何なのかという定義も必要ですが、言語の壁もありました。それらの課題というのが結果的には強みにもなったと思います。期待値や人材の採用といった課題もあったので、次に、深掘りしたいと思います。 プロセスの不明瞭さについてはどう対応したのでしょうか? @Sumil:プロセスについて、コンテキストを明確にしました。インドと日本だけではなくさまざまな国籍の人たちがチームに関わっています。連携をし始めたときに何が面白かったかといいますと、チームがスクラムをしようと言ったときに、スクラムを普遍的に理解できたことです。それがチームの基礎となり、どうやって実行するのかという基盤になったと思います。 全てを教科書通りに行っていたのですが一つ例外があります。それは日々の進捗についてです。毎日30分くらいの定例を行っていました。チームの何がうまくいったのか、昨日やったのは何なのか、今日何をしなきゃいけないのかを共有しました。ディスカッションがある一定領域を超えたら、そこから派生してもいいということになりました。それが6、7ヶ月ぐらいうまくいっていたと思います。 もう一つ補足したいのが、みんな何かしらのアクセントがあることです。喋るとき、アクセントがわかりづらいというときもあります。それから面白いのが、誰かがミーティングを行っている間、何かを書き留めています。それによってメンバー全員に内容が伝わったと思います。 また他のドキュメントもあります。たとえば、ディスカッションしたかがわかるデザインのドキュメントも使いました。これが、そのコラボレーションで役に立ったと思います。 @keigoand:ただ、全てパーフェクトにはなりません。スクラムでも制約があります。ただ、クリアなプロセスがあるということで、これは非常に役に立ちました。さらに、ドキュメンテーションもなかなか簡単ではありません。またコミュニケーションにも時間がかかるということもあるんですよね。 また、柔軟性も非常に重要だと思います。文化が違うところもあるので、これが我々の強みだと思います。 @Sumil:我々は文化の違いの話をしてきましたが、個人個人でも違うわけです。非常に多様性があります。メルカリでも個人個人のレベルでも尊重していると思います。 例えばディスカッションしていると、問題に対して楽観的に見ています。しかし、個人個人、ある部分を見てないこともあるかもしれません。そうすると誰かがこういう非常にクリティカルな過程からそれを見たときに、その人が問題を提起することもあります。 そういう意味でそれぞれのこの意見の違いを尊重しています。そうすることで、正しい意思決定ができると思います。開発の中ではこういったものを、やっていくわけですが、プランニングデザインのディスカッションでも同じようなことが起こると思います。また楽しむということも大切です。例えば新しい言葉を学ぶということを楽しんでいます。 @keigoand:私は食べ物に関連する言葉をよく学びました。技術的なところでもそうだと思います。技術的な言葉を学ぶのは面白かったです。 @keigoand:言語にいろいろなバリアがありましたが、もう1年くらい経っています。Global Operations Teamのサポートでチームミーティングや1on1などいろいろなミーティングをしています。 DeepLは、翻訳ツールです。日本語・英語に翻訳することができます。情報を共有したいときにはDeepLをよく使います。 @robert:日本人以外にも非常に多くの人たちが日本語をしゃべります。ただ、言語を学ぶというのは時間がかかりますよね。 ある日、インドオフィスのエンジニアが英語で書いたテキストを日本語に変えました。そして日本人のカスタマーサポートメンバーが回答を日本語で書いて、さらにDeepLで翻訳してといったコミュニケーションをSlack上でとっていました。これはいい例だと思います。 @keigoand:このメッセージが日本語だったら、「この言語は知らないから」と無視してしまうかもしれません。しかし、カスタマーサポートのようなチームでは日本語の方が都合がいいこともあります。一方、エンジニアはドキュメンテーションは英語の方ががいいと言っています。お互いに話をするということが必要な際に、DeepLは非常に役立ちます。 @Sumil:続いて、Availabilityについてです。これも、非常に面白い内容です。 インドと日本では、Timezoneが違います。日本は3時間半早いわけですよね。このチームの中には12時間のAvailabilityがあります。 また、オーバーラップの時間があるということもあります。このオーバーラップを1人当たり持つということで、ここでコラボレーションができるという利点があります。祝祭日がありますが、グローバルですから、誰かがすでに働いています。よって業務に支障は出ません。 本番へのアクセス、例えばインシデントが起きた時にどうするのかという問題があるのですが、法的な要件がありますから、それ以外のところでは、本番環境にアクセスするときにはアクセスコントロールがあります。 @keigoand:また、期待ということで、これもみんなでお互い理解するのがいいと思います。コミュニティ・委員会のようなものがあり、Site LeadやCTOがいて、そういった人たちとも定期的にミーティングをしてサポートしてもらっています。 特に最初はより多くのミーティングを設け、お互いを理解するようにしています。またそれを文章化しています。いろいろなポイントについてお話をしますので、期待値を文章化したドキュメントがありました。 @keigoand :もう一つはHiringです。 インドオフィスの立ち上げを成功させるために、理想的ではないけどエンジニアリングマネージャーを採用する前に、現場のメンバーから採用をしました。エンジニアリングマネージャーを採用することは、より時間がかかるからです。プロセス自体はきちんとルール付けをしました。 Hiringだけではなく、採用後のチームの仕組みなどのオプションについてもマネージャー同士でディスカッションしました。 特に新しいことを始めるときにはいろいろな人を採用します。そこでは完璧な方法といったものはありませんが、プランが1回策定されるとあとは楽になっていきます。 @Sumil:それから、チームビルディングについてもたくさん話をしました。これは、日本人がインドのオフィスに来た時のものです。エンジニアたちがいろいろなことを一緒にやってるということで、非常に大きな絆を作ることができました。 インドオフィスがオープンして1年になるので、パーティを今週行います。非常に良いタイミングだと思います。このような形の新しい写真が各々増えていくと思います。 参考記事: Japan’s Largest C2C Marketplace Mercari, Expands Presence in India -Expands GCoE footprint and inaugurates new office- @robert:最後に、今後についてお話ししていきましょう。 @keigoand:我々が改善すべき点は、監視やインシデント処理です。進捗は良いですが、さらに進めていく必要があります。また、サービスの統合をMarketplaceやメルペイチームと一緒に進めていきます。 @robert:また、メルペイ/メルコインについてです。Fintechは日本で行うため、法律の規制が伴います。ここでも、ベストプラクティスを共有することが大切だと思っています。 オペレーションやOKRを調整することが必要になると思います。日本リージョンからスタートして、メルカリ全体のために我々は仕事をしております。またいろいろなOKRのプライオリティの調整はなかなか大変ですが、今後も成長していきたいと考えております。こういったセッションは、ぜひ来年もやりたいです。 以上です。ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルコインのインフラ設計・構築と、信頼性のあるサービスをリリースするためのSREの取り組み – Masaki Iino / Takaaki Yuhara【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルコインのインフラ設計・構築と、信頼性のあるサービスをリリースするためのSREの取り組み 」の書き起こしです。 @m-iino:本セッションでは、「メルコインのインフラ設計・構築と、信頼性のあるサービスをリリースするためのSREの取り組み」についてお話しします。 まずは、プレゼンターの紹介です。私はIinoと申します。2019年5月にメルチャリに参画し、インフラとバックエンド担当。2020年2月からメルペイSREチームに参加。2021年からメルコインSREのテックリードとして、メルコイン事業の立ち上げを担当しています。 @yuhara:このプレゼンの後半を担当する、Yuharaといいます。2021年からメルコインのSREチームでネットワークやインフラ周りを中心に立ち上げを担当しました。よろしくお願いいたします。 @m-iino:本セッションでは、前半と後半に分けてお話しします。前半は、メルコインに求められるセキュリティとコンプライアンスへの取り組みについて説明します。後半は、インフラの全体像と信頼性のあるサービスをリリースするための取り組みについてお話ししていきます。 それではまず、セキュリティとコンプライアンスへの取り組みについてお話しします。 メルコインとは、メルカリアプリ内でビットコインの売買ができるサービスを提供する会社です。2023年3月9日より、暗号資産交換業を開始しました。本セッション内では、メルカリアプリ内の暗号資産取引サービスを「メルコイン」としてお話しします。 そんなメルコインのインフラに求められるものとは、何でしょう。暗号資産取引所システムは、金融取引を取り扱うため、セキュリティとコンプライアンスが非常に重要な要素となります。 セキュリティについては、暗号資産取引所は、サイバー攻撃や不正アクセス、ハッキング等のリスクを抱えています。そのため、強固な情報セキュリティを有することが必要です。 コンプライアンスについては、暗号資産取引は各国での法律や規制に基づいて運用管理されているため、各国の法律や金融監督当局の規制を遵守する必要があります。 これらのセキュリティとコンプライアンスを適切に管理し、コード化することで、お客さまデータの保護と取引所の信頼性を維持することが可能です。 メルコインのセキュリティ規程や要件は、メルカリやメルペイとは異なります。 暗号資産ビジネスの特性上、さまざまなサイバー攻撃への対策を行う必要があります。また、国の規定が急に変更される場合は、即座に対応しなければなりません。そのため、メルコインは、メルカリ・メルペイとインフラを分離することで、守るべきポイントを減らし、急な規制変更にも耐えられるよう、コンパクトにすることを目指しました。 暗号資産取引所システムのセキュリティとインシデント管理には、高い水準が求められます。理想はその水準を全てのカンパニーで満たすことですが、すぐの実現は容易ではありません。例えば、インフラを分離せずメルコインをメルカリ・メルペイのインフラと同居させた場合、メルカリ・メルペイのシステム管理体制や運用に大きな影響を及ぼします。 メルカリ・メルペイで発生したインシデントをメルコインに伝播させないためでもあり、逆に攻撃される可能性が高い暗号資産取引所システムへの攻撃をメルカリ・メルペイに波及させないためでもあります。 将来的には、全てのカンパニーでメルコインと同等のセキュリティコンプライアンス基準を満たす予定です。 プロダクション環境における具体的な分離例を説明します。まず、Google Workspaceがメルコインとメルカリ・メルペイで分離されています。既存のmercari.comに対して、mercoin.comというGoogle Workspaceを用意しました。 GCP Organizationも、それぞれのWorkspaceに存在しています。しかし、Billing Accountは、共通のものを使用しています。これはメルカリがGoogleと交わした契約条件などをメルコインにも適用するためです。 複数のGCP Organizationで共通のBilling Accountを使うために、GCPのMulti Billingを使用しています。この機能は、最大で五つのOrganizationに適用することが可能です。数が限られているため、よく検討し、慎重に適用する必要があります。 開発者が誤った設定をすることで、原因が生じる可能性があります。開発者が意識せずとも、セキュリティが保証されるべきです。そして、新たにmicroservicesを追加してもセキュリティを保つべきです。そのため、メルコイン全体でSecure by defaultを目指すことになりました。 メ゙ルコインでは、メルカリグループが積み上げてきたセキュリティ機能や設計を受け継ぎつつ、1から作れる強みを生かして、初めからセキュアな状態を作り、維持することを目標としています。また、セキュリティ設定を後から追加していくのではなく、初めから使える設定を最小限にすることで、開発者が意識せずとも危険な設計をしてしまうことを防いでいます。必要に応じて部分的に例外を許可するようにしています。 GCPの Organization Security Policy をGCP Organization全体にかけることで、サービスが増え、新たにGCPプロジェクトを作成しても、初めから危険な設定ができないようになっています。 プロジェクト発足時からセキュリティチームと協力して、全てのOrganization Security Policyを一つずつ検討し、Organizationレベルでポリシーを適用しています。検討の際には、Googleが提供している Google Cloud Security Foundations guide や CIS Benchmark の推奨事項も参考にしながら、ポリシーを作成しました。 ここで採用しているポリシーの一例を紹介します。SSH keyをGCEのMetadataに埋め込んで使うことを防止し、ブートローダーやOSの改ざんも防いでいます。GCEのデフォルトサービスアカウントへのエディター権限の付与も制限しています。また、GCSのパブリック公開も制限しています。 IAMに関しても、最小権限を設定したカスタムブラウザロールを用意し、各チームに合わせた、GCPフォルダレベルで各チームにロールを増やしています。例えば、プロダクション全体を見るSREチームには、広い範囲で最小権限を有効にし、microservicesチームには、担当するmicroservicesを束ねるチーム用のGCPフォルダーに対して最小権限を付与しています。 オペレーションなどで権限昇格が必要な際には、「Carrier」という社内製の権限昇格ツールを使って一時的な権限昇格を行います。Carrierについては、セッションの後半でも説明します。 また、Security PolicyでカバーできないものはPRCの項目に追加し、新規サービスのリリース時など、定期的にチェックを行っています。 セキュリティとコンプライアンスの観点からメルコインのインフラに対して、メルコインのチームがオーナーシップを持つ必要があります。 メルカリグループでは、Mercari SRE、Merpay SRE、Mercoin SREと、それぞれのプロダクトごとにSREチームが存在します。 それぞれのSREチームが担当するプロダクトを安定的に動かすために、インフラの開発運用や、microservicesのサポートを行います。プロダクトごとのSREとは別に、インフラ基盤の開発・運用をするPlatformチームがいます。インフラ全体のオーナーは彼らが担っています。 メルコインSREと比較するために、まずはメルペイにおけるSREについて説明します。メルペイでは、SREが開発チームのサポートをしつつ、メルペイが共通で使うシステムの開発管理を行っています。Platformチームはインフラコンポーネントの開発をしつつ、インフラ全体のオーナーでもあります。 一方でメルコインでは、SREの基本的な役割は、メルカリ・メルペイと同じですが、インフラ全体のオーナーをSREが担っています。 Platformチームにはインフラコンポーネントの開発・運用を委託する形で承認をSREが行っています。こうすることで、メルコイン組織に所属する人がメルコインのシステムを管理する体制を実現しています。 メルコインでは、バックアップを含むお客さまデータやサーバーリソースを全て日本国内に置いています。 日本国内で取り扱うことで、日本の法令と規制の遵守が容易になります。また、お客さまデータの保護指針が明確になり、管理とセキュリティ対策が容易になります。 そのため、GCPのリージョンを東京と大阪に制限しています。ただ、GCPがグローバルでのみ提供している機能は、リージョンの指定はしていません。 Organization Security PolicyのresourceLocationsをGCP Organization全体にかけることでサービスが増え、新たにGCPプロジェクトを作成しても、初めから国外でのリソース作成ができないようになっています。 ただし、必要に応じて、プロジェクト単位で他のリージョンへのリソース作成を許可することも可能です。ポリシーの管理はSREが行っているため、例外を設定するには、システム上でSREの許可が必要です。 メルコインは、お客さまの安全と信頼を確保するために独自のインフラを構築しました。これはメルカリグループから分離されており、メルコインのチームがインフラの管理を行っています。システムは日本国内で運用されており、安全な取引環境を提供しています。さらに、開発者が特別な注意を払わなくても、システムの設計主体が安全性を確保するようになっています。 @yuhara:ここからは、メルコインのインフラの全体像と信頼性のあるサービスをリリースするための取り組みについてお話しします。 まずはメルコインのアーキテクチャについてです。全てのmicroservicesはGCPを利用しており、共通のGKEクラスターの中で動いています。 microservicesはレイヤーアーキテクチャとなっており、インターネットからのリクエストを受け付けるゲートウェイサービスと、認証をつかさどるAuth Tokenサービス、各バックエンドサービスの手前に置かれるBFFとしての役割を持つAPIサービスやビジネスロジックをつかさどる各種バックエンドサービスという形で、レイヤーを構成しています。 各microservicesのワークロードは共通のGKEで動いていますが、そのサービスが利用するデータベースなどは、microservicesごとに個別のプロジェクトにわかれており、サービスオーナーであるバックエンドエンジニアチームで管理しています。 microservicesはそれぞれのプロジェクトにわかれていますが、ネットワークの側面でいうと、Shared VPCの構成をとることで、VPCに所属するリソース、GKEやGCEなどのリソースは、プロジェクトがわかれていても、共通のVPCの中で通信することができます。 またShared VPCのホストプロジェクトが、ネットワークのハブとしての位置づけになるので、そのホストプロジェクトをネットワーク管理者が管理することで、例えばVPC Firewallで、Shared VPC内の通信を制御したり、Cloud NATによって外部向けの通信をコントロールしたり、あるいはVPC内のプライベートドメインをCloud DNSで管理することができるようになっています。 メルコインでは、Secure by Defaultのポリシーに沿って、VPC FirewallでDefault Deny構成としており、必要な通信を管理者が許可する運用を行っています。 あとメルコインではGKEクラスターは用途に応じていくつかのクラスターにわかれており、コンシューマー向けのサービスに関わるアプリケーション用のクラスターと、それ以外のクラスター、例えばGitHub Actionsのself-hosted runnerを自前で管理しているので、そのためのクラスターや、社内の運用ツール用のクラスターなど、クラスターが複数にわかれています。 クラスター間で通信が必要なケースでも、Shared VPCによって、VPC内で通信が収まります。 またメルコインでは、メルカリのOrganizationとは完全に分離された独立したOrganizationとVPCの構成になっていますが、メルコインからメルカリ側のサービスと連携するケースがあります。 例えば、メルカリのユーザーIDとメルコインのユーザーIDをマッピングするために、メルカリのユーザーIDをメルコインから取得するケースです。このようなケースでは、VPCがわかれているため、一般的にはインターネットにサービスエンドポイントを公開して、インターネット経由でアクセスするか、異なるVPCをVPCピアリングでネットワークを接続する方法などが考えられます。 いずれの方法にしても、ネットワークを繋げるための設計が煩雑なため、メルカリグループとしては、異なるカンパニー間のVPCを簡単に接続する仕組みとして、Private Service Connect(PSC)を採用しています。 Private Service Connectでは、対象となるサービスをService Attachmentを使って公開したいプロジェクト(今回の例では、メルカリ側から見たメルコインの対象プロジェクト)に絞って限定公開することで、指定したプロジェクトからのみの接続を許可し、セキュアにアクセスすることが可能になります。 VPCピアリングなどは不要で、簡単にメルカリ側のサービスとの連携を実現できます。 続いて、メルコインGKEクラスターに関わる設計の一部を紹介します。メルコインのGKEクラスターはプライベートクラスターとなっています。 プライベートクラスターは、外部IPアドレスを持たない、つまりVPC内の内部IPアドレスのみを持つNodeの構成となっています。またKubernetesのAPIサーバーは、VPCの内部IPアドレスで提供されるので、Nodeや同じVPC内にいるホストからは、このプライベートエンドポイントに対して、ネットワークに閉じた形で通信できます。 またメンテナンスやオペレーションのためにインターネット上からKubernetesのAPIサーバーにアクセスするケースでは、パブリック向けのエンドポイントを特定のIPアドレスに限定して許可する形で運用を行っています。 あとはNodeが外部IPアドレスを持たないため、外向けの通信はCloud NATを経由する形になっています。 その他のメルコインのGKEで使っている機能の一例として、一つ目に、Network Policyがあります。全てのmicroservicesが一つの共通クラスターの中で、マルチテナントになっているため、microservicesネームスペースへの通信を制御するために、Network Policyを有効にしていて、デフォルトでは全てをdenyする設定としています。必要なmicroservicesのみのアクセスを許可するために、Network Policyをアップデートしていくホワイトリスト方式の運用を行っています。 続いて、Cloud DNS for GKEです。Cloud DNSを有効にしています。DNSのスコープとしては、クラスタースコープとVPCスコープという二つのモードがありますが、メルコインではVPCスコープを使ってます。VPCスコープを使うと、GKE内部のDNS名がVPC全体に伝播するので、クラスターの外のホストから直接特定のKubernetesサービスの名前を引くことができ、Ingressを経由することなく、クラスターの外からmicroservicesにアクセスできます。これはあくまで前提として、VPC FirewallやNetwork Policyで通信が許可されている場合に限ります。 あとは、Google GroupをKubernetesのRoleBindingに指定することができる機能のGoogle Group for RBACも有効にしていて、ユーザー管理をGoogle Groupと連携させたり、Workload IdentityについてはKubernetesサービスアカウントをGCPのIAMサービスアカウントと連携さして、Keyless構成を実現させています。 Istioに関しては、GKEで用意されているアドオンを使うこともできますが、メルコインではアドオンを使わずに個別にセットアップしています。アドオンだと、Googleマネージド Istioが使えるものの、バージョンの指定や、使いたい機能や設定の調整などができないため、メルコインとして使いたいバージョンや機能を指定するために、ユーザーマネージド Istioで運用しています。 Istioの用途としては、主にCanary Releaseで1%トラフィックマイグレーションを行うことや、microservices間の通信をMTLSで暗号化することなどがあげられます。 次にメルコインのmicroservicesの開発・運用の全体像を見ていきます。先ほど、全てのmicroservicesは共通のGKEクラスターの中で動いていて、ネームスペースで区切られたマルチテナントになっており、GCPもプロジェクト単位でわかれているという話をしました。これらの開発・運用方法についても紹介したいと思います。 microservicesごとに開発チームが決められており、そのチームがオーナーシップを持って運用も行います。この例では、サービスAチームはKubernetesのネームスペースA上のmicroservicesと、それに関わるGCPプロジェクト内のSpannerや、Pub/Subといったリソースの管理です。 ただし、これらの構築や運用には多くの専門的な知識やリソースの管理が必要です。限られたメンバーとスケジュールの中で、1から全てをプロビジョニングするのは大変で、メルコインとして期待する設定が行われていないといった可能性も出てきます。 SREとして、チームの開発を促進し、かつメルコインで定めた設定をプロビジョニングできるように、抽象化したモジュールを提供しています。これらを使うことで、開発者は全ての設定を一つ一つ行う必要はなく、既に標準化されたものをプロビジョニングできます。 具体的には、SpannerやPub/SubといったGCPの各種リソースだけではなく、オンコールでインシデント管理を行うために、メルコインで利用しているPagerDuty、コード管理のためのGitHub、監視に関するDatadogや一部のKubernetesのリソースに関わる設定は、Terraformで定義し、Kubernetesのワークロードに関わるリソースはCUEを使って抽象化できるようになってるので、もう少し具体的に説明していきます。 Terraformで提供しているモジュールの例としては、ここにあるようにいくつかの用途に応じて数種類あります。 microservices-starter-kitは、開発者がmicroservicesを作る際に使うキットになっています。GCPプロジェクトやKubernetesネームスペースなどが作られ、必要なIAM設定など、microservicesを作るために必要な設定が含まれています。 microservices-teams-kitは、サービスチームに関わる設定を提供していて、チームのGoogle Groupのメンバー管理や、そのチームに付与されるIAM設定、オンコールに関わるPagerDutyの設定やGitHubで使われるGitHub Teamの管理などを、これで一元管理しています。 microservices-spanner-kitは、Spanner instanceやデータベースの設定に加えて、データベースのバックアップや、Spanner autoscaler(Spanner instanceの負荷に応じてインスタンスをスケールアウトできるオートスケーラーの仕組みを独自に導入している)それらに関わる必要な設定も含めて、このキットで対応できます。 microservices-slo-kitは、そのmicroservicesのサービスレベルやSLOに応じて、Datadogの監視などの設定を行うことができるモジュールで、一つ一つ監視モニターを作らなくても良い形になっています。 Kubernetesのリソースも同様に、開発者が多くのYAMLを管理する必要があり煩雑になるため、それらを簡易化し、開発者の認知負荷を低減するために、CUEというオープンソースの言語を使って抽象化を行っています。これらによって、YAMLに比べて大幅にコードが削減されるとともに、Istioのような新しく取り入れる技術についても、開発者の負荷を軽減でき、かつメルコインとして、セキュリティや可用性の面でコントロールが利いた状態でワークロードが生成できる状態になっています。 ちなみにCUE自体はまだそれほどメジャーな言語ではないので、気になる方は こちらのブログ を参照してください。 ここまで、抽象化によっていかに開発者が簡単にmicroservicesの開発・運用を行えるかというお話をしてきました。一方であまり過度に抽象化していくと、例えば他と少し異なる設定を行いたいときに対応できず使い勝手が悪かったり、またそれらを対応するために共通化しているモジュール本体を修正する必要が出て、逆にコストが高くなる側面もあります。 そのため、メルコインだけでなくて、メルカリグループも含めて、キットを提供して抽象化しつつも、直接開発者がTerraformを記述できる自由度を持たせた形で、microservicesの開発運用ができる状態になっています。 そうすると、標準化されていないリソースなども本番環境にプロビジョニングされる可能性があるので、メルコインとしてのセキュリティや可用性などの観点から、推奨する設定、あるいはやってはいけない設定といったメルコインのポリシーを守るために、CI/CDパイプライン上で、TerraformやKubernetesのコードの検証をConftestを使って行っています。 一例としては、Shared VPCに接続するためのTerraformモジュールがあります。許可されたサービスのみが接続できるように制限したいので、事前に許可されているかをチェックしたり、TerraformでVPC Firewallを設定する際に、監査などの観点からログを出力することを推奨しているため、そのチェックを行ったり、Kubernetes マニュフェストでも、コンテナが特権モードになっていたり、ホストネットワークを使用していないかなどを検証したりしています。 実際に運用を始めると、障害対応などで緊急のオペレーションが必要なケースも出てきます。対応方法として、インフラなどの構成を変更するために行動を修正してCI/CDを通すやり方もありますが、時間がかかりすぎて復旧までに時間を要してしまいます。 またはIAMの権限を取得するのも同様に、Terraformのコードから、CI/CDを通すと、権限が付与されるまでに待たないといけないため時間がかかってしまいます。このCarrierというツールは、有効期限付きの一時的な権限を、承認をもって取得できるシステムです。 基本的にはSREや開発者は本番環境への一切の変更権限を持っておらず、必要なときにのみCarrierを使って権限申請し、SREが承認した上で、権限取得する運用を行っています。これによって、申請したときの有効期限が切れた後は、自動的に権限も取り消されるので、権限の消し忘れなどもなく、統制が取られた状態で安全に運用できます。 メルコインは、セキュリティやコンプライアンスなどの側面から、メルカリとは完全に独立したGCP Organizationとして分離されています。メルコインのmicroservicesは、共通のGKEクラスターでマルチテナントを構成しており、セキュリティなどの観点でNetwork Policyなどを使って完全に他のテナントと分離した構成です。 開発者がmicroservicesのオーナーシップを持っており、SREからインフラを抽象化したツールなどを提供することでサービスの開発と運用を促進してきました。一方で課題感としては、抽象化しているツールが増えてきたことで、学習コストや開発者の認知負荷が高くなってきてるというのがあって、それらを開発解決するために、よりシンプルなインターフェイスのようなものが必要になっています。 今後、そういった課題に対しても、より良いものを取り入れて改善していけるといいなと考えております。 本日はご清聴いただきありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】How to Unleash Fintech – Shunya Kimura / Keigo Watanabe / Noriaki Utsunomiya 【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 How to Unleash Fintech 」の書き起こしです。あわせて、「 【書き起こし】Keynote – Shunya Kimura【Merpay & Mercoin Tech Fest 2023】 」をご一読ください。 @kimuras:「How to Unleash Fintech」というタイトルで、パネルディスカッションを進めます。 @keigow:メルペイVP of Engineeringの@keigowと申します。私は、2016年にメルカリグループに入った後に、2018年のメルペイ立ち上げのタイミングから3年、メルペイに所属してました。2年ほどグループ会社のソウゾウという会社で新規事業の立ち上げに取り組んでいたんですけれども、この4月にメルペイに戻りました。本日は過去からのメルペイの取り組みについても触れられればと思っていて、とても楽しみです。よろしくお願いします。 @nu2:同じくVP of Engineeringの@nu2と申します。今年の5月に入社して、ちょうどオンボーディング期間を終えたばかりです。フレッシュな視点を意識して今回お話できればと思っています。 @kimuras:まず導入ですが、2019年からメルペイのFintechサービスがリリースされて、スマート払いやスマートマネー、クレジットカードサービス、ビットコインなど土台を作ることができました。利用者は約1500万人です。 特にこの1年では、メルカードやビットコインなど、大きなリリースもありました。今回はそのFintech事業にとっても、大きな技術的な成長を報告できるので、ぜひ皆さんに楽しんでいただきたいですし、参考にしていただければなと思っています。 今回は、これまで作ってきたFintechの土台を活かして、今後さらにこの価値の他のサービスも広げていきたいという気持ちでセッションを開催しています。 Fintechサービスの成長に欠かせないのは、攻めだけでなく守りの姿勢を大切にすること。便利なUIにするほどセキュリティのリスクが高まってしまうので、同時に守りも重視しなければいけません。 メルペイ創立から担当されている@keigowさんにお聞きしたいんですけども、これはFoundationプラットフォーム開発に重点を置いてきたというお話をしましたが、@keigowさんとしてはどのような考えがあったのかを聞きたいです。 @keigow:当初から完璧にできていたわけではなく、できていた部分と今でも苦労している部分があるのかなと思っております。組織の良い部分は、マイクロサービスアーキテクチャで開発を進めたこと。また、決済のコアとなるマイクロサービスを独立したチームで開発を進めることは、立ち上げ当初から意識していました。 メルペイ立ち上げから5年間、エンジニアリング組織には大小様々な変化はありましたが、その点の根本の部分は変わっていないと思います。 現状のメルペイのエンジニアリング組織は、主にProduct、Foundation、Enablingという三つの領域にわかれています。Productエンジニアリングは、新しいProductの機能開発や改善、お客さま体験の向上に直接つながる開発を行います。 続いて、先ほどプラットフォームとして表現されていたFoundation。Fintech領域で特に大事な部分、決済や残高の管理、与信の管理のマイクロサービスというところは、基本的に1ヶ所に閉じて、専任のチームをアサインして、その中で中長期を意識した開発を進めていくということは、創業当初から続けています。 最後に、Enablingチーム。これには、バックエンドやクライアントのアーキテクト、SRE、データプラットフォームの方が所属しています。横断的な技術課題の解決、生産性の向上を担っています。 こうして組織ごとに役割をフォーカスすることで、「攻め」と「守り」を意識できました。 @kimuras:初期の段階から長期的な視点も考えてきたということですね。なるべく改善しながら進めてきた、あるいは組織をそのような形にしてきたということで、うまくできた点かなと思います。@nu2さんの入社したばかりのフレッシュな視点では、どのように見えますか? @nu2:メルカリはメルペイが誕生する前から、今までずっと成長曲線を描いてきたのは、主にお客さまとお客さまが出品される品物のエンゲージメントの点と、売上金の換金という二つのプラットフォームが、Productマーケットにフィットした結果だと思います。 関係企業がグループのFintech領域を担うメルペイになり、これまで今まであまり世の中になかった決済体験みたいなのにつながって、それを提供しつつメルコインも事業を開始して、まさに価値の循環を体現していると感じていました。 機能としてはiDの決済から始り、QRコードやメルカード、即時決済、さらに清算することですぐに与信枠が回復する技術をこのタイムスパンで成し遂げてきたことは、とてつもない開発スピードだと感じました。 同時にお客さまの利用が増えていくことで、トランザクションが増量し、それに伴ってシステムのスケーラビリティがどう担保されているのかは、入社前から興味関心がありました。 @kimuras:実際に入社してみて、いかがですか? @nu2:何年も先まで見据えたアーキテクチャで、現状スケーラビリティを担保されている部分もあれば、クラウド技術に依存しているので、その辺は今後ずっと拡張していくと、コストやレスポンスに支障が出るのかもしれないということは、現場の方たちとお話しているので、そこを知恵を出し合いながら改善を重ねていきたいと思っています。 @kimuras:続いて、Fintech領域のエンジニアリング領域の面白さについてです。堅牢なシステムを作り、セキュリティを守らなければならない上でも、なめらかな社会を実現していくことは、難しくもありとても面白いことだと思います。 おふたりの、仕事のやりがいやエンジニアリングの面白さについても、ぜひ教えてください。 @keigow:一番は、お客さまに新しいサービスを提供できることです。 メルペイ自体はユニークなサービスなのかなと思っています。メルカリやメルカリShopsといった、マーケットプレイスのサービスと一体となって提供され、メルカリグループの新しいミッションが「あらゆる価値を循環させ、あらゆる人の可能性を広げる」というところで、物を売ることで得たお金を支払いに使える、そのお金を利用してビットコインを買えるといったサービスは、これまでの世の中にないものだと思っています。そのような、新しいものを提供することにワクワクしています。 @nu2:私もこれまでのキャリア的にBtoC次にBtoBtoCを経験して、今回はCtoCに携わっています。お客さまと直接向き合う点が大きいと思っています。 社会の一部をソフトウェアとして実装していく点が大きいですね。私自身、メルカリグループのミッションに非常に共感したことが入社の動機になりました。どのような行動を起こせば、なめらかなアクションをとったり、組織に対してフィクションを起こさずに済むかを常に意識しています。 また、我々のサービスは、これからもお客さまに使っていただきたいです。ビッグスケールするときに、想定しなかった技術的な課題が絶対出てくると思っています。国内外を視野に入れたビックスケールサービスを実現することに対して、非常にやりがいを感じています。 @kimuras:ありがとうございます。続いて、今回のMerpay & Mercoin Tech Fest 2023のセッションや見どころを説明してください。 @keigow:「Merpay Engineering Career Talk」というパネルディスカッションでエンジニアリングマネージャーとEngineering Headの3人で、キャリアについて話す予定です。 【書き起こし】Merpay Engineering Career Talk – Keigo Watanabe / Osamu Tonomori / Katsuhiro Ogawa【Merpay & Mercoin Tech Fest 2023】 @nu2:「Merpay & MercoinにおけるLLM活用の取り組み」と題し、発表します。私も入社後すぐに支援する形で参加したLLM技術を用いた社内ハッカソンのような取り組みがありまして、そちらで最も評価されたProductのプレゼンテーションも披露します。 今後生成AIの技術は誰もが注目している技術だと思っていますので、どのような議論が展開されるのか私も非常に楽しみです。 【書き起こし】Merpay & MercoinにおけるLLM活用の取り組み – Yuki Ishikawa / Daisuke Torigoe / Noriaki Utsunomiya / hmj【Merpay & Mercoin Tech Fest 2023】 @kimuras:続いて、見どころセッションについてはいかがでしょうか。 @keigow:一つは、「Merpay iOSのGroundUp Appへの移行」。iOSリアーキテクチャのお話しで、かなり大規模なプロジェクトなので、面白い話が聞けると思います。 もう一つは、「メルコイン決済基盤の実践話」。もともとメルペイの経験も踏まえて、メルコインの決済基盤がどのように作られているのかを詳細に話してくれると聞いているので、楽しみです。 【書き起こし】Merpay iOSのGroundUP Appへの移行 – kenmaz【Merpay & Mercoin Tech Fest 2023】 【書き起こし】メルコイン決済基盤の実践話 – Junwei Liang【Merpay & Mercoin Tech Fest 2023】 @nu2:私は「メルペイのあと払いとスマートマネーを支える返済基盤マイクロサービスの進化」と「メルコイン決済マイクロサービスのトランザクション管理を支える技術」の2つです。どちらもマイクロサービスについてのセッションです。 なぜこの2つに注目しているかといいますと、私が入社の決め手の一つでもあるのですが、金融の取引領域にマイクロサービスアーキテクチャを採用してるのもすごくチャレンジングなことだと思っています。 なぜかというと、Network latencyなどの課題をどうクリアするかが大きいポイントだなと思っていまして、成し遂げたい世界観を構築するための技術的な挑戦を他のセッションでもあるんですけれども、マイクロサービスにフォーカスしてこの二つを取り上げました。 【書き起こし】メルペイのあと払いとスマートマネーを支える返済基盤マイクロサービスの進化 – Cui Peichong【Merpay & Mercoin Tech Fest 2023】 【書き起こし】メルコイン決済マイクロサービスのトランザクション管理を支える技術 – Shota Suzuki【Merpay & Mercoin Tech Fest 2023】 @kimuras:個人的には、メルコインが社内でも最新のアーキテクチャを使っているということもあって、僕も楽しいと思ってますし、今回紹介できることをとても嬉しく思っております。 @kimiuras:続いて、メルペイ・メルコインの領域あるいはメルカリでもいいんですけども、どんな世界を実現していきたいか、あるいは今後どんなチャレンジをしたら面白いかなどについて、意見をお聞きできたらなと思います。 世の中を便利にするための土台はできてきましたが、これらをいろんなサービスで今後活用していくことによって、より可能性が広がっていくという考え方もありますし、世界に挑戦することも面白いかなと思います。 @keigow:Product的に今のメルペイをものすごく単純化すると、財布にお金が入ってきて、出ていく。加えてビットコインを購入し、資産運用の要素が組み合わさっていると思います。 直近の出金や決済は、iD決済から始まり、コード決済、メルカードなど、かなり整ってきたと感じています。一方で入金や運用についてはもっといろいろな可能性があると思います。物の売買だけでない入金の手段や、より手軽な資産運用も含めて、増やせる財布というか、そこにお金を入れておくことで価値が出てくるという世界観を、メルペイで実現できると面白いと思います。 エンジニアリングという観点では、高い可用性やセキュリティが求められる中で、いかに高いスピード感を持って開発していくかが非常に重要だと思います。守りはするけれど、保守的にはならない、「守りのために攻める」ということを意識したいです。 @kimuras:「保守的にはならない」ということについて、特に気をつけていかないといけないという危機感を覚えることはありますか? @keigow:守りに入ること自体は簡単ではあって、現状維持、あるいはより枯れた技術を利用すること自体は別に間違ってないんですけれども、リスクに見合ったリターンがある技術は当然あると思うので、そこは意識してアンテナを張りたいです。 リスクだけがあるのは全然良くないんですけれども、新しいことを取り入れることは意識していくことが必要な部分かなと思ってます。 @kimuras:新しいところでいうと、マネージドサービスやOSSなどを意識されていますか? @keigow:それもそうですし、LLMをどう取り入れるかは、サービスの提供という観点では面白い部分かなと思います。かなり応用の幅がありそうです。 @nu2:私はメルカリグループが掲げる価値の循環というミッションを実現するため、さまざまな価値を循環させるための基盤・経済圏にお客さまが参加したいと思える状態を作っていかなきゃいけないと思っています。 先ほどお話にあった即時決済や即時回復は今まで社会になかったものでした。我々はそれを利用していますので、どれだけ便利なものなのかを体現できると思います。まだまだお客さまに届いていないとも思うので、便利な世の中を実現して、メルカリグループの経済圏にもっと多くのお客さまに参加して欲しいです。 お客さまが増えることで、セキュリティやアベイラビリティ、レスポンシビリティに非常に高いハードルが生まれると思いますが、対応していきたいです。 @kimuras:「保守的になりすぎてはいけない」というお話がありましたが、そうならないために挑戦していきたいことや考え方はありますでしょうか? @nu2:今のクラウド技術を元にしてサービスを展開していますが、クラウド技術提供者が用意するミドルウェアを待つのではなくて、我々が新しいソフトウェア自身をミドルウェアとして構築・開発し、我々がオープンソースとして逆に提供するぐらいの勢いが必要かなと思っています。 @kimuras:「増やせる財布」「資産管理」という観点で実現してみたいビジョンはありますか? @nu2:財布の中で何を使うかというお客さま自身の情報を預からせていただくので、そこから今すでに実現している信用情報以外のことにも利用できるのではないかと思います。 ただ、あくまでお客さまの価値の循環のために利用することがデータとしてすごく重要だと思っています。 @kimuras:データの種類や量は本当に増えてきていて、データ管理のアーキテクチャも常に見直していますが、今後はデータの活用をさらに進化させていかないといけないフェーズになったと感じています。 資産管理やロイヤルティプログラムなど、今後データサイエンスも伴うようなデータ利活用が、メルペイ・メルコインの成長の一つの軸なんじゃないかなと僕も思っています。 最後に、現状の課題とチャレンジということで、やりたいこと挑戦したいこと、改善したいことがあれば、ひとこといただきたいです。 @keigow:足元の課題はたくさんあるかなと思ってまして、VPとして一番責任あるところで言うと、技術的な改善やリファクタリングをProductの優先順位として高めて推進する体制を作ることは強く意識しています。 以前よりは、議論を進めながら、ロードマップにエンジニアリングの部分を載せていくことができるようになってきているので、ここの部分は引き続き強化していきたいです。 @nu2:我々はFintechサービスをお客さまに提供する際に「安心・安全」というのを掲げているんですけれども、我々が掲げる以上、我々のシステムとしても安心・安全が求められます。 ただそれに対して一定のコストがかかるので、コストとのバランスを見ながら、いかに最適なコストで安心・安全を提供するかは課題だと思います。 @kimuras:ありがとうございます。以上でこのセッションを終わりにします。ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルペイのあと払いとスマートマネーを支える返済基盤マイクロサービスの進化 – Cui Peichong【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルペイのあと払いとスマートマネーを支える返済基盤マイクロサービスの進化 」の書き起こしです。 @pedro:私からは、「メルペイのあと払いとスマートマネーを支える返済基盤マイクロサービスの進化」について紹介します。 まず、軽く自己紹介します。Cui Peichongと申します。社内ではSlackネームの@pedroと呼ばれています。2019年4月に、バックエンドエンジニアとしてメルペイに入社しました。現在はCredit Designチームに所属し、メルペイのあと払いやメルペイスマートマネーの請求・精算に関わるマイクロサービスの開発に携わっています。 本セッションのアジェンダはこの通りです。まず、返済基盤の現状のマイクロサービス構成について紹介します。そして、返済基盤の機能を提供するinvoiceマイクロサービスを導入した経緯を説明し、導入に伴って生じた技術負債の話もします。最後に、負債の解消となるinvoiceマイクロサービスの独立化について紹介します。 それでは、返済基盤の現状を説明します。今、お客さまに返済機能を提供しているサービスは二つあります。一つ目は、メルペイのあと払いです。 メルペイのあと払いは、メルカリでのお買い物やメルペイが使えるお店・Webサービスでの月々のお買い物の代金を翌月に支払えるサービスです。このサービスは、三つの返済方法を提供しています。一つ目は、自動引落し。接続した銀行から自動で引き落とすことで支払う方法です。それ以外に、メルペイの残高と、コンビニATMの支払い方法があります。 もう一つ、返済機能を提供しているサービスは、メルペイスマートマネーです。メルペイスマートマネーは、メルカリアプリでお金を借りられるサービスです。 メルペイスマートマネーの毎月の返済は、接続した銀行口座からの「自動引落し」と、「残高でいつでも返済」の二つの手段があります。 この二つのサービスの構成は、このようになっています。lendingマイクロサービスはスマートマネーの利用、請求額の算出、契約管理などの機能を提供しています。 deferred-payマイクロサービスは、あと払いの利用、請求金額の算出、定額払いの契約管理などの機能を提供しています。 スマートマネーとあと払いが提供する返済機能には共通部分が多いので、両方のサービスに対応できる返済機能を、invoiceマイクロサービスが実現します。 これらの返済機能を実現するために、invoiceマイクロサービスがメルペイのCommon Foundationとなるいくつかのマイクロサービスとやり取りをしています。 主に銀行接続とチャージを管理するbankマイクロサービスでチャージして、決済処理の全般を管理するpaymentマイクロサービスを通して、スマートマネーやあと払いの債権を管理するdebtマイクロサービスに債権の返済をリクエストします。 以上が、現状のマイクロサービスの構成です。実は、初期にはinvoiceマイクロサービスが存在しませんでした。ここでは、invoiceマイクロサービスを導入した経緯を説明します。 メルペイスマートマネーは、あと払いより後にリリースされたサービスです。そのため、リリースの前に返済機能を提供する必要があるのは、あと払いだけでした。 そして、返済機能専用のマイクロサービスを作る必要もなく、deferred-payマイクロサービスが返済機能を含めて、あと払いに関連する全ての機能を提供していました。もちろん、返済の機能を実現するためにdeferred-payもCommon Foundationとなるマイクロサービスも直接やり取りしていました。 この状態で、メルペイスマートマネーの開発プロジェクトが開始され、その中でいくつかのrequirementsが出てきました。まず、基本的なrequirementsは、メルカリアプリでお金を借りることができ、かつ返済できるサービスでしたが、返済機能に関していくつかの課題がありました。 まず、あと払いの自動引落しと同じ日に実行した場合は、銀行へのAPIキャパシティの制御を考慮しなければなりません。できれば、まとめて銀行へのチャージをリクエストしたいです。 そして、請求書延滞後にメルペイ残高や売上金から自動で充当したいときに、あと払いの請求書との優先順位を制御しないといけません。 このようなrequirementsのもとに、いくつかのマイクロサービスの構成案を検討しました。一つ目の案は、lendingマイクロサービスを作り、スマートマネーの利用・請求・返済の全ての機能を実装するものでした。 この案のメリットは、lendingマイクロサービスが独立しているため、独立して全ての機能の設計・開発ができます。一方で、デメリットもいくつかあります。まず、lendingマイクロサービスとdeferred-payマイクロサービスが離れていることで、それぞれ返済の機能を提供しますが、銀行へのAPIのキャパシティ制御が困難になります。また、あと払いの請求書とスマートマネーの請求書の中と順位の制御も難しくなります。 あと払いの返済機能が既に存在しているのに、lendingマイクロサービスに似た実装を行うことにもなります。 二つ目の案は、独立した返済のマイクロサービスを作ることです。lendingサービスはスマートマネーの利用・請求や契約管理などの機能だけを提供し、invoiceマイクロサービスという独立の返済用マイクロサービスを作り、最初はスマートマネーの返済を管理しますが、将来的にあと払いの返済も実装するというものです。 この案は、一番理想に近い形ですが、デメリットもあります。あと払いの返済機能のマイグレーションを実現する前は、一つ目の案と同じように、銀行へのAPIキャパシティ制御も難しいです。 invoiceマイクロサービスに返済機能を実装するため、deferred-payマイクロサービスと重複しそうです。また、将来あと払い返済機能のマイグレーションを考慮しなければなりません。 三つ目の案は、あと払いの返済機能を利用するというものです。 lendingマイクロサービスがスマートマネーの利用・請求と、契約管理の機能だけを提供し、deferred-payマイクロサービスがこれまでの責務以外にスマートマネーの返済も対応します。具体的には、deferred-payマイクロサービスの返済機能を拡張して、invoiceマイクロサービスとして、あと払いとスマートマネー両方の返済に対応します。 この案のメリットは、返済機能を一本化でき、一つ目・二つ目の案のような銀行へのAPIキャパシティや充当順位の制御に関する問題がなくなります。あと払いの既存の返済機能を拡張するため、重複の実装も少なくなります。 しかし、ご覧のように、マイクロサービスの責務と実際の構成の乖離があります。もともとdeferred-payマイクロサービスはあと払いの機能だけを提供すべきでしたが、スマートマネーの返済も対応することで、複雑になります。 最終的に、リリースのスケジュールと実現の難易度などを考慮し、初期リリース時に一時的な技術負債を覚悟した上で、案3で実装し、その後deferred-payマイクロサービスにあるinvoiceマイクロサービスを独立させる案に決定しました。 この案を実現するために、deferred-payマイクロサービスにある返済関連のデータモデルの整理・拡張が必要です。 ここで請求書のデータモデルを例に説明します。まず、あと払いドメイン専用の項目と、invoiceマイクロサービスが扱う抽象化した請求書の項目を見分ける必要があります。 例えば、smartpay_contract_idは、あと払いドメイン専用の項目です。amountやpaid_amount、invoice_monthなどの項目は、invoiceマイクロサービスとして抽象化した請求書の項目です。 それだけではなく、スマートマネーに対応するために、いくつかの項目を追加する必要があります。例えば、どのサービスの請求書なのかを判別できるように、サービスIDを追加しました。 既存の返済ロジックも、スマートマネーに対応できるように拡張しました。 そして、今後invoiceマイクロサービスの独立化を意識して、既存のインターフェースと分けて新規のinvoice gRPCサービスを作成しました。この案によって、メルペイスマートマネーを無事リリースできました。 ある程度、技術負債を覚悟しましたが、実際に運用のフェーズに入ったら、さらに実感できるようになりました。 まず、コードベースが混在することで、さまざまな影響が出ます。例えば、あと払いサービス機能を開発するときに、invoiceマイクロサービスへの影響を意識しなければなりません。反対に、新たな返済機能を開発するときに、あと払いサービスへの影響も意識する必要があります。 また、データベースが一つになることによる影響もあります。あと払いサービスの運用中にインシデントが発生したときに、データを調査する必要があります。その際、スマートマネーのデータを除外しなければならず、メンテナンスコストが上がります。 あと払いサービスの運用だけではなく、データ分析の複雑さもあります。この技術負債を解決するために、invoiceマイクロサービスの独立化のプロジェクトが開始されました。 まず、独立したinvoiceマイクロサービスを作ります。このマイクロサービスのデータモデルは、deferred-payマイクロサービスにある返済関連のデータモデルから、抽象化したものです。そして、deferred-payマイクロサービスにある、invoice gRPCサービスと全く同じインターフェースのgRPCサービスを提供します。 既存と同じインターフェースを提供することで、Customer単位で簡単にマイグレーションできました。 具体的には、Customerごとにマイグレーションの状態を管理して、マイグレーション済みの場合に、deferred-payマイクロサービスにあるinvoice gRPCへのリクエストを処理せずに、そのままinvoiceマイクロサービスへProxyします。この形にして、clientとしてのlendingマイクロサービス側は、修正しなくてもマイグレーションできるようになりました。 マイグレーションのバッチは、このような形になっています。deferred-payマイクロサービスにあるマイグレーションのバッチがCustomer単位の返済関連データを抽出し、invoiceマイクロサービスにあるマイグレーション専用のgRPCエンドポイントをリクエストし、データをinvoiceマイクロサービスのデータベースに保存します。 実際のマイグレーションの進捗は、この通りです。特に初期段階はかなり慎重にマイグレーションを実行しました。 メルペイあと払いは、割と長い歴史があるサービスなので、想定外のデータもあります。マイグレーションの比率の拡大とともに、イレギュラーなデータを検知し、改修することを繰り返しました。そして、一定期間の安定運用が確認でき次第、マイグレーションのペースを上げ、完了しました。 全てのCustomerのマイグレーションを完了した後に、clientであるlendingマイクロサービスと、deferred-payマイクロサービスの向き先を新しいinvoiceマイクロサービスへ変更できるようになります。 最後のまとめです。 マイクロサービスの開発においては、最初に理想的なアーキテクチャを作るのは難しい場合があります。その際に、技術負債を意識したマイクロサービス構成の意思決定ができ、技術負債の解消計画を立てた上で、理想のアーキテクチャを求めることがいいアプローチだと思います。 マイグレーションに関しては、段階的に実行することで安全に終えることができました。今回はマイクロサービス開発の一つの事例として、invoiceマイクロサービスの導入と独立のお話をしました。参考になれば幸いです。 以上で、本日のセッションを終わりにします。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】メルカリへのFIDO導入の経緯とこれからの展望、課題から得た学び – koi / kokukuma / daichiro / hidey【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルカリへのFIDO導入の経緯とこれからの展望、課題から得た学び 」の書き起こしです。 @koi:みなさんこんにちは。「メルカリへのFIDO導入の経緯とこれからの展望、課題から得た学び」を始めます。 このセッションではFIDOの概要をある程度ご存知で、これから導入しようとしている方、実際に導入を進めようとしている方に向けて、メルカリで直面した課題や面白さをディスカッション形式でお届けします。 @daichiro:私はメルコインiOSチームの@daichiroと申します。2019年にメルペイに入社して、2021年からメルコインで業務を担当しています。メルペイ時代にdアカウント連携などの機能を実装し、その後iOSの認証認可を担当し始めました。メルコインでは、主に口座開設周りを担当しています。今日はよろしくお願いします。 @hidey:メルペイAndroidチームの@hideyです。2018年にメルペイに入社し、メルペイをリリース後しばらくはメルペイの支払いタブの実装などを担当していました。最近はメルペイAndroid全体の技術的負債の解消などを行っています。FIDOの開発では、主にAndroid側の実装を担当しました。今日はよろしくお願いします。 @kokukuma:@kokukumaです。僕はメルカリの認証認可に関連するIDPチームに所属しています。FIDOについては、メルカリの中にどう適用していくかを考える全体設計に関わっています。 @koi:私はメルカリでIDPチームのプロダクトマネージャーとして働いています。FIDOの実装時期から現在も引き続きFIDOに関わる仕事を中心としています。本日はモデレーターとして本セッションを担当します。 このセッションでは、冒頭10分ほどは私から説明パートとしてメルカリのFIDO・パスキー導入のステータスや今後の展望について紹介し、後半の20分をディスカッションパートとして、登壇しているエンジニアのみなさんと、テーマに沿った議論をします。 さっそく、説明パートに入っていきます。ではメルカリのFIDO/パスキーについての、現在のステータスです。 そもそもメルカリがFIDOのサポートをするモチベーションとなったのは、新サービス・メルコインの立ち上げが大きなきっかけでした。 暗号資産交換業を開始するメルコインでは、高いセキュリティ要件を満たす必要がありました。そのためまずは、メルカリアカウントにログインした状態を前提に、メルコインサービスを使うための認証としてFIDO認証を提供しました。 現在はメルコインだけではなく、SMS認証を利用している機能にもFIDO導入を進めており、現時点では電話番号の変更、メール・パスワードの変更、あんしん支払い設定においてFIDOの登録を行っているユーザーが、FIDO認証を利用可能という状況になっています。 メルカリがFIDOをサポートしている環境については、こちらでまとめています。アプリを先行してサポートしており、Webについては現在対応中です。いわゆるSynced passkeyをサポートしているバージョンはiOS16〜/Android 9〜で、メルカリのアプリのサポートバージョンと差があるといった点は、ディスカッションポイントとして後半に持っていきたいと思います。 リリース後の実績にも触れたいと思います。現在、FIDOCredentialの登録者は104万人となっています。その中で認証成功率、成功するまでの所要時間をSMS OTPと比較した表がこちらです。 認証成功率はSMS OTPと比べて14%ほど高く、所要時間は4分の1程度。SMS OTPと比較するとFIDOでの認証はお客さまにとって良い体験を提供できていることがわかります。 また、ディスカッションに入っていく前に、メルカリでお客さまとのコミュニケーションを行う上で、便宜上定義している言葉をこちらにまとめてみました。FIDO Credentialの設定ページとして「生体認証画面」、FIDO CredentialをそれぞれDevice-bound passkeyを「生体認証」、Synced passkeyを「パスキー」と表現しています。 @kokukuma:補足ですが、今のメルカリはかなりニッチな状況です。現状の一般的なパスキーの導入としては、「Webのログインに対して、あくまでオプショナルな機能として導入する」だと思います。WebアプリケーションならWebで開くし、ネイティブアプリケーションでもログインはin-appブラウザが開くので基本的に認証機へのアクセス方法はWebAuthn APIを使う、ログインに使うものなのでパスキーが使えなかったときの認証方法としてパスワードや他の認証方法は残す、と言ったような感じです。 ただメルカリの場合、メルコインというサービスにおけるビジネス的要求を満たすためにFIDOを導入しています。メルコイン自体は同じメルカリアプリの中にあり、メルカリのアカウントでログインした後に使えるので、FIDOの適用箇所はログインではなくて再認証やステップアップ認証です。 メルコイン自体はWebでなくアプリで提供されるものです。かつ、メルコインを使うにあたって認証するためにブラウザを立ち上げるようなUXの悪い仕様にはしたくないという話もあったので、WebAuthn APIではなく、NativeAPIを使います。 また、メルコインにおいては、フィッシング被害をできる限り軽減したいという考えから、パスワードやSNS OTPではメルコインを使わせない方向性です。そのため、メルコインのビジネス要件を満たすために、今のこのメルカリの状況があるので、一般的なパスキーの導入状況とは異なります。 ちなみに一般的な状況で言うと、Web+DBのパスキーの特集がすごくよくまとまっているので、参考になると思います。 参考記事 https://www.w3.org/TR/webauthn-2/ https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication/supporting_passkeys/ https://developers.google.com/identity/fido/android/native-apps?hl=ja @koi:前提を踏まえて、今後の展望としては、利用箇所の面では他にも存在しているSMS認証の実施箇所で、FIDOを利用できること。また並行して、お客さまにFIDOを利用していただくため、登録率・利用率の拡大を実施していく予定です。 また、セキュリティを担保することを前提に、利便性の良い認証方法を提供し、安心安全にサービスを利用できる世界を実現したいと思います。 説明パートは以上です。では早速、本編のディスカッションパートに入っていきます。 @koi:トピックはこちらです。「実装で困ったところ」「分かっていれば避けられたのに話」「技術的に面白かった話」を1個ずつ話していきたいと思います。 こちらの図に沿って進めていきます。 最初のトピックは、実装で困ったところです。最初にiOSを担当した@daichiroさんに話を聞いてみたいと思います。メルコインはメルカリアプリのサポートバージョンと同じというところで、冒頭iOS14からギャップがあるというお話をしました。その点についてどのような苦労がありましたでしょうか? @daichiro:トピックは、大きく分けて二つあります。一つ目は認証の実装が大変でした。「Authenticator」のところでは、端末が秘密鍵を作って署名をしています。 iOS SDKが提供しているFIDOの認証器がiOS16以降でしか使えない中、iOS14をサポートしなければいけない状況でした。そこで、フルスクラッチで実装をし、iOS14・15の端末については自作の認証器で認証しました。W3Cが仕様を出しているのですが、仕様書とにらめっこしながら、バイナリデータをやり取りするという慣れないことに取り組みました。 二つ目は、マイグレーションです。iOS14・15で自作の認証器を使っていたお客さまが、機種変更やアップデートをしてiOS16になると、Appleが提供するFIDOの認証器を使うようにしないといけないのですが、そこの場合分けや、自作のものとAppleが提供したもののインターフェースが違うと作業が多くなりそうでした。 インターフェースについてはW3Cの仕様に沿っていたので、そこまで苦労することはありませんでしたが、マイグレーションをする必要のあるパターンが多く、そこも大変でした。 @koi: Androidはいかがでしょうか? @hidey:AndroidはiOSと違って認証系の実装の部分は、公式のライブラリでアクセスするものがGoogleから提供されているので、その部分の苦労はありませんでした。一方、ライブラリでラップされているエラーのハンドリングは、少し大変でした。 ひとつハマったのが、Googleの開発者サービス経由で認証器(Authenticator)にアクセスする際、そのバージョンに依存して発生したエラーです。これはリリース前まで見つけられなかったので、本番障害が出てしまいました。 @koi:続いて、サーバーサイド側での苦労というのもあれば聞いてみたいなと思います。 @kokukuma:実装ではそんなに苦労したわけではありませんでした。ただ、設計かつ現在進行系で困っているのは、メルコインのためにFIDOを導入しフィッシング耐性を強化したことで、いろいろな弊害が出ていることです。 フィッシング耐性のために二つ目の鍵の登録もパスキーで守る仕様にしたため、UXに支障が出ています。例えば、パスキーが使えずメルコインが使えない、二つ目の鍵を登録できないという問い合わせが発生しています。その辺りは困っていますね。 一方で、メルコインにおいてパスキーの利用を強制したこと自体は、我々がそんなに訴求しなくてもメルコインの訴求につられて鍵の登録数が上がるという副次的なメリットがあったので良かったと思います。 @koi:次のトピック「分かっていれば避けられた話」に移ります。@daichiroさん、いかがですか? @daichiro:自作認証器は本当に大変なので、止めた方がいいと思います。(笑) もちろんリリースする前にQAやデバッグはめちゃくちゃしましたが、それでもリリースするときに不安になって精神的に良くなかったですね。ただ、サービスをどうお客さまに提供するかは大事なので、今からやるなら自作認証器はなるべく使わずに、iOS16以降で対応することができたと思います。 もう一つは組織的な話になります。メルカリ・メルペイ・メルコインそれぞれのカンパニー間のコミュニケーションで苦労したことがありました。僕があまり英語に慣れてないこともあり、伝えたいことが伝わらずに、時間を無駄にしたという反省があるので、あまり普段一緒に仕事しないメンバーと仕事をするときはもっと丁寧にコミュニケーションをした方がよかったと思います。 @hidey:コミュニケーションに関しては、もっと丁寧にやればよかったと思いますね。 Androidの話でいくと、少し趣旨はずれますが、Synced passkeyのみのサポートでよければもう少し楽になったと思います。リリースタイミングとも関わるので、致し方ない部分でもありますが、できればSynced passkeyのみの対応にすると、最終的な実装も楽になって綺麗に実装できたと思います。 @kokukuma:それは完全にあります。最初は Device-bound passkeyの状態で出して、後からSynced passkeyに移行したのですが、やはりDevice-bound passkeyを使っているお客様からパスキーが使えなくなったというお問い合わせは比較的にきやすいので、最初からSynced passkeyにしておけば、こういうことにはならなかっただろうなと思います。 @koi:最後のトピックは、「技術的に楽しかった話」です。FIDOという新しい認証技術に触れてみなさんが思ったことを、ぜひ聞きたいです。 @kokukuma:FIDOをきちんと利用しようとすると、どうしてもアカウント登録やログインのUIに言及せざるを得なくて。それがきっかけで今のメルカリの登録の導線を改善するきっかけになったのはよかったですし、ワクワクしてます。 @daichiro:個人的な意見ですけど、スマートフォン開発をする上で、スマートフォンの機能を使ったものは、とてもやりがいがあるなと思います。 今回の自作の認証器で言えば、秘密鍵の生成や生体認証は端末を持っていないとできないことですし、iOS16以降の対応のときも、最新のAPIを使っての実装だったのでちまたに資料がない状態で作るのはチャレンジングでした。やりきった後は、成長を実感しました。 それから、認証機能はアプリの中でも使う人がとても多い機能で、サービスにとってインパクトがある機能だと思います。そんな開発に携われたことについては、とてもやりがいがありましたね。 @hidey:個人的には、新しい技術の導入は、それ自体が楽しいという感覚はあります。このプロジェクト自体が割と楽しんでやれたとは思ってます。組み込むときにどういう動作になるのかという調査から始めたのですが、調査自体も楽しめました。 認証回りは数年に1回くらい関わることがあるのですが、毎回前回と比べて新しい技術の進化を感じられるのが、刺激的で面白いなとは思ってますね。 @koi:ありがとうございます。さまざまな苦労もありつつ、みなさん成長できる点が感じられ、いいお話を聞けたかなと思っております。質問が一つきてるのでまとめをさらっと終わらせてから、そちらに触れていきたいなと思います。 まとめとしては、iOS15以下をサポートする場合は、独自実装が発生するのでハードな面もありました。FIDOを実際にプロダクトにどう絡めるのかを考えるのは楽しいです。 また、見え方としては地味でも、多くのお客さまに使ってもらう機能のためやりがいがあるという、いいところも聞けました。 ここで、「他社サービスではWebアプリでパスキーに対応する方式も見られますが、ネイティブアプリから使うことは検討されなかったのでしょうか?時期的な話や接続する部分の実装の懸念点があったならば聞きたいです」という質問が来ています。 @kokukuma:確かにその時、iOSでNative APIが一般的には使えなかったので、自前で実装するか、それともWebAuthnを扱うかという話になっていました。結果的に自前に寄せようとなった理由は、メルコインにおけるUXです。特にメルコインでは、お客様が何かしらの操作をするときに追加で認証を要求するという形での利用が主だったので、その操作の間にブラウザ立ち上げて認証だけして落とすという体験が非常に悪かったというのが理由です。 @koi:では、以上でパネルディスカッションを終わりたいと思います。それではご視聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】なめらかなFintech QAを実現するために テストケースフォーマットを標準化した話 – Masatoshi Sato / Yuki Sakamoto【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 なめらかなFintech QAを実現するために テストケースフォーマットを標準化した話 」の書き起こしです。 @satomasa:「なめらかなFintech QAを実現するために テストケースフォーマットを標準化した話」ということで、ここ半年ほど、主に私と@y-sakamotoさんで取り組んだ内容について説明します。 @satomasa:メルペイでQAエンジニアをやっている@satomasaと申します。よろしくお願いします。 @y-sakamoto:同じくメルペイでQAエンジニアをしております、@y-sakamotoと申します。よろしくお願いします。 @satomasa:まず、メルペイQAチームの体制から説明させていただきます。QAチームはQA1・QA2・QA3の3チームにわかれています。それぞれのチームは社員とビジネスパートナーさんで構成され、メンバーはメルペイに存在する各プロダクトにアサインされる形で日々QAの活動を行っております。 メルペイにはいろいろなプロダクトが存在することもあり、QAへのやり方もいろいろあります。バックエンド、フロントエンド、クライアント、QAのプロセスもさまざまです。例えば、テストケースを使わないケースもありました。 また、プロダクトがたくさんあるため、各プロダクトチームの体制も状況もさまざまです。アサインされたチームの状況によって、各QAメンバーが工夫しながらテストケースを進化させていました。そのため、テストケースのフォーマットがチームごとあるいはメンバーごとによっても違う状態でした。 テストケースのフォーマットが標準化されていない状態が続くことで、いくつかの課題が見えるようになってきました。 例えば、アサインチーム変更時のオンボーディングコストが高いこと。例えばプロダクトAからプロダクトBのチームに異動になった場合に、新しいチームのテストケースに慣れる必要があったり、テスト実施時に検出した不具合が管理されていなかったり、チームごとにテスト結果の記載方法が違うため、品質状況を把握するために必要な情報の取得が難しいという問題もありました。 また、QA完了時のテスト計画報告書を作成する際に工数がかかっていました。テスト結果の集計がされていないなどの理由により、QAを完了した後に改めてテスト結果を集計する必要がありました。 以上のような課題を解決するために、テストケースフォーマット標準化プロジェクトが立ち上がりました。 テストケースフォーマット標準化プロジェクトで取り組んだ内容について順番に説明します。 まず、プロジェクト方針の決定ということで、決めたことはいろいろあるんですが、一部を紹介します。 まず、どこまでフォーマットを標準化するかに関しては、当初は「最低限のルールだけ決めて、それぞれのチームである程度自由に変更ができるフォーマットにしよう」ということにしました。 この部分については、後に方針を変更しました。各チームのテストケースを見比べたところ、意外とフォーマットに違いがなかったことと、自由度が高いと、結局バラバラになり、目的を達成できないリスクがあるためです。そこで固定化のフォーマットを作るという方針に変更しました。 プロジェクトの活動方針についても決めました。weeklyでmtgを1時間開催することにし、この時間で、進捗の共有だけではなくて、プロジェクトの作業を行うことにしました。 私も@y-sakamotoも、通常のQA業務を並行して行っているので、このプロジェクトに関わる時間をあらかじめ確保しておくことで、プロジェクトの業務が停滞することがなかったと思います。 次に、各チームのテストケースフォーマットの調査を行いました。 各チームの代表的なテストケースをサンプリングして、10種類ほど集めました。サンプリングしたテストケースをメンバーで比較した結果、各チームでいろいろなテストケースのフォーマットが使用されていることと、基本的な部分についてはあまり違いがないということがわかりました。これによって、どのようにテストケースフォーマットを標準化していくべきかが何となく見えてきました。 次にドキュメントの作成を行いました。今回のプロジェクトで作成したドキュメントは大きく三つあります。テストケースフォーマット、テスト結果集計、運用プロセスです。こちらのドキュメントの詳細は、後ほど説明します。 次にトライアルの実施を行いました。ドキュメントの作成が一通り終わったタイミングで作成したルールやフォーマットが運用に耐えられるかを試すために、トライアル期間を設けました。 まず新しいフォーマットを試してもらえるチームを募集し、実際に運用してもらい、気づいたこと・改善してほしいことをフィードバックしてもらいました。 その内容を、自分と@y-sakamotoさんで確認して、必要に応じてドキュメントを更新しました。トライアル期間でいくつかフィードバックをもらいましたが、運用上、大きな問題が発生しないってことがわかったので、バージョン1.0のリリースに向けて、さらにドキュメントの精度を上げていくことになりました。 いよいよバージョン1.0のリリースとなります。トライアル期間で出たフィードバックを元に修正をして、バージョン1.0としてリリースしました。ただ全チームで一斉に新しいフォーマットに切り替えることが難しいので、切りのいいタイミングで新しいフォーマットへの移行をお願いしました。 プロジェクトの立ち上げが2022年12月で、バージョン1.0のリリースが2023年4月と5ヶ月ほどかかりましたが、何とかリリースできました。 現在は、運用のフェーズとなっております。 運用フェーズでもフィードバックシートを用意して、実際に使ってみて感じた点や疑問点、不明点を書いてもらっています。運用フェーズでもweeklyのmtgは継続していて、新しいフィードバックがあれば、メンバーで議論して、改善が必要な点は、ドキュメントを更新しております。 次に、今回のプロジェクトで作成したドキュメントについて説明します。 @y-sakamoto:私の方から、テストケースフォーマットについて説明します。まずは目的を明らかにしました。先述の通り、今まではチームごとにフォーマットが異なっていたため、品質の分析に必要な情報が得られないケースもありました。 例えば、Aチームのテストケースにある項目が、Bチームのテストケースにはないため、最終的な品質分析を行う際に、Bチームのメンバーにヒアリングをして必要な情報を得るという、無駄な工数がかかることもありました。 またフォーマットが統一されることによって、チーム異動が発生した場合も、改めて異動先のフォーマットに慣れる必要がなくなるため、浮いた時間はドメインキャッチアップなど、よりオンボーディングでフォーカスしたいことに当てられると考えました。 続いて、我々はテストケースの項目とレイアウトを作成しました。テストケースに記載すべき必須項目については、検証観点や環境、エビデンス、確認手順、期待する結果など一般的なものを設定しました。 しかし、チームや検証対象によって必要な情報というのは異なりますので、必須項目以外にも、各チームの判断で項目を追加して良いというルールになっています。 また弊社ではイングリッシュスピーカーの方にテストケースのレビューをお願いすることもあるため、一部を英語化してレビューしやすいように言語面でも工夫を加えています。 メインとなるテストケース以外にも、必要なシートを作成しました。一つはバグ一覧シートです。 これまでは検出したバグを各チームおのおのが定めた場所で管理をしていました。しかし、チーム横断で行われる大規模な開発などでバグ集計をするときは、異なる管理場所を確認をしなければならず、バグを集計するだけでもコストがかなりかかっていました。そこでフォーマット内にバグ一覧シートを作成して、そこさえ確認しにいけば良いという形にしました。 次に自動テスト結果シートです。こちらはリリースの際に実行した自動テストの結果を残すシートになっています。 これまでは自動テストの結果をどう残すのかが定まっていなかったので、テストの証跡として十分ではありませんでした。しかし、実施した場合はこのシートに結果を残すと明確にルール化したことで、きちんと自動テストが実行され、QAもその結果を確認しているという証跡が間違いなく残るようになりました。 @satomasa:次にテスト結果集計について説明します。結果集計を必須にすることで、各チームの品質状況の把握の効率化と一定のルールに沿った集計結果シートをあらかじめ作成することで品質報告書の作成を効率化することが目的となります。 具体的に決めたルールとしては、テストケースの結果に使用する種別をOK・NG・Resolved・対象外・保留の五つとしました。特にNGだったテストケースがOKになった際に使う「Resolved」は各チームでルールがバラバラだったので、今回の標準化で統一された部分です。 テスト結果で集計する項目も決めました。 具体的には、項目数、実施対象項目数、OK、NG、Resolved、対象外、保留、進捗率、完了率、残項目数の10項目としました。項目も決めたのと、各項目の計算方法も、今回決めたので、チームによって、進捗率の計算方法や実施対象項目数のカウント方法が違うことがなくなり、全チーム同じ結果が集計できるようになりました。 現在、メルペイではこの集計シートを使ってテスト結果を管理しております。 次に、運用プロセスです。今回定めたテストケースフォーマットを正しく運用するために、運用プロセスを定義しました。 テスト実施中に検出した不具合をバグ一覧シートにまとめる、自動テストの結果を自動テスト結果シートに記載する、などの内容が書いてあります。運用が正しく行われているかを確認するために、チェックリストも作成しました。 テスト完了時にチェックすることで、テスト完了時にも、ルール通りに運用されているかの確認を行っています。 @y-sakamotoさん、良かったところはいくつかあると思いますが、何かありますかね。 @y-sakamoto:僕はテストケース設計するときに毎回フォーマットに悩む時間が少なからずあったので、フォーマットがすでに用意されていることで無駄な考える時間が数が減って、テスト観点出したり、設計時に本当にやるべき作業により集中できたと思います。 @satomasa:テストケースレビューの効率化もできたと思います。テストケースレビューは、開発の人も担当することがあるので、QAエンジニア以外にもメリットがあったと思います。 @y-sakamoto:フォーマットがバラバラだと、違うチームからレビューを頼まれたときにどこを見たらいいかわからないこともあったので、フォーマットが統一されているとレビューは確かにしやすいですね。 パートナーさんにも聞いたのですが、フォーマットが統一されたことで進捗状況が一目でわかると好評で、私も嬉しかったです。 @satomasa:それから、チーム異動時のオンボーディングコストの削減。今のところチーム異動が行われるケースはありませんが、削減される見込みです。 次に苦労したことです。難しい点は、やはり全ての要求を満たすテストケースフォーマットを作ることでした。 @y-sakamoto:全員の意見を盛り込もうとすると、情報過多になりフォーマット化した意味がなくなることもあると思います。意見を取捨選択することも難しかったです。 また、意見を反映しなかった場合に、「意見をくれた人にどうやって説明しよう」という大変さもあったかなと思います。 それから、最初の方針決めるときに、例えばバックエンドとクライアントという性質が違うものを同じフォーマットにまとめる運用と定めましたが、その判断は勇気が必要だったなと思います。 性質が違うものを同じケースでうまくやれるのかという不安はありましたが、意外に使ってみると大丈夫だったので一安心でした。 @satomasa:自分も@y-sakamotoさんも通常のQA業務を抱えつつ、こちらのプロジェクトに参加してたので、業務が忙しいときはこちらのプロジェクトに関わる工数が確保できず苦労しました。 @satomasa:今回のプロジェクトを通じて、思わぬ効果もありました。 具体的には、QAチーム内でのコミュニケーションが活性化されました。現状のQAチームの体制上、各プロジェクトチームに配属になっているので、なかなかQAメンバーでコミュニケーションを取る機会が正直ありませんでした。 一つのことにQAメンバーで取り組む機会がなかったので、今回のプロジェクトを通して、今までコミュニケーションが取れていなかったQAメンバーとも、コミュニケーションが取れるようになったのが大きかったかなと思ってます。 @y-sakamotoさんとも所属しているプロダクトチームが違うので、これまではあまり話したことがありませんでしたが、今回のプロジェクトを通してコミュニケーションが取れたと思います。 @y-sakamoto:そうですね。プロジェクトが違うと、長い間一緒に何か一つのことをやる機会がなかったので私も@satomasaさんとこの標準化のプロジェクトをやれてよかったかなと思いますし、これからのQA業務やまた何か一緒にやろうってなったときもよりスムーズにできると思います。 @satomasa:最後に、今見えている課題と、今後取り組んでいきたいことを紹介します。 まずは全チームへ浸透させたいです。多くのチームに使ってもらうことで、いろいろなフィードバックを得られるので、それを参考にしながらよりよいフォーマットを作りたいです。 今後取り組んでいきたいことは、テスト結果報告書の自動作成です。テストケースフォーマット等や集計結果を標準化したことで、テスト結果報告書に必要な情報が収集できるようになりました。 その情報をもとに、テストが終わったタイミングで、テスト結果報告書を自動作成できる仕組みを作れたらと思います。 @y-sakamoto:自動作成を実現できたら、ものすごく工数削減になると思います。 @satomasa:以上が、テストケースフォーマット標準化プロジェクトで取り組んだ内容です。ご清聴ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】発生可能な取引の属性データを用いた素早い不正検知 – Liu / Li【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 発生可能な取引の属性データを用いた素早い不正検知 」の書き起こしです。 @Liu:みなさん、こんにちは。本日のプレゼンテーションにお越しいただきましてありがとうございます。 本題に入る前に、簡単に自己紹介をさせてください。私は2019年10月に機械学習エンジニアとしてメルカリに入社し、不正防止システムの開発に関わっています。 @Li:私は@Liです。私は2017年4月にヤフー株式会社に入社し、ソフトウェアエンジニアとして働いていました。2019年1月からは機械学習エンジニアに軸足を移し、2021年9月にはメルカリに入社しました。現在は機械学習プラットフォームの構築に関わり、最近ではFeature StoreやGraphDBなどの技術開発に取り組んでいます。 @Liu:ここでは、不正防止モデルとテクニックをご紹介しております。関心がある方はブログの記事をご覧ください。 参考記事 不正検知システムに機械学習を導入してコストマネジメントを実現した話 ML technique used to detect ChargeBack in Merpay つながりをデータから解き明かしたい ~ 複雑ネットワークの世界とそれを活用した不正検知の紹介 そしてここにいくつかの過去のイベントがございます。 参考資料 Using Feature Store and Vertex Pipelines in Fraud Prevention System Feature StoreとVertex AIを使った機械学習基盤の実現 グラフ理論と不正対策〜つながりをデータから解き明かしたい それではプレゼンテーションの主要なポイントに注目をしたいと思います。主に5つをカバーします。 まず最初に背景について説明します。私たちの不正検知の戦略は、大きく二つに分けられます。事後検知と即時検知です。 事後の検知とは、不正な取引が行われた後に発覚し、商品の配送を停止するなどの措置を取り、不正の被害を防止することです。すでに配送完了とされている商品もあるため、不正を見逃す可能性があると言われています。 一方、即時検知は取引の進行中に検知する方法であり、不正行為が発生した場合には素早く対処することができます。応答時間は0.1秒の場合もあります。 即時の不正検知を実現するためには二つの重要な要素があります。 まず、TnSのバックエンドチームが提供するJudgeサービスがあります。このサービスは超高速な不正防止システムであり、低遅延の設計がなされています。 次に、機械学習チームが開発した不正関連の機械学習ソリューションがあります。このソリューションは、潜在的なリスクランクを1分から1日の単位で算出し、Judgeサービスに提供します。機械学習ソリューションとJudgeサービスの不正防止システムを組み合わせることで、私たちはさまざまな不正取引をニアリアルタイム(Near-Realtime)で検知し、防止することが可能になります。 参考記事: 「0.1秒でも遅ければ、お客さまを守れない」不正検知領域に挑むメルペイのエンジニアが日々感じる“奥深さ このような背景を踏まえて2つ目のアジェンダに移りたいと思います。 これは不正検知をニアリアルタイムに加速するためのメカニズムです。取引が完了する前に潜在的な取引のリスクランクを算出し、提供することで、プロアクティブなアプローチで不正リスクを低減することができます。 これを実現するための鍵は、取引が発生したり完了したりする前に存在している属性データを活用することです。 このデータには、アイテム情報や、セラー情報、バイヤー情報などの重要な詳細が含まれています。これらの情報は、潜在的な取引のリスクを評価するために必要です。このデータを分析することで、不正取引の可能性を予測し、事前に対策をとることができます。 これによって私たちの不正検知システムをプロアクティブで効率的に改善しています。そして全てのお客さまに安全な体験を提供することを保証しています。 私たちの仕組みは主に3つのステップで構成されています。まず、機械学習モデルを活用して、属性データに基づいて潜在的な取引のリスクランクを計算します。その後、潜在的なリスクランクは計算が完了するとJudgeサービスに送られ、不正判定に使われます。 Judgeサービスは、継続的に進行中の取引をリアルタイムでチェックし、送られたリスクランクを使って潜在的な不正取引を特定します。このプロセスにより、私たちは不正取引が被害をもたらす前に発見し防止できるようになります。 私たちのMLソリューションでは、元々バッチ予測を行いましたが、この方法には一つの課題がありました。バッチ予測する前に取引が終了してしまった場合、検知が取引の終了後になり、防止対策に手遅れが生じる可能性があります。 この課題を解決するためには、取引が終了する前に潜在的なリスクランクを計算し、Judgeサービスに送信する必要があります。つまり、既存のバッチ予測では手遅れになる取引を検知するために、不正検知プロセスを加速する必要がありました。それには、バッチ予測よりも早い検知方法が必要でした。 不正検知プロセスを加速するために、私たちは既存のバッチソリューションにストリームソリューションを導入して、ニアリアルタイムの検知を実現しました。この新しいソリューションでは、Feast Online StoreとStream予測システムを作り、利用しています。これによってデータ処理と予測をニアリアルタイムで行い、より効率良く不正検知を行うことができます。 プレゼンテーションの三つ目の要素・システムアーキテクチャに進みたいと思います。 システムアーキテクチャは、さまざまなコンポーネントを統合し、スムーズで効率的な検知プロセスを保証しています。 アーキテクチャは、四つのパートで作られております。 まず、Feature Storeですが、これについては次のパートで@Liから紹介されます。そして次がバッチシステムで、Vertex Pipelinesを使用して実行されています。ストリームシステムではマイクロサービスを活用して、ニアリアルタイムの処理を行っております。 そして、Publish APIを使って最終的な計算結果をJudgeサービスに送ります。このアーキテクチャにより私たちは潜在的な取引のリスクランクを予測・計算し、提供することができます。 バッチシステムは、大規模なデータ処理やモデル予測する上で重要な役割を担っており、膨大な過去データをもとに効率的にリスクを計算することができます。 バッチの実行管理はCloud Schedulerによって行われています。これにより1日または1時間単位で予測をスケジュールし、トリガーすることができます。また、データ処理とモデル予測にはVertex Pipelinesが使用されています。 データは、SpannerとBigQuery上で保存・管理されています。 次がStream Systemです。 Stream Systemは、3つのマイクロサービスから成り立ちます。まず、複数のサブスクライバーを持つワークロードサービスです。次に、特徴量の取得と挿入を担当するAPIサービスであるFeature Serverがあります。そして最後に、ML予測やロジック処理を行うサービスがあります。特徴量データと予測結果などはSpannerを用いて保存と管理がされています。 こちらはマイクロサービスが連携・動作しているフローを示したシーケンス図です。 Publish APIは、潜在的なリスクランクの計算結果をJudgeサービスに送信する役割を担っています。Outboxに保存されているリスクランク情報は、Publish APIにリクエストしてPublishします。 こちらはOutboxに格納されているデータフォーマットです。中には、Pub/Subに必要な情報が含まれています。また、Publishされたかどうかを判定するフラグ情報や、「この時間までレコードを送信しないように」指示するschedule TIMESTAMPも含まれています。 Publish APIは、Cloud Runにデプロイされ、以下のように使われています。 Publish APIは計算された潜在的なリスクランクをPub/SubのMessageとしてJudgeサービスに送信します。 バッチシステムからの計算結果は、Outboxに定期的に蓄積されます。Cloud schedulerは1分ごとにPublish APIがJudgeサービスに対してOutboxのデータをPublishするようトリガーします。Stream Systemの計算結果は、専用のPub/SubからPublishされます。Publish APIは送られた計算結果をSubscribeし、JudgeサービスにPublishします。 こちらでは、Public APIの仕組みを示しています。興味のある方はぜひご覧ください。 私からのメッセージは以上になります。ありがとうございました。 @Li:それでは、続いてFeature Storeについて説明します。 Feature Store (FEAST) は主にデータの入力部分を担当しています。特徴量テーブルの管理やモデルのトレーニング、予測に必要なデータを提供します。データはBigQueryとSpannerに保存されており、モデルのトレーニングやバッチ予測用のデータはOffline Store (BigQuery)から、オンライン予測用のデータはOnline Store (Spanner)から提供されます。 先ほど不正検知のためのストリーム予測が紹介されましたが、ニアリアルタイムでの不正検知を実現するためには、推論だけでなく、特徴量の取得もニアリアルタイムかつ低遅延で提供する必要があります。そのために、私たちはFeast Online Storeを導入しました。 まず、Feature Storeがどのような役割を果たすのか、簡単に紹介させてください。 この図は、Feature Storeのない典型的なMLインフラの一部を示しています。Feature Storeがないと、データソースへの接続やデータ処理のコードなど、同じコードが複数のトレーニングジョブ間で重複してしまい、冗長になります。また、特徴量の処理フローはトレーニングとサービングのプロセスに埋め込まれているため、特徴量の再利用が容易ではありません。 そのため、データサイエンティストはモデルを構築する際、データストアにアクセスするための低レベなコードを書く必要があり、データエンジニアリングのスキルが求められます。 参照: https://www.hopsworks.ai/post/feature-store-the-missing-data-layer-in-ml-pipelines この図は、Feature Store導入後の概要を示しています。Feature Storeを使用することで、データソースとモデルの間の特徴量を一元的に管理し、全ての特徴量を一箇所に保存・管理し、異なるモデル間で再利用することができます。 データサイエンティストは簡単に特徴量を検索し、それらを使用してモデルを構築することができます。一方、MLエンジニアはモデルの管理に集中することができ、データエンジニアは特徴量の作成と管理に専念することができます。効果的な役割分担が可能となり、生産性が向上します。 Feature Storeの中には、Online StoreとOffline Storeという2つのコンポーネントがあります。これらは主に異なる目的で使用されます。 Online Storeは、オンライン予測時に特徴量を提供するために使用されます。対象の最新特徴量のみを保存し、低遅延のアクセスを可能にすることで、特徴量値の迅速な取得を最適化しています。 一方、Offline Storeは大量の過去データを保存・管理することに特化しており、バッチ予測やモデルトレーニングジョブに活用されます。 これらの2つのコンポーネントは、効率的かつ効果的な特徴管理を提供するために協力して動作します。 Feature Storeのアーキテクチャはこちらのようになります。 データ自体は、BigQueryやSpannerなどのデータストレージに格納されています。Feature Storeは、中間層として機能し、特徴量へのアクセスを簡単かつ整理された形で提供します。 まず、Online Storeを見てみましょう。 Online Storeには、2つの異なるデータ収集方法があります。1つ目は、Kafkaから流れてきたデータをFlinkが処理し、処理済みのデータがFeature Server APIを介してOnline Storeに取り込まれる方法です。2つ目は、Offline StoreからデータをOnline Storeにマテリアライズする方法です。 なぜなら、一部の特徴量はリアルタイムではなく、直接的にKafkaから取得することができないため、Offline Storeからデータを取得して必要な特徴量セットを揃え、予測時に提供する必要があるからです。マテリアライズジョブはCloud Schedulerからトリガーされます。 Offline Storeに関しては、データ変換ツールであるdbtを使用して特徴量テーブルが作成および管理されます。 先程、Online Storeへのデータ取り込み方法について2つ存在すると話しましたが、ではいったいどの特徴量はマテリアライズし、どの特徴量をストリームで取り込むべきでしょうか。 基本的には、リアルタイムで取得可能な特徴量はストリームで取り込み、処理するべきです。一方で、集計された特徴量などのリアルタイムではない特徴量は、Offline Storeからマテリアライズするのが適しています。 もちろん、すべての特徴量をOnline Storeにマテリアライズすることも可能です。その場合、モデルのパフォーマンスは基本的にバッチ予測と同様になります。 マテリアライズジョブの実行方法には、定期実行とオンデマンド実行の2つがあります。 定期実行では、主にCloud Schedulerがトリガーとして活用されます。Cloud SchedulerはPub/Sub経由でマテリアライズジョブに関する設定情報を送信します。それにより、サブスクライバーAPIがメッセージを受け取り、Feature Serverにジョブの開始をリクエストします。 一方、オンデマンド実行では、マテリアライズジョブ情報を含むメッセージを直接Pub/Subに送信します。その後の流れは定期実行と同様です。 このときのPubSubは、マテリアライズジョブに関するすべてのリクエストを受け入れるハブとして機能しています。 最後に話したいもう一つのポイントは、Online StoreとOffline Storeの間でFeatureViewを管理する方法です。 FeatureViewは、特徴量データをコンテナのように保持し、エンティティに関連する特徴量の論理的なグループを表現しています。 Offline Storeには"M"という名前のFeature Viewがあり、リアルタイムの特徴量Aと非リアルタイムの特徴量Bを含んでいると仮定しましょう。 予測のために、Online Storeにもデータを持たせたい場合、どのようにOnline Storeにデータを取り込むかを選択する必要があります。 ここでの問題は、特徴量AはKafkaから取得できますが、特徴量Bはマテリアライズジョブを介してOffline Storeからのみ取り込むことができるということです。 異なる方法で同じFeatureViewにデータを取り込むと、データ上書きが発生し、新しいデータが古いデータに上書きされてしまう可能性があります。 この図は、2つの方法を使用して同じFeatureViewにデータを取り込む場合に何が起こるかを示しています。 Kafkaからの取り込みとマテリアライズジョブの両方がFeatureView単位でデータの挿入を行うため、同じFeatureView内ではストリームで取り込まれた最新の特徴量が、マテリアライズジョブで取り込まれた1時間前の特徴量に上書きされる可能性があります。 もちろん、Offline Storeからすべての特徴量をマテリアライズして上書きを防ぐこともできますが、ストリーム取り込みはニアリアルタイムで行われるため、最大限活用したいと考えています。 解決策は非常にシンプルです。それは、Online Storeで取り込み方法ごとにFeatureViewを分けることです。 まず、Online Storeで新たに2つのFeatureViewを作成します。 "stream_feature_view_M"では、"feature_view_M"の中でKafkaから取り込まれるリアルタイム特徴量定義のみを含めます。 "materialize_feature_view_M"では、"feature_view_M"の中でOffline Storeからマテリアライズされる特徴量定義のみを含めます。 モデルには、2つのFeatureViewデータを合わせて全体特徴量としてを提供します。 最終的に、Offline Storeではモデルのトレーニングとバッチ予測向けに"feature_view_M"の特徴量を提供し、Online Storeではオンライン予測向けに"stream_feature_view_M"と"materialize_feature_view_M"を合わせた特徴量を提供します。 これにより、同じFeatureView内で特徴量の更新頻度が違うとしても、データが上書きされず、正しく更新された特徴量データを提供することができます。 これがこの解決策の基本的な考え方の説明になります。 最後にまとめです。 本セッションでは、不正検知速度を向上させるための新しい仕組みについて説明しました。この仕組みでは、取引が行われる前に潜在的なリスクランクを算出し、即時不正防止システムに提供することで、全体的にニアリアルタイムの不正検知を実現しました。 この仕組みは不正検知を高速化し、機械学習モデルの予測をニアリアルタイムで不正防止に活用することができます。 また、このメカニズムを実現するためのシステムアーキテクチャやその具体的な実装方法についても話しました。既存のバッチソリューションにストリームソリューションを導入することで、包括的な不正防止ソリューションにより一歩近づくことができました。 お知らせがあります。私たちは不正防止システムにGraphDBを取り入れました。グラフベースのアプローチは、不正検知に置いて顕著な効果を発揮しています。データ間の関係やパターンを見つけることで、さまざまなタイプの不正を特定することができます。さらなる詳細については、近日中に公開されるブログ記事をお楽しみにしてください。 それでは本日のプレゼンテーションは以上とさせていただきます。ありがとうございました。
株式会社メルカリ
2023/10/23
【書き起こし】GoによるSQLクエリテストの取り組み – Yuki Mukasa【Merpay & Mercoin Tech Fest 2023】
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 GoによるSQLクエリテストの取り組み 」の書き起こしです。 @a-r-g-v(batta):GoによるSQLクエリテストの取り組みについて、発表させていただきます。 初めに自己紹介をさせてください。2020年に新卒としてメルペイに入社をしました。そこから3年間ほど、メルペイの加盟店管理のシステムを作るチームに配属されていました。現在は、メルカリの認証認可を担うチームに所属しております。 こちらが本日のアジェンダです。 はじめに、背景を説明します。加盟店管理のチームには、複雑な条件を持つBigQueryのSQLクエリがいくつか存在しています。 例えば、加盟店管理の費用計算などの計算クエリのように、外部環境の変化によって要件が定期的に変更され、マイクロサービス化などのシステム化が難しいクエリがあります。このクエリは、複雑であるだけでなくテスタビリティにも問題がありました。 そのため、開発者がテストを実施することが困難になっており、クエリの変更を安心して行えない状態にありました。 では、このクエリの複雑性とはどのようなものだったのでしょうか?大きく二点ありました。 一つは、抽出条件の複雑さです。契約条項に基づく複雑なビジネス要件が、クエリの複雑さを増す要因となっていました。例えば、加盟店管理費用を計算するビジネス要件においては、正しく費用を計算するために、審査通過日、加盟店獲得後の決済情報、決済用QRコードの要否の情報を組み合わせて、クエリを行う必要があります。この条件がクエリを複雑にしていました。 また、クエリが複数のマイクロサービスのデータベースを横断して参照していることによって、複雑さを増していました。メルペイでは、マイクロサービスアーキテクチャを採用しており、業務ドメイン単位でサービスが分割されています。 例えば、加盟店の申し込み、審査、事業者の情報、決済履歴、QRコードの配送履歴などは、それぞれ別のマイクロサービスとして分割されています。一方で、管理費用を計算するためには、これらのデータベースを横断的に参照する必要があります。また、これらの依存しているマイクロサービスの中には、別のチームが管理しているものもあります。この状況が、クエリを複雑にさせています。 では、チームにはクエリにまつわるどんな課題があったのでしょうか?大きく二つありました。 一つは、クエリに対する開発テストが煩雑であったことです。複数のマイクロサービスのテーブルに依存しているために、投入対象のテーブルの数や、投入データ行数が多くなっていました。また、クエリの抽出条件が複雑であるため、必要なテストパターン数が多く、データとして投入する量も多くなっているという課題がありました。 また、手作業の多さも問題でした。実際のテスト環境のテーブルに対して、マイクロサービスが生成していないデータを投入することは、問題です。そのため、クエリをテストするために、新しくテーブルを作り、テストデータを投入した後にそのテーブルを使用するようにクエリを書き換え、クエリを実行・結果検証・クリーンアップという手順を、都度のクエリごとに行う必要がありました。これを毎回のクエリ改修や、テストパターンごとに行うのが大変であるという課題がありました。 二つ目は、クエリに対する自動テストの欠如です。デグレードを検出する自動テストスイートが存在しませんでした。そのため、クエリの変更を安心して行うことができない状態になっていました。 これらの課題に対する解決方法として、Goのテストから、クエリに対するテストを実装できる仕組みを作成しました。 具体的には、テストコードから参照されるライブラリとして実装しました。これは、テストコードによってテストデータを投入し、BigQuery上でSQL実行を簡単に行える仕組みを組みました。この仕組みによって、可読性・メンテナンス性が高い形でテストを行えるようになりました。 また、このテストデータ作成を支援するために、クエリからGo構造体を自動で生成するツールも作りました。さらに、この方法で作成した自動テストケースを蓄積し、CIで実行することによって、デグレードの検知を自動化しました。 次に、全体の動作イメージを説明します。クエリのテストはGoのテストとして、テストケースを実装するようにしました。 テストケースごとに、こちらを実行します。まず、テスト対象が依存しているテーブルを抽出して、テスト用のデータセット配下にテーブルを1件ずつ作成します。 テストケースで指定されているテストデータを、テスト用のテーブルに挿入します。次に、テスト対象のクエリのFROM句に書かれているテーブル名を、作成したテスト用のテーブルを利用するように書き換えます。 書き換えたクエリを実行して、期待している結果と同じかどうかを確かめ、最後にテストケースのクリーンアップ動作で作成したテスト用のテーブルを全て削除する形で動作します。 また、テストケースから、テストデータの投入を支援するために、クエリが利用しているテーブルをGoの構造体として自動生成する仕組みも作りました。 具体的には、同一リポジトリに存在する全てのSQLファイルを読み、コード生成を行うコマンドを作りました。コマンドは二つの構造体を生成します。 一つは、クエリが依存しているテーブル一覧を表す構造体です。クエリが依存しているテーブルを全部列挙して、対応関係をGoの構造体として生成します。ここの利用テーブルの列挙は、正規表現を用いてFrom句をパーズして行いました。 二つ目は、各テーブルの定義に対応するGoの構造体です。上記で算出したクエリごとに、テーブルのスキーマ定義を実際のテスト環境のBigQueryのテーブル定義を参照し、自動生成するコマンドを作成しました。 それでは、実際に作成したツールを用いて、クエリに対してテストを作成する方法を実現したいと思います。 こちらがデモで使用するテスト対象のSQLクエリです。このクエリは、UsersテーブルとChargeテーブルをユーザーIDで結合して、ReferralTypeがORGANICであるユーザーの決済金額の合計を算出するクエリです。このクエリに対してテストを書きます。 先立って、このUsersテーブルとChargeテーブルのテーブル定義をお見せしたいと思います。 こちらが、BigQuery上に存在するUsersテーブルの定義です。Usersテーブルは、ユーザー1行ごとに行が作成されるテーブルです。 もう一つは、ペイメントサービスのChargeテーブルです。Chargeテーブルは、ユーザーの決済コードを1回ごとに1行作成されるテーブルです。 それでは、実際にテストを変えていきたいと思います。まずテストを書く前に、コード生成のコマンドを実行します。このコマンドを実行することによって、このクエリが依存しているUsersテーブルとChargeテーブルのGoの構造体が自動で生成されます。 また、先ほどのクエリが依存しているGoのテーブルの一覧を表す構造体と、BigQueryに対して、簡単にデータを投入できるヘルパー関数が生成されます。このヘルパー関数を使って、クエリに対してテストを書いていきます。 ヘルパー関数を指定し、Goのテストを書いていきます。スライスの一つ一つが1行に対応するイメージです。先ほどのクエリは、ユーザーIDでジョインしていたテーブルですから、同じユーザーIDを使うために定数を宣言しておきます。 このように同じユーザーIDを使用するようにして、金額も1,000にしておきます。あとユーザーのタイプがオーガニックでないといけないので、そのようにします。このヘルパー関数が生成するクエリをプリントするのと、実際にBigQuery上でこのクエリを実行してみたいと思います。 実行すると、まずクエリが出力されます。ヘルパー関数がテストテーブルを作り、データを挿入して、そのテストテーブルを使用するように、書き換えたクエリが作成されています。 これをBigQueryで実行すると、ここで投入したデータ、つまり「Totalamount:1000」というデータが実際に出力されます。このように、Goのテストの書き味で、クエリに対してテストが書けるようになります。 次にクエリテストの取り組みの効果についてお話します。大きく二つの効果がありました。 一つ目は、開発者テストの実施が容易になり、安心してクエリを変更できるようになったことです。テストデータのコーディングに型の支援を入れるようになったため、列名やデータ種別の誤指定の防止や、IDによるコード補完の恩恵を受けることができるようになりました。また、テストデータの共通化やGoのテーブルテストの活用が可能になり、差分テストケースの追加が簡単になりました。 これにより、境界値テストケースの一つの値だけを変更してテストを行うケースの追加が簡単になりました。また、共通化により、クエリに対してテストを網羅的に実施するコストが低下しました。 二つ目は、開発者テストの蓄積によりデグレード検知ができるようになったことです。自動化されたテストケースが蓄積されたことにより、クエリ変更に際するでグレートの検出が簡単に行えるようになりました。 そのため、より安心感を持ってクエリ変更を行うことが可能になりました。 今後の展望として、追加したい機能や応用の方法を三つ考えています。 一つは、QAテストケースの置き換えの検討です。QAテストにおいても本ツールを応用して、テストデータの投入やQAテストの実施、テストケースのメンテナンスをQAチームが完結して行える仕組みを作成したいです。 二つ目は、クエリのテストケースの網羅性を可視化する方法の検討です。Goの通常のテストでは、コードカバレッジなど、テストケースの網羅性を計算・可視化するためのメトリクスを簡単に利用できます。同様に、SQLクエリに対してテストカバレッジを算出する研究があり、類似の仕組みを本手法にも導入できないか検討したいと考えています。 三つ目は、投入テストデータの正しさの検討です。投入テストデータとマイクロサービスが実際に作成するデータに不一致があると、テストの意味がなくなってしまいます。現状では、クエリテストに利用するテストデータを作成する際、依存マイクロサービスの振る舞いを理解して、データを作成しています。この不一致のリスクを最小限にするために、データインターフェースの明文化などを検討したいと考えております。 以上で発表を終わりにします。ご清聴ありがとうございました。
株式会社メルカリ
2023/09/22
mercari.go #23 を開催しました #mercarigo
はじめに こんにちは、mercari.goスタッフの shota sugiura です。 9月7日にメルカリ主催のGo勉強会 mercari.go #23 をYouTubeでのオンライン配信にて開催しました。この記事では、当日の勉強会の活動内容をレポートします。動画も公開されていますので、こちらもぜひご覧ください! mercari.go #23では、株式会社ナレッジワークより @tenntenn さん、株式会社カウシェより @yuki.ito さん、株式会社Stackより @そな太 さんをお招きして、パネルディスカッション形式でGoに関する意見交換をしていただきました。Go1.21が2023年8月にリリースされたことを受けて、Goのモダンな書き方やError Handlingの方法、Go1.21で利用したい新しい機能をテーマに、各社の事例を交えた興味深い議論が行われました。 mercari.goスタッフとして、イベント視聴した私の感想も含め、パネルディスカッションの内容を簡単にまとめてご紹介します! テーマ1: Goのモダンな書き方 https://www.youtube.com/watch?v=QtLTQkAj8ec&t=126s 最初のテーマでは、各社の事例を元にしたGoのモダンな書き方についてお話していただきました。 @yuki.itoさんからは、カウシェで実践しているモノレポでのマイクロサービス開発について話していただきました。モノレポにすることで、会社としてのスタンダードなパッケージ構成の提供やビジネスロジックに関わらない処理の共通化ができ、プロダクト全体の品質を担保できます。最近リリースされた gonew というツールを早速使っていて、これを利用して会社標準の新しいアプリケーションを素早くスピンナップできるようにしているそうです。また、全社で共通のgo.modを使ってモジュールの管理をしているというのも非常に興味深い話でした。 Go 1.21に入ったツールチェーンに関する変更についても触れられました。go.modに書いてあるversionをみてツールチェーンのアップデートが自動でかかるようになったなど、嬉しい変更が入っています。これに関連して、Goのビルドの完全性に向けた取り組みについての ブログ が話題に上りました。最近特に、Goチームがサプライチェーンアタックへの対策に力を入れているようで、こういった言語標準レベルでの取り組みによってGoがより便利で安全なものになっているのだなと感じました。 テーマ2: Error Handling https://www.youtube.com/watch?v=QtLTQkAj8ec&start=1545s 過去のmercari.goでもたびたび話題になっているError Handlingですが、パネラーの方々それぞれのアプローチが聞けて参考になりました。 @そな太さんは、標準のインターフェースを利用できて、かつスタックトレースを取りたいという理由から xerrors を使い続けているそうです。特に困ることはないそうですが、最新標準に入った複数のエラーをラップする機能などを利用できないデメリットを許容できるかは考えどころです。 @yuki.itoさんは、標準のパッケージのerrors、fmt.Errorfを利用しているそうです。スタックトレースは取れないですが、必ずエラーの発生箇所を特定できるような有意なメッセージをつけてエラーをラップするというのを社内で徹底しているそうです。ただ、うっかりラップし忘れるのを完全に防げるわけではないので、linterなどで機械的に防ぐのも良いかもしれないとお話されていました。 @tenntennさんからは、非常に面白いアプローチが紹介されました。Goチームが管理しているpkg.go.devのinternalなpackageに derrors というものがあり、このパッケージのWrap関数を真似して利用しているそうです。名前付き戻り値でエラー変数を定義し、そのポインタを引数に渡してderrors.Wrapをdeferで呼ぶと、nilでないエラーが返ってきた時に必ずラップする仕組みになっています。エラーのラップだけではなくて、GCPのError ReportingやSentryのようなエラー通知の処理も挟むことができるのでとても便利そうです。 このほかにも、クリーンアーキテクチャーにおけるエラーの扱いや、ログレベルに関する話など、多くの人が気になっているであろう話題に関して各々の取り組みを紹介いただきました。 テーマ3: Go1.21で利用したい新しい機能 https://www.youtube.com/watch?v=QtLTQkAj8ec&t=3140s このテーマの最初に話題に上がったのは1.21で導入された slog です。@yuki.itoさんと@そな太さんはまだ本番では利用できていないですが、ゆくゆくは今利用しているライブラリを置き換えてslogを利用してくことを検討しているそうです。既にサードバーティのライブラリで実現できていた機能ではありますが、そのような誰しもが使う機能が標準に入ったことの意味は大きそうです。 Go1.21ではあらたにmaps, slicesパッケージが導入されましたが、このmapsパッケージに入る予定だったmaps.Keys, maps.Valuesは1.21のリリース直前に削除されました。この動きの背景となっているiteratorのデザインや、それを利用した xiter パッケージのプロポーザルに関する話題でパネルディスカッションが盛り上がりました。今まさに議論されている機能なので、これがどのような形でまとまって実装されていくのかとても興味深いですね。 おわりに 今回はいつものmercari.goとは一味違うパネルディスカッション形式の勉強会をお送りしました!Goのモダンな書き方や今後の展望など、Goの最先端の情報を追っているお三方ならではのお話を楽しんでいただけたのではないでしょうか? ライブで視聴いただいた方も録画を観ていただけた方も本当にありがとうございました! 次回のmercari.goでは、9月末に開催される GopherCon 2023 の参加者を集めて活動報告会を開きます。10月下旬に開催する予定なので、 メルカリcompassグループ のメンバーになってイベントの通知をお待ちください。次回もお楽しみに!
株式会社メルカリ
2023/09/20
#ididblog #iosdc で「サワードウ(パン)」と「メルカリiOSの10年間の歩み」について発表してきました
こんにちはメルカリで Architect チームの Director of Engineering をしている @motokiee です。 iOSエンジニアの祭典である iOSDC Japan 2023に参加してきました。今年で8回目を迎えた iOSDC Japan ですが、2019年以来のオフラインメインでの開催ということでとても盛り上がっていました。 また、メルカリとしては初めてブースを出展したのですが、180名以上の方に立ち寄っていただき参加者の方々と交流することができとても有意義でした。 今回、メルカリからは2名が発表を行いました。iOSDC Japan 2023 day2 で 「メルカリ10年間のiOS開発の歩み」 というタイトルでメルカリの10年間のiOS開発の変遷について40分のトークを行いました。このブログでは、補足情報としてトークをしようと思ったきっかけ、時間の都合上トークには盛り込めなかった10年の歴史の調査方法についてご紹介します。 もう一名の登壇者である @lestrrat は欠席により空いてしまった LT に代打枠で登壇し、サワードウ(パン)について発表を行いました。サワードウはiOS関連技術とは関係がないのですが、当日 LT で欠員が発生してしまい、 iOSDC Japan 主催者の長谷川さんからのリクエストで当日急ピッチで準備を行って発表を行いました。 急遽準備を行ったこともあり、機材トラブルでスライドなしで LT を行いました。投影したかった スライドはこちら です。 お聴きになった皆さんは早速パンを焼いているでしょうか? トークについて 「メルカリ10年間のiOS開発の歩み」 ではタイトルの通り、メルカリの10年間のiOSアプリ開発の歴史を振り返りました。 発表資料はこちら です。 初期のスライドは200枚を超えていましたが、内容を削ぎ落として140枚ほどのスライド数に落ち着きました。トーク時間も本番では40分ぴったりで終えることができました。 CfPを出そうと思ったきっかけ 今回この内容でCfP(Call for Proposal)を出そうと思ったきっかけは、もちろんメルカリが10周年を迎えたことが理由の一つです。メルカリ社内でも10周年を祝う企画が内外で多々行われていますが、エンジニアリングとしての社史を残し、10年続くサービスの移り変わりを外部に公開することでコミュニティに貢献したいと考えました。 自分は2016年に入社してからメルカリのフリマ事業にずっと関わってきたわけではないのですが、メルカリAppはもちろん、新規事業も含め幅広く携わってきたので全体感を持ってトークを構築できるのではないかと考えました。 ※ メルカリ本体での開発はもちろん、iOS Re-architecture の推進、メルペイ立ち上げサポート、リリースフローの整備、子会社での複数の新規事業開発(メルカリ アッテ、メルカリ カウル、メルカリ Shops)、iOS Architect チームの Director などを行ってきました もう一つの理由は、トークの中でも触れた10年近く事業を支えてきた初代メルカリiOSリポジトリのアーカイブでした。 メルカリは去年 GroundUP というアプリをゼロから書き直すプロジェクトを完了 させ、今年アーカイブを実施しました。このリポジトリを通じてたくさんの人と働いてきたという個人的な思い出もあり感傷的な気持ちになりました。 10年の開発の歴史を40分のトークにまとめるにはかなりの時間と労力を要するだろうとは思っていたのですが、実行に踏み切れたのはそんな思いがあったからです。 実際、6月後半くらいからトークのアウトラインを考え始め、調査に2週間、スライドにまとめ、最終的に公開された状態にまで仕上げるのにさらに1ヶ月近くを要しました。 トークに含められなかったこと メルカリのiOSアプリ開発と一口に言っても、この10年間で本体のフリマアプリ以外にも多種多様なアプリを立ち上げてきています。残念ながら今回の資料には入れられなかったアプリもあったのですが、この10年で行ってきた主なチャレンジをカバーできていると思います。 また、社内には歴史的経緯を知っている人たちも少なくなってきています。特にiOSアプリ開発に深く関わってきたなかでは自分が一番長く在籍しているという状況だったこともあり、様々なツールを使って調査を行いました。 トークでは調査の方法について触れる時間がなかったため割愛しましたが、実際に使った調査手法をスライドの56ページから62ページにまとめているのでご興味があれば御覧ください。 おわりに たくさんの興味深いトークが共有され、他の参加者やスポンサーの方々と直接コミュニケーションを取れる貴重な機会でした! メルカリとしては第一回から8年連続の8回目の iOSDC Japan スポンサーとなりましたが、これからも引き続き技術コミュニティへ貢献を続けていきたいと思っています。 スタッフの皆さん、参加者の皆さん、スピーカーの皆さん、お疲れ様でした!また来年お会いできることを楽しみにしています! メルカリはiOSエンジニアを募集しています!もしメルカリに興味を持っていただけたらぜひこちらもご覧ください! https://apply.workable.com/mercari/j/AEA2A632A9/ https://apply.workable.com/mercari/j/5EFBF06F3B/ https://apply.workable.com/mercari/j/79482261D5/ もちろんサワードウ(パン)を焼いてみた、という報告もお待ちしています。
株式会社メルカリ
2023/09/08
キャリアの明文化から3年間、どんな変化が? Engineering Ladderの活用と改善
こんにちは、メルカリ Engineering Office チームの@yuki.tです。 私たちのチームでは、しなやかで強固なエンジニアリング組織を作ることをミッションに、様々な活動を行なっています。私はその中でも、主にエンジニア評価のサポートに携わっています。 メルカリでは、約3年前にEngineernig Ladderとして、メルカリのエンジニアに期待される行動を成長段階ごとに明文化したものを作成しました。Engineering Ladderは主にエンジニアの評価や目標設定に使われています。 この記事では、Engineering Ladderが作成されてから3年間でどのように活用・改善され、どのような影響があったかをまとめます。 評価・等級制度の作成や、エンジニアの組織作りに携わっている方にぜひ読んでいただきたいです。 Engineering Ladderとは 一般的にキャリアラダー等と呼ばれている、職務に必要なスキルを明確にするための仕組みです。等級制度と紐付け、各等級ごとに求められるスキルや行動を定義し使用されていることが多いです。 エンジニア向けには海外の事例が多く、Spotify、Medium、CircleCI、Google、Dropbox社などで利用されており、外部公開している企業もあります。 最近では国内でもキャリアラダーを公開する企業が増えてきました。 メルカリでは、 3つのバリュー (Go Bold, All for One, Be a Pro)をベースにし、期待される行動を明文化したものを「Engineernig Ladder」と呼んでいます。 各エンジニアが持つ個性やスキルを尊重しながら、互いの強みを活かす組織を目指すために作られました。 Engineering Ladderは、評価や目標設定、キャリア設計で利用されており、今自分がどの段階にいて、次の段階に進むために必要な行動、スキルは何か、ということを確認するための指標となっています。 どのように使われているか メンバー自身の自己評価や、マネージャーからのfeedbackでEngineering Ladderを参照して使用しています。 会社全体で使われている等級制度(グレード定義)もありますが、すべての職種に使用できるように抽象度が高い内容のため、エンジニアの仕事に当てはめにくい場合があります。それに対して、Engineering Ladderはエンジニアの仕事に合致するように具体化した基準として位置づけられています。 Engineering Ladderのこれまでの改善と影響 1年目:Engineering Ladderの使用をスタート Engineering Ladderの作成後、まず評価での使用を開始しました。 開始後は「該当期間の成果を具体的に書けるようになった」や「評価のすり合わせができるようになり、納得感が上がった」という意見があり、ポジティブな影響がありました。 他にも、組織で期待されているエンジニア像を共有・発信するために、採用面接用のEngineering Ladderをベースにした質問項目も作られました。 メルカリでEngineering Ladderを作ることになったきっかけ、作成の過程、効果については、こちらの記事で詳しく説明されています。 参考記事: 会社の文化を言語化すると何が起こるのか。Engineering Ladderの作成プロセスとその結果 Continious feedbackの推進 Engineering Ladderの作成後、評価を助けるツールとして、Continuous feedbackという仕組みが推進されました。 Continuous feedbackは、評価時期だけでなく、1ヶ月等のより短いスパンでマネージャーとメンバーで認識をすり合わせる仕組みです。このときにEngineering Ladderを使って行動を振り返ることを推奨しています。 この仕組みを導入したところ、メンバーの評価への満足度が向上しました。 Continuous feedbackの効果を確認するためのSurvey結果 Continuous feedbackについてはこちらの記事で詳しく書かれています。 参考記事: 評価の満足度を劇的にあげた秘訣。Continuous Feedbackのすすめ これらのようにポジティブな影響が見られた一方で、Engineering Ladderの内容にはまだまだ下記のような課題がありました。 書かれている内容にわかりにくい部分がある 全社のバリューやグレード定義と完全に一致していないようにみえる 特に全社のグレード定義との整合性については、Engineering Ladderが作られた後に全社の定義が刷新されたという経緯があり、整合性が不完全な状況でした。 2年目:会社全体のグレード定義と合わせるためアップデート 前述の通り、作成時点のEngineering Ladderは会社全体のグレード定義の項目との整合性が不完全だったため、この年に構成と項目を大きく変更しました。 変更前:メルカリの3つのバリューを元にエンジニアリング組織で作成した項目 変更のためには、まず会社全体のグレード定義の項目を、エンジニア向けにさらに分解してあらたな項目(Key behaviors)を作成しました。 変更後:全社グレードから作成されたKey behaviors Key behaviorsを作成した理由は、抽象度の高いバリューを細分化してエンジニア向けに具体化することと、今後組織の求めるエンジニア像がアップデートされた際にKey behaviorsごとの差し替え・変更を可能とし、メンテナンス性を高めることでした。 Key behaviorsの作成後は、それまでのEngineering Ladderの文章を、関連するKey behaviorsに当てはめて再構成し、抽象度や記載内容のわかりにくい部分の修正など微調整を加えました。 このときのアップデートでは、すでに完成された文章がある状態から作成しましたが、もしゼロからキャリアラダーを作成する場合も、最初に項目を作成したうえで成長度合い(等級制度のグレード等)に応じて文章を作っていくことができます。 そして完成されたEngineering Ladderが、 現在公開されている内容 です。 (このあとも部分的に更新されているため細かい文言は当時から変更されています。) バージョンアップ前のEngineering Ladder(社内公開用) ※3つのバリューをベースに作られたものの、関係性は示されていませんでした バージョンアップ後のEngineering Ladder(社内公開用) ※内容の改善と併せて、3つのバリューとの関係性をわかりやすくして公開しました このアップデート前は、会社全体のグレード定義とEngineering Ladderの整合性が不完全だったため、エンジニアリング組織は独自の評価記入フォーマットを使う必要がありました。それが改善されたことで、エンジニアリング組織も会社全体と同じ評価記入フォーマットが使えるようになりました。 3年目:使用する組織が増え、幅広く影響力を持つツールに Engineering Ladderは、作成直後はメルカリのエンジニアリング組織だけで使用開始しましたが、年を追うごとにグループ内で使用する組織が増え、現在はカンパニーを跨いでグループ内のエンジニア組織で広く使用されています。 社内での閲覧数の推移 またメルカリではEngineering Ladderを社内のGitHubで管理しており、Issueの起票だけでなく、各メンバーが直接Pull Requestを出して、コントリビューションできるようにしています。 Engineering Ladderの内容に疑問や、改善点を見つけた場合に、それらをメンバー自身が解決できるという仕組みです。Pull Requestの内容はEngineering Ladderのプロジェクトメンバーがレビューしたうえで半年に一度Releaseされます。 公開後のコントリビューション数をみると、公開直後はCommit数が多いですが、改善を繰り返すうちにCommit数が減っています。 (2022年12月と2023年6月に大きな山がありますが、これは半年に一度行われている、プロジェクトメンバーによる定期アップデートのCommitです) コントリビューション数の推移 各組織からのFeedback 各組織からは、主に下記のようなFeedbackが得られています。 組織全体で評価の認識を揃えることと、納得感の向上に繋がっています。 評価される行動が言語化されているので、メンバーを評価しやすくなった 個人ではなく行動の評価であることが評価時にメンバーへ伝えやすい メンバーへの説明だけでなく、マネージャー同士の認識も揃えることができる メンバーとマネージャーで共通認識を持つことで、評価の納得感が高くなった メンバーの行動をEngineering Ladderに当てはめて次のグレードとのギャップを埋めることで、目標設定に活用できる 今後について 今後は、Engineering Ladderにある、Engineering Manager Skillsの改善をしつつ、 エンジニアリング組織のVision との連携をより強固にしていき、組織の方向性を伝えるツールとしてより役立てることを検討しています。これまでは主にメンバーやマネージャーからのFeedbackや、GituHub上のIssue・Pull requestからの改善が中心だったところを、組織の変化に応じたメッセージを伝える場としても使っていくという意図です。 またEngineering Ladderを重要視しすぎると、特に入社したばかりのメンバーはEngineering Ladderの内容が全てだと考えてしまう恐れがあるため、Engineering Ladderを使うことで根底にあるメルカリのカルチャーを各メンバーが理解して体現できることも目指していきたいと考えています。 社外への影響 最後に社外への影響についてです。メルカリで公開しているEngineering Ladderは Creative Commons Zero(CC0) を適用しているため、他社様が自社でキャリアラダーを作成する際に参考にしていただくこともあります。 他社様におけるキャリアラダーの導入事例 最近では、メルカリのEngineering Ladderを参考に株式会社LegalOn Technologies様が自社の評価基準を作成されたとご連絡をいただきました。 新しい基準の作成後は、評価がしやすくなったり、会社としての方向性が定まったことによるポジティブな影響が得られたそうです。 詳細については、 株式会社LegalOn Technologies様のブログ でご紹介されています。 まとめ この記事では、メルカリのEngineering Ladderについて、社内での活用方法や、作成後にどんな改善が行われ、どのような影響があったかをまとめました。 Engineering Ladderは公開後も会社の状況に応じて内容や使い方の更新を続けることで、より使いやすく改善されています。そして特に評価の納得感の向上に貢献しています。 現在ではメルカリのグループ会社や、他社様からも参照していただいています。 この記事で紹介したEngineering Ladder以外にも、メルカリでの開発者体験やカルチャーにご興味がある方は、ぜひキャリアサイトをご覧ください。 Mercari Careers
株式会社メルカリ
2023/08/23
アンケート疲れから考えるフィードバック獲得の改善方法
要約 ビジネス環境においてフィードバックを得るのは簡単なことではないかもしれません。その点、アンケートは良い方法のように思えますが、期待どおりの結果を得るには、注意しなければならないことがあります。 アンケートから得たいことを明確にしましょう – アンケートは良い投票システムとは言えません。後で結果を返すようにしないと、回答者はアンケートでフィードバックを返すのをやめてしまいます。 一般に、多くのアンケートは回答者を疲れさせてしまいがちで、その結果、チャンスを失っています。また、私が「survey blindness(アンケートによる盲目化)」と呼んでいる現象があります。回答者はあまりに多くのアンケートを目にするために、どれに答えたかわからなくなり、アンケートに答え損ねてしまうのです。 より手っ取り早くてもっといい方法として、個人や小グループの対象者と対面で話をするという方法があります。 私たちの経験から、回答者は、アンケートによってどのような変化が促進されるのかを理解すると、アンケートに対する認識が高まるということがわかりました。 はじめに 「アンケートから役に立つ情報は得られているか?」 数ヵ月前、私たちのチームはこのような問いかけを始めました。業務上、私たちは多くのアンケートを行っています。毎回の全社会議やその他の大きな集まり、イベントなどではそれぞれ独自のアンケートを行っていました。 私たちのような比較的小さなチームでさえ、多くのアンケートを担当していました。「フィードバックフォーム」と呼ぶこともありましたが、これらは見た目も中身も基本的にはアンケートと同じでした。 時には、返ってくるアンケートの数がイベントの人気を測る指標の1つだと考えたりしたものです。けれども、そうではないことがよくあるということもわかりました。返ってきたアンケートの数がイベントの良し悪しと無関係ということもよくあります。 私は手始めに、アンケートについて十分に考察するために、その過程、設計方法、目標、アンケートで収集した情報をどのように活用したかについてチームに尋ねてみました。 さまざまな発見がありました。 始めに言っておきますが、すべてのアンケートが悪いわけではありません。私たちの場合、まるでアンケートという立派なハンマーに、釘のようにたくさんのやり取りや「フィードバック」を必要とする質問が用意されているかのような状態になっていたということです。 私がこのことに疑問を感じるようになったのは、単純に会話で「アンケート」という言葉を聞いた人の反応からです。あきれてうんざりというのが大抵の反応でした。また、大きなイベントのアンケート回答率が1桁だったり、大規模なアンケート調査で自由回答欄には何も書かれていないということも何度かありました。こうしたことから、アンケートは効果的な投票システムではないという論点も見えてきました。 これは明らかに、間違った使い方をしているか、使い過ぎかの徴候です。 釘とハンマーのどちらが先だったのかはわかりません。おそらく、Googleフォームを見つけた誰かが、オンボーディングセッションに対するみんなの感想を知りたいと頼まれてアンケートを作成し、それが毎月のように使われるようになったといったところでしょう。 最近では、ご存じのように新型コロナウイルス感染症の拡大によって多くの人が2年以上も在宅勤務をすることになり、気軽に会って誰かの意見を聞くことや、雰囲気を察することが急に難しくなったため、ミーティングやイベントがうまくいったのか、どのような点を改善すればよいのかなどを知るために、簡単な質問をするのはいい考えだと思われるようになったのです。 私たちはまた、アンケートをイベントの人気や満足度を推測するKPI(重要業績評価指標)として使い始めました。これは、ある種の投票システムとして提出されるアンケートフォームの数を評価するのと非常に近い意味合いもあります。 設計 こうした多くのアンケートに最後まで回答し、実際にクリックしてたくさんのアンケートに答えてきた結果、私は「このアンケートはどのように使われるのだろう?」「責任者は誰なのだろう?」「どうしてこの情報が必要なのだろう?」「私のコメントはどうなるのだろう?」などと考えるようになりました。 この答えはすぐにはまったくわかりませんでした。自分たちのチームが担当するアンケートに関してさえもです。フィードバックに対してどのような対応ができるのかも、それをアンケートに答えてくれた人にどのようにして伝えればいいのかも、そもそもわかりませんでした。 私たちが質問していたのは、イベントは役に立ったか、長すぎなかったか、短すぎなかったか、テーマは興味のあるものだったかなどです。 よく使ったのが1から5までのスケールでの評価です。1が「役に立たなかった」、5が「非常に先進的だった」などです。多くの評価システムと同じように、この方法も結果を歪める傾向にありました。特に記名式の場合は、4か5の評価がほとんどでした。 自由回答欄がある場合でも記入されていないことがほとんどで、得られたフィードバックの大半の理由はわかりませんでした。 また、質問はかなり一般的なものだったので、しばらくすると似たようなフォームはすべて渾然一体となっていきました。 もちろん、フォーム作成ソフトは、星や「非常に役に立った」から「まったく役に立たなかった」までのスケールがテンプレートになっているものも多く、このスタイルに適した設計になっていることもあります。また、私たちはたくさん質問をするほど粒度の高い情報が得られると考えてしまうことがあります。けれども、必ずしもそうではありません。 アンケートを行ったり、フィードバックが欲しい理由は無限にあり、テーマも多種多様です。ですから、設計に絶対的な正解や不正解はありません。けれども、より良いものにすることができることはわかっていました。 どのように見えるとしても、アンケートは双方向ツールだということに私たちは気が付きました。質の高い情報を手に入れたい場合は、プロセス全体をより良いものにするために、私たちも情報を提供する必要があったのです。 より良いものにするために、基本的なレベルで回答者に次のことを理解してもらうようにする必要がありました。 アンケートへの記入を求める理由。 誰のためのアンケートか。 情報の使い道。 アンケートの結果実施したことに対するフィードバックはいつ、どのように提供されるのか。 私たちは欲しいデータの価値と、それに対する行動をどのように計画するかを検討することから始めました。 例えば、研修セミナーであれば、「長すぎましたか?」と尋ねるより、 「説明の時間は、システムについてよく理解するのに十分でしたか?」と尋ねたり、 「講師の[マイクロサービス]、[クラウドインテグレーション]、[セキュリティ要素]についての説明は短すぎたり長すぎたりしましたか?」と尋ねるほうが効果的かもしれません。 一般的な質問をする代わりに、よりイベントに合わせた質問をし、それ以外のことは自由回答欄で拾うようにするべきです。 定期的なイベントの場合、これは明らかなことかもしれません。そう考えると、このようにしてより良いデータを手に入れない理由などあるでしょうか?ここで注意しなければならないことがあります。繰り返されるイベントから再現可能なデータを得たい場合は、おそらく、年間を通して、中心となる質問とセッションごとの具体的な質問を用意する必要があります。 話をする 同じ時期に、開発者体験の一環として、私たちはエンジニアリングマネージャー(EM)一人ひとりと30分間、事前に内容をほとんど決めることなく話し合いを行うことを決め、これを「Outreach and Visibility(見える化)」プロジェクトと呼びました。 このプロセスを始めてまもなく、EMもアンケートのことが気になっているのだということがわかりました。 「なぜこんなに多くのアンケートをするのか?」という質問も多かったのですが、一番多かった質問は、「こうしたアンケートによってどのような変化が促進されたのか?」というものでした。 これは私たちの感覚とも重なる部分がありました。多くのアンケートを実施しましたが、伝達方法の変化についてはどうだったでしょうか。私たちは実際に多くの社内サービスを改善しました。アップデートし、改善し、必要ないものは廃止しました。では、何が食い違っていたのでしょうか。私たちは、熱心にアンケートを送り、結果について調べ、分析し、その結果も回答者に送ってきました。けれども、その結果、何を変えたのかは伝えてこなかったのです。 多くの場合、とても単純なことでした。なぜ変更したのかを伝えてこなかったのです。変更した理由がフィードバックやアンケートによるものであっても、そのことを回答者に伝えていなかったわけです。この点を変える必要がありました。プレゼンテーションの終わりやSlackチャンネルで例を挙げるときに、この話にもっと触れなければならなかったのです。フィードバックへの感謝が必要でした。ここから私たちは、Engineering Ladderにアップデートを示す方法をより明確にするようにしました。 また、定期的な「Outreach and Visibility(見える化)」の話し合いは好評だったため、継続してさらにフィードバックを集め、懸念に耳を傾け、その中で、得られたフィードバックから行っていることを伝えたり、改善点を示したりもしています。同時に、フィードバックフォームのいくつかを廃止し、Slackで直接フィードバックするよう勧めています。 おわりに ビジネスから情報を得ることは、動きの速い業界では非常に重要です。アンケートはこのために有効なツールですが、他のツールと同じように、それぞれの課題ごとに正しく設計して使う必要があります。1種類ですべてを済まそうとすればエンドユーザは疲弊し、フィードバックの質が低下してしまいます。 究極的には、話をするという選択肢は常にあります。このハイブリッドなビジネスの世界で、それはテレビ会議で行われるかもしれませんし、オフィスで行われるかもしれません。1対1で行われるかもしれませんし、小グループで行われるかもしれません。けれども、それはいつでも可能です。 どのような方法を選ぶとしても、回答者に、その回答のおかげで改善がなされたのだということを説明し、この循環を完結させることが不可欠なのです。
株式会社メルカリ
1
More pages
11
12
13
14
コンテンツ
トップ
イベント
マガジン
ブログ
グループに関するお問い合わせ