株式会社メルカリのブログ - TECH PLAY

TECH PLAY

株式会社メルカリ

株式会社メルカリ の技術ブログ

296

Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 メルペイMLにおける品質保証とリスク管理 」の書き起こしです。 @shuuk:みなさんこんにちは。それでは「メルペイMLにおける品質保証とリスク管理」の発表を始めます。よろしくお願いいたします。 それではまず、私たちの自己紹介をします。まず私は、Shu Kojimaといいまして、Slacknameは@shuukとなっております。元々は受託開発でWebエンジニアをしておりましてその後、株式会社ALBERTというところで、データサイエンティストを経て、データアナリストとしてメルペイに入社しました。 その後は、MLエンジニアにジョブチェンジをして、現在は不正検知のMLを扱うFraud Prevention Teamでマネージャーをしています。本日はよろしくお願いいたします。 @yukis:Yuki Saitoと申します。メルペイでシステムリスクセキュリティのDivisionのディレクターを務めております。私自身はもともと新卒で大手の精密機器メーカーでネットワークエンジニアとして働いていました。 あまりにも金融事業をやりたくて、金融ベンチャーに飛び込んでそこからは金融事業をやっていく上でのIT周りだとかリスク管理を責任者としてやっていました。システムコンサルも挟んで現職に至ります。よろしくお願いします。 @haruki:Haruki Kanekoと申します。メルペイではリスク管理チームのマネージャーをやっております。キャリアとしては信用リスク管理一筋で、最初の頃は銀行系のカードローン会社、それからベトナムのハノイに駐在して、ノンバンクでリスク管理をやっていたり、直近ですとドイツ車メーカーの個人向けローンに関するスコアリングモデルの開発や与信戦略の立案、規制対応を経て、2021年からメルペイのリスクチームにジョインしています。本日はよろしくお願いいたします。 @shuuk:それでは早速始めていきます。まず、概要を説明させてください。私たちメルペイでは、与信と不正検知の領域でMLを活用しております。Fintechでは求めるリスク管理の基準も非常に高いので、品質を担保するためにルールやフローの整備を今まで進めてきました。 中でも現場のスピード感と品質を両立するなど、いろいろと悩みがあったので、そこにどう折り合いをつけたのかを今日はお話できればいいかなと思っております。 ではまず、最初冒頭数分程度で前提となる知識をご紹介して、その後パネルディスカッション形式でお話しします。まずは弊社のMLシステムの紹介を簡単にします。 一つ目が、与信のMLのシステムで、こちらは過去のお客さまの取引の情報から将来の貸し倒れの確立を予測して、メルカードなどの後払い系のサービスの利用限度額を決定することをミッションにしたものになっています。 そしてもう一つの柱が不正検知です。こちらは不正な動きをしている人とかトランザクションを検知することに機械学習を用いております。 ではここからメルペイにおけるリスク管理の全体像に関して@harukiさんから説明をお願いいたします。 @haruki:まず、メルペイにおけるリスク管理の全体像について説明します。お客さまのお金を取り扱うFintechでは、プロダクトにも当然高い品質が求められます。またインシデントや障害を起こしてしまうと、監督官庁、具体的には経済産業省や、金融庁への説明責任も発生してしまうという背景がございます。 特に当社メルペイの強みの一つでもあるのですが、メルペイは認定包括信用購入あっせん業の認定を日本で初めて獲得、これによって、MLモデルによって、分割払いやクレジットカードにおけるお客さまの利用限度額を算出することができております。 その分このMLシステムが想定外の挙動を起こさないように、きちんとリスク管理を行う必要性があります。 参考記事: メルペイ、事業者として第1号となる「認定包括信用購入あっせん業者」の認定を取得 金融機関における一般的なガバナンスの体制についてご説明したいと思います。こちらをThree Lines Modelと呼んでいます。 一番左側のプロダクトマネージャーやエンジニアなど、お客さまに対して製品やサービスを提供する部署を第1線とし、真ん中のリスク管理の立場から客観的に第1線を支援する部署を第2線としています。社内の最後の砦として、内部監査室を第3線としています。社内の役割を分けることで、ガバナンス体制を強化するという目的があります。 真ん中の第2線ですと、リスク、リーガル、コンプライアンスなどのチームがあり、私のリスク管理の立場からでは、信用リスク管理上の観点からMLチームのエンジニアの検証結果に関してダブルチェックを行ったり、第2線の立場から異なる視点で検証してみたりと、第1線部署と綿密にコミュニケーションしつつ多角的に評価して、安心安全なプロダクトを世の中に送り出すというのがミッションになります。 第2線はリスクを軽減するために、そのルールや社内規定、マニュアル、ポリシーといったドキュメント類を第1線と共同で作っていくというのが重要なミッションでございます。 本日お話したいのが、メルペイのML領域において、このルールがあまり明確には存在していなかったので、これを作りました。 @shuuk:私の方からMLにおけるリスクが2種類あるというお話をさせていただきます。 MLには「システムリスク」と「モデルリスク」という大きく二つのリスク管理の考え方が並列して存在しております。システムリスクとは、システムの想定外の挙動によるリスクで、例えばアプリが停止したり第三者にのっとられたりといったものを想定しています。 モデルリスクはモデルの想定外の挙動によるリスクで、貸倒率や不正な取引の確率の予測精度が下がって結果的に事業損失が出ることを想定してます。 想定しているロジックも違っていて、システムリスクは基本ルールベースを想定していますが、モデルリスクはブラックボックスアルゴリズム(AI)を想定しています。 リスクを低減する具体的な方法も違っていて、システムリスクの場合は開発チームから独立したQAチームが、QAを実施することが基本的な方法の一つになります。モデルリスクの方は、どちらかというとビジネス指標の確認やML精度指標の確認、リリース前後のバックテストモニタリングなどを手法としております。 ここからディスカッションパートに入ります。 @haruki:メルペイでどういったモデルを使っているかや、ガバナンスの体制、システムリスク・モデルリスクについてご説明させていただきましたが、私からシステムリスクについていろいろお伺いしたいです。ですけれども、このMLのシステムリスクを考える上で、QAをどうするかが問題としては大きかったと思います。当時はどういった議論があったのでしょうか? @yukis:QAに限らずシステムリスクの規定というと堅いのですが、ポリシーを考える上でI TGCと言われるIT全般統制の中で、特にQAの領域は、開発者とは独立した組織によってクオリティアシュアランスをするという組織上の権限分離が行われたもので、統制・ルール整備をするのが正攻法です。メルペイももちろんそういうポリシーとして定めています。 一方でそれは、開発者と違ったナレッジを持っている組織であったとしても、ルールベースのロジックをベースにして、クオリティアシュアランスが可能であることを前提としたルール・統制となっています。 ここはMLの領域にまるっと適用するのはあまり現実的ではないということが、課題としては大きかったです。 @shuuk:MLはルールベースみたいにテストケースを作成するのは難しくて、一応不確実性のあるものをQAする方法もいろいろ提案されてはいるものの、まだまだ発展途上の段階だと思います。しかもそれをQAチームに第三者としてやってもらうのは、現実的ではないとは思っていました。 @haruki:そういった難しさがある中で、社内で合意形成していくのは大変だと思うのですが、当時はどのようにして合意形成したのですか。 @shuuk:最初は無邪気に「モデル部分のQAが難しいので除外できませんか」と経営陣にも提案をしていましたね。ただ、「品質保証を何もやらなくていいんですか」という話は当然ありまして、回答に悩みました。 @yukis:僕も同じで、モデルの部分の正しさや、間違い・不正が介在した場合というときの事業インパクトを考えると、誰も「品質保証をしなくていい」とは経営陣は言わないということは、おっしゃる通りだと思います。 でも、それを汎用的なルールとしてあてがうより、例外的にどのようなポリシーで進めるのが良いかを考えました。 そもそも独立したQA組織による品質保証をなぜ正攻法でやりがちなのかというと、原点に立ち返ったときに、基本的には開発者自らが品質保証をやってもいいのですが、組織として見たときに、開発者自らが品質保証を怠ってしまったり、脆弱性や不正なソースコードを埋め込んでしまうリスクがあります。第三者的にそのリスクがないことを説明しなければならないとき、開発者とは独立した部隊(QA)がアシュアランスをしているのは効率的なんです。 必ずしも第三者がやる必要がない一方で、第三者による品質保証が困難となった場合、それでも第三者がやらなきゃいけないとなると、それ自体がそもそも品質保証低下につながってしまう可能性があるので、そういったポリシーはむしろ不適当です。 代替的なガバナンスは、今のメルペイのプロダクトの性質や組織の性質を考えたときにどうすべきかを柔軟に検討する必要性があったと思います。そこをMLチーム・ITリスクチームと試行錯誤してきました。 @shuuk:代替的なガバナンスという考え方はすごい鍵だったと思います。当時はまだモデルリスクという考え方を社内でそこまで持ってなくて、システムリスクだけが先にありましたが、システムリスクで保証しきれないときに、モデルリスクという新しい品質保証の柱を立ち上げて、ブラックボックス的なものはモデルリスクで見ましょうという線引きがなされました。 具体的には、バグを全部片っ端からQAするより、結果として出てくる事業KPI影響のバックテストやモニタリングを事業リスクをみている第2線の方と一緒に指差し確認することをルール化することで、変なモデルが世の中に出ないことを、担保できるという結論になりました。 @yukis:マクロ的にそう見たときにも違和感はなくて、世の中的にもグローバルな標準規格では代替的なコントロールをどう定義するかは世の中のポリシー的にも結構出てきています。 QAって大量のシステム分岐をあらゆる観点をチェックして問題がないかを確認すること自体が目的ではなく、クリティカルなバグを見つけ出すことができていれば良いと思っています。事業サイドとの合意形成によってクリティカルなバグを見つけて修正するプロセス自体は、良いアプローチの一つだったんじゃないかなと個人的には思っております。 @haruki:従来の品質保証の定義ややり方では対応できず、モデルリスク・システムリスクと切り分けて対応しました。いろいろあったと思うのですが、他にはどんな課題がありましたか。 @shuuk:もうひとつの論点として、ブラックボックスは杓子定規にQAをしないと決まったとして、ルールベースの処理を全部QAするのかという話はありました。 MLシステムといってもブラックボックスのアルゴリズムって実はほんの一部で、ルールベースの処理の方がむしろたくさんあります。それを全部QAチームに依頼するのかと考えたときに、開発スピードは正直当然落ちてしまいます。 また、コストと効果が見合うのかも考えなければなりませんでした。例えば特徴量重要度が最下位の特徴量の品質保証を第三者がめちゃくちゃ頑張ったとして、大幅にリスクが減るのかという話があがりました。 @haruki:そうですよね。MLモデルだと多量の特徴量を使って、判別力や頑健性を上げていこうというものですので、網羅的に一つ一つやっていたらきりがなくなってしまいますよね。その辺りはどのように折り合いをつけたのでしょうか? @shuuk:モデルリスクとシステムリスクの境界を工程別に分けました。スライドの通り、私たちの利用している教師あり学習は基本的には何らかの確率値を出しています。確率値の後処理を誤ると、例えば利用限度額を誤ってしまうなどの直接的にプロダクトに影響があります。そのため、ここはQAをしようという話になりました。 一方、前処理や特徴量がバグっていたとして、最終的には確率値の精度に吸収されます。よってここはモデルリスクで吸収をして、事業KPIの影響を見た上で品質を保証する形になりました。 ただそもそも、バッチが動いてないとか、システムとして何も動いてないという話は普通にシステムリスクでやるという線引きをして、QAの負担を最小限にしつつ品質保証する形にしました。 @yukis:かなりいろいろ考えさせられたトピックでした。モデルリスクとシステムリスクそれぞれ定義にまで立ち戻って考えました。 システムリスクは予期せぬコンピューターダウンや不正によってコンピュータが誤作動してしまうことをいいます。一方でモデルリスクはシステムリスクとは違うような特性を持っています。 この場合、それぞれのリスクを担保するための保証が何かというと、システムリスクは同じテストケースと同じアプローチで品質保証すると、何度やっても同じ結果になりますが、一方でモデルリスクにおける品質保証はアノマリーを検知してそこから改善してビジネスとして適切なモデルとしていくことだと個人的に感じています。 「一定の理論・法則に基づいて合理的に説明できないけど何かおかしい結果である」という状態を改善するのが、モデルリスク上の品質保証だと思います。一般的な他のドメインでしているようなQAという考え方に当てはめるのは違うと個人的には思っています。 セキュリティの振る舞い検知的な話にも近いと思います、特定の挙動的にはOKだけど、特定の挙動がある時間帯で連続したり、特定の挙動の後にこの挙動が起こると明らかにおかしくなるといったことと似ていると思います。 @yukis:続いて、メルペイでのモデルのリスク管理をきちんと定めるようになったきっかけについて聞かせてください。 @haruki:まず、メルペイが置かれてる状況として、業界として歴史あるクレジットカードた分割払いといった社会的な重要性が高く、割賦販売法という厳格な法律に基づいて、与信管理が求められているというのがあります。 一方で、我々のAI与信ライセンスを、国内で唯一経産省から認められてまして、MLのモデルでお客さまの利用限度額を独自にモデルで算出できる点で、非常に柔軟性高い一方で、品質には配慮しなきゃいけないという背景があります。 @shuuk:MLの出力によって自由に決められることは、責任が増えるということでもあります。MLエンジニアとしても、基準を満たしていく必要があるので、変な精度のモデルをデプロイしてお客さまを混乱させないように、緊張感のある開発を行っています。 @yukis:高い要求水準の中で実際には当初からその要求水準を満たせていたんですよね。 @haruki:数年前はいろいろと難しい局面もありました。例えば与信戦略の変更で、当時は意思決定が属人的で、一部のお客さまの与信を上げた際に、スコアの想定値を上回る延滞率なってしまって、これで追加調査を求められたり、与信戦略を戻さないといけないといったことがありました。 常にバッファを設けて貸倒率・延滞率はコントロールしていますが、モデルの挙動が想定外になると財務的な損失が一気に出てしまうので、非常にセンシティブだと思います。 @shuuk:当時もビジネスサイドと会話しながら要求品質と決めてたのですが、ポリシーとして明文化されてないので意思決定が属人的になっていたことは、当時振り返ると否めないです。 また、見る指標もいわゆるAUCといったMLエンジニアが見るような人が中心だったので、それが具体的にビジネスにどれぐらい影響があるのかがわかりづらいということもありました。 @yukis:その後、より品質高く与信を運用していくためにどういうフローを構築していったのかを聞きたいです。 @haruki:モデルの整理やトリガーになるイベント、開発の工数、モニタリング項目、有識者が会議体で決議できるように可視化することが必要でした。 お客さまの与信という社会の生活を密接に関わるものを取り扱っておますので、MLモデル実装後、AUCだけでなく、ビジネス上のKPI、例えば、想定延滞率と実績延滞率の乖離をきちんと見るように意識したというのが大きいです。 なお、整備したルールは、作って終わりではなく、MLチームと一緒にどうしたらこれを浸透させられるかを考えたり、チェックリストを作ってガバナンスを浸透させていくことは、今も継続議論しています。引き続き安心安全なプロダクトをリリースするために、一緒に頑張っていきたいなと思っています。 参考記事: 与信モデル更新マニュアルを作成した話 それでは、ご視聴ありがとうございました。
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 日本におけるお客さま本人確認と今後の技術的課題 」の書き起こしです。 @tim:みなさん、こんにちは。このセッションでは、「日本におけるお客さま本人確認と今後の技術的課題」についてお話しします。 @tim:Tim Tosiです。私はフランス、イギリス、そして日本で仕事をしてきました。フランスのパリ出身です。私はメルペイに入社する前、いろんな業界を経験し2020年の1月にメルペイに入社しました。KYCチームのバックエンドエンジニアから始まり、2021年3月からはKYCチームのEMをしています。 @mann:こんにちは。Manpreetと申します。私はバックエンドのソフトウェアエンジニアとしてメルペイに勤めています。 元々はインドでキャリアをスタートし、銀行、通信、eコマースでの経験があります。2019年頭に日本に引っ越しました。2021年10月にメルペイに入社し、KYCチームのバックエンドエンジニアとして勤めています。 @chris:みなさん、こんにちは。Christopheと申します。私は2014年に来日しました。最初は通信、ビッグデータに勤めて、2021年にメルペイに入社し、KYCのテックリードとしてバックエンドエンジニアをしています。 @chris:まずは、eKYC関連の法律が出る前に、日本での本人確認がどのように行われてきたかお話しします。 eKYCへの前に知られていたのが、本人確認法です。これは2008年に犯罪収益移転防止法に変わりました。引き続き、組織犯罪処罰法、麻薬特例法が今でも継続しています。簡単に最初の法律だけに焦点を当てて話をします。 まず、再犯罪防止という意味で、条約に基づきFATFがプロセスを制定したもので、口座開設時、大口取引時の本人確認の実施などが義務付けられています。 2001年にFATFはテロ資金供与に関する特別勧告を発表し、2006年末までに1000米ドルまたは1000ユーロを超える現金供与の本人確認を義務付けるように求めました。これを受けて日本では10万円を超える現金供与における本人確認を義務付ける条文を追加し、2007年1月4日に発効しました。 日本では、2000年代に入ってから、携帯電話や電子メールを利用して詐欺行為を行う架空請求詐欺や特殊詐欺が社会問題化しており、これらの犯罪で騙し取った金銭を安全に受け取る手段として架空口座を利用することがあります。この法律の目的は金融機関と取引する際にお客さまの身元を確認することで、偽名・なりすまし取引による資金獲得を防止することです。 より具体的に、どういうときにお客さまを特定すべきかというと、三つの要素があります。 まず一つ目は、金融機関と取引を開始するときです。例えば口座開設や信託取引の締結、保険契約の締結をする際です。二つ目は、10万円以上の取引がある場合、三つ目は、トラベラーチェックなどで200万円を超える場合です。 本人確認方法は、個人の場合、氏名・住所・生年月日が必要です。保険証や運転免許証、外国人在留カードを使うことが多くなっています。次に法人の場合、担当者は本人確認に加えて会社名と事務所の所在地が記載された証明書を提出する必要があります。 これらの情報を提供するとトランザクションが行われますが、本人確認が一度済めばこういった確認を提供する必要はありません。証明するためには金融機関の担当者に直接身分証明書を提示したり、パスワードや本人しか知らない情報を提供したりします。とはいえ、詐欺やなりすましの疑いがある場合、本人確認のプロセスを全てやり直す必要があります。 本人確認が行われた場合、取引時確認記録を作成し、金融機関が7年間保管しなければなりません。本人確認の要求にお客さまが応じない場合、金融機関が取引を行わないことを免除されます。 残念ながら、いくつか起きた問題をご紹介します。 最初に「学費」です。日本では大学入学金が10万円を超えることは珍しくありません。この法律が施行されたときTVや窓口には「指定された期日に納付するために、適切な身分証明書を持参するように」という注意書きが貼られました。 次が、預金詐欺です。例えば、お金を盗まれた原告が、「金融機関が適切な本人確認を行わなかった」と主張した訴訟があります。ですが裁判所はこの法律はマネーロンダリングを防止するものであり、預金詐欺を防止するためではないことから、金融機関は本人確認を進める必要はなかったと判断しました。 最後に、個人情報の収集です。この法律は、金融機関にしか適用しません。無関係の企業がこの法律を利用して、個人情報収集の目的でお客さまに個人情報を尋ねることがあります。また、勤務先や親族に関する情報など、無関係の情報を尋ねることで、さらに踏み込んだ情報を得ることもあります。 最終的にこの法律は2008年3月1日に廃止され、代わりに犯罪による収益の移転防止に関する法律が制定されました。 @mann:次のトピックはeKYCについてです。 eKYCとは、オンラインで本人確認を行う方法です。これまでとは異なり、お客さま自身が個人情報と身分証明書をシステムにアップロードします。 ここからは、特に日本におけるKYCにおける出来事をいくつか振り返ります。 1988年12月に 麻薬及び向精神薬の不正取引の防止に関する国際連合条約 が採択され、1989年7月に金融活動作業部会(FATF)が設立されました。これによってFATFと日本の総合評価において、日本では1992年7月に 麻薬特例法 、そして2000年2月に組織的犯罪処罰法、2003年1月に本人確認法が施行され、お客さまの本人確認と取引時確認記録の保存の義務が課せられました。 2007年3月に犯罪による収益の移転防止に関する法律が成立し、改正顧客識別法と組織的犯罪処罰法の一部という二つの法律に基づいて作られました。その後法改正が繰り返され、2018年には犯罪による収益の移転防止に関する法律施行規則の改正が行われました。 Fintechと相性の良い効率的な本人確認方法をいくつか挙げて、オンラインKYCを実現し、今日のKYCとeKYC対策を形作りました。 それを元に、なぜKYCを行うのか、なぜメルカリグループにKYCという部門があるのかについてご紹介をします。 本人確認は、犯罪収益移転防止法に準拠して実施されています。特定事業者が提供するソフトウェアにより、氏名、住所、生年月日、顔写真などを確認したり、書類の厚みを判別して改ざんされていないことを確認したりするなど、本人確認を目的とした画像データの利用が規定されました。 また、お客さまの利用目的や職業も確認しています。特に、特定事業者は取引時確認記録を作成し7年間保存しなくてはなりません。お客さまとの取引の中に疑わしい取引があれば規制当局に報告をする必要があります。 現在のAML(アンチマネーロンダリング)の体制は、この四つの目標を達成することにフォーカスしています。まず一つ目は、犯罪収益移転防止法の外為法に対応されており、2と3は主に組織的犯罪処罰法と麻薬特例法で対応してます。四つ目については、脅迫罪処罰法で対応し、外為法、国際テロリスト資産凍結法で対応しています。 これらの法律に加えて、金融情報センターで提供されるガイドラインでも対応していますし、AMLやCDD(Customer Due Diligence)について法令を遵守した運用を行うためのガイドラインも作られています。 ここではいくつか提供されているガイドラインについて紹介します。お客さまは本人確認を実施するときに、その場で写真撮影をし、偽造されていない画像データを提出する必要があります。 ここで受け入れられている身分証明書は、運転免許証やマイナンバーカード、在留カードなどです。 上のグラフのパーセンテージは昨年の割合で、eKYCの方法として45%のお客さまは運転免許証を選択しています。 身分証明書の正当性を確認するために、ガイドラインではドキュメントの厚さの確認をしています。例えば、写真を撮るときに傾けてもらうなどの方法をとっています。ライブネスチェックでは、お客さまにランダムなポーズを取ってもらっています。 最後に、本人確認書類の厚みなどを目視で確認します。改めて強調していきますが、特定事業者はお客さまの氏名、住所、生年月日、利用目的、職業を確認することが義務づけられています。 まずお客さまは在留カードやパスポートなど、書類のタイプを選択します。そして、お客さまが書類の画像データを提出します。書類の正当性が確認されます。そして、有効性チェックのためにお客さまはランダムなポーズを要求されます。お客さまは氏名、生年月日などの個人情報を入力します。そしてeKYCが提出され、合否が反映されるまで、通常約1週間かかります。 ICチップを使用するeKYCは、オンラインで本人確認を行います。これがまた別の方法となります。この方法では、ICチップに搭載されるデータを使用します。関連当局とお客さまの身元を確認しICチップを読み取ります。 メルカリでは、マイナンバーカードを利用しています。ICチップを読み取って、JPKIという公的個人認証サービスで電子署名を行っていきます。そして認証を行います。 金融庁のガイドラインによれば、在留期間のある外国人のお客さまについては、リスクに応じたCDD、eKYCを行う必要があります。口座が売買されていたり犯罪に利用されているおそれがあるからです。滞在期間の延長がこれ以上確認できない場合には、利用制限をかけるなど、適切なリスク対策を講じる必要があります。 外国人は、在留カードなどを使うことができます。また、氏名、住所などの基本情報に加えて、国籍、ビザの種類、在留期間を記入する必要があります。 @tim:メルペイのKYCチームは、ほとんどが外国人メンバーで構成されていますので、ネガティブな印象を持ちました。 実は新しい措置に関する潜在的な問題は、eKYCの受け止め方によって変わってきます。SNSを見てみるとネガティブに受け止めているのは、私たちだけではないようです。必ずしも不正対策そのものが問題ではなく、対策が新たに追加されることは、ほとんどの場合、お客さまの手間が増えることとなります。 政府機関も日本の企業も新たな詐欺対策を決定する際に、このことを念頭に置くということが重要です。 もう一つ私たちが強く考慮しなければならないのは、新しい脅威です。しばらく前からある強力な脅威の一つがディープフェイクテクノロジーです。これは、機械学習や人工知能のアルゴリズムを使って、写真、動画、音声トラックなどのメディアを操作し、人物をすり替えることです。 技術的なことについて私は専門外なので、このトピックに深く踏み込むことは避けたいと思っています。ただ、興味ある方々は調べていただければと思います。 私たちの申請記録であるビデオなどの資料は、身元確認に合格した人物が使用され、身元確認書類の使用者であることを確認するために手作業でチェックされます。 しかし、人間がディープフェイクを判定するのは、実際にはかなり難しいです。現在の法律で日本で期待されている本人確認に関しては本当の脅威となる技術が登場していることになります。日本がこの現実に合わせて規制を更新する必要があります。 特に反社会的勢力に関するヒントを与えたくないので、実際に話せないことがたくさんあります。十分に曖昧なままとなりますけれども、私たちは、2021年にこの問題の調査をパートナーである日本の大学とメルカリR4Dチームで共同チームを設立しました。 ディープフェイク技術が社内の本人確認フローを通過する可能性を調査しています。 社内の本人確認システムだけではなく、複数の方法で反社会的勢力と戦っています。 また、お客さまの行動を監視したり、アプリケーションの使用におけるパターンを検討することを行っています。 最近、マイナンバーカードに関するニュースを目にすることが多いかもしれません。マイナンバーカードに関わる法律の一部を改正することになりました。行政手続における特定の個人を識別するための番号として利用されることになります。( 行政手続における特定の個人を識別するための番号の利用等に関する法律等の一部を改正する法律案 ) これに続く社会の基本的なデジタル化を進めて、多くの行政の業務をオンラインで行えるようにすることが公式のスタンスとなっています。 改正のポイントは2つあります。まず、いくつかの身分証明書がマイナンバーカードに統合されることです。例えば健康保険証がマイナンバーカードに統合されることです。近い将来、eKYCを実施するための書類が減るということです。 業界にとって最大のインパクトは、将来お客さまがeKYCに使用できる書類がマイナンバーカードだけになることを政府が後押ししているということになります。ICチップの中に含まれているお客さまの個人情報を確認するため、手作業による身元確認をやめ、システムとマイナンバーカードの埋め込み署名を信頼するということで、ディープフェイクの影響を減らすことができます。 二つ目として、お客さまは手動で情報を入力する必要がないため、ユーザーエクスペリエンスが大幅に向上します。Fintech製品への登録中に、ミスを減らすことができます。 マイナンバーカードICチップを通じたeKYCの本人確認フローは、即座に完了します。お客さまが登録時に待つ必要もありません。eKYCはマイナンバーカードに埋め込まれたICチップを通じてのみ実行することを認めるかどうかは、現在では不明です。 私たちは、政府がこの方法をとることを望んでいます。マイナンバーを本人確認に利用することで、安全性とユーザーエクスペリエンスの両方が向上することは明らかであるにもかかわらず、多くの人々がこのような状況でマイナンバーを利用することに消極的です。 業界として私たちはお客さまに対してなぜ私たちの製品のやり方を変えるのか、法律の改正が業界の絶え間ない変化・進化に適用する必要性をどのように生み出すのかを説明する際に、もっとうまくやる必要があります。変化は必ずしもネガティブなものではありません。 とはいえ、あまりにも早い変化は複雑な問題を引き起こすことになります。最近、マイナンバーに関する複数の問題が報道されています。デジタル庁は、2016年1月に、国民が行政へ給付を受けられるようにするために、マイナンバーカードの銀行口座への登録受付を開始しました。 2021年10月から2023年5月にかけて、いくつかの問題が起きました。まずコンビニで住民票を取得しようとしたら、不適切な住民票が発行されたという問題がありました。 その後、一部の健康保険情報が本人ではなく、別の人に紐付けされたこともありました。 2023年5月、日本デジタル振興センターは、マイナンバーに紐付けられた銀行口座情報が他のものとなっていることがわかりました。 この問題は、手入力が問題であり、マイナンバー制度そのものに起因するものではないと覚えておく必要があります。マイナンバーカードが良い選択肢ではないのではなく、日本の本人確認手続きが誰にとってもより安全・簡単にこなせるようにすることが必要です。 私の見解ではいくつかのプロセス改善が必要で、マイナンバー制度は業界にとって非常にいい選択肢だと思います。 このプレゼンテーションは以上です。ID認証のイノベーションを望む全ての人の安全を守りたいと思います。 ご清聴ありがとうございました。
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 Merpay iOSにおけるSwift Concurrency対応の挫折と今後 」の書き起こしです。 @takeshi:「Merpay iOSにおけるSwift Concurrency対応の挫折と今後」という話をTakeshi Satoがさせていただきます。 自己紹介です。Takeshi Satoと申します。2019年にメルペイに入社して、支払いタブ画面、E2Eテストの整備、eKYC(本人確認)画面の開発を担当しました。今ではTnS(Trust and Safety)という不正対策チームでメルカリアプリの安全を守っております。「一冊でマスター!Swift Concurrency入門」という本を出しております。 今日私がお話するのは、失敗プロジェクトの共有です。私がリーダーをし、Merpay iOSにSwift Concurrencyを導入しようとしたものの、中断したお話をします。 今振り返って気づいたダメだった点をお伝えし、同じようにConcurrency対応やその他プロジェクトのコードを大きく変更する方の参考になればと思います。 Swift Concurrency対応プロジェクトは、2022年9月頃から進めていました。そのプロジェクトの概要をお伝えします。 次に、ロードマップの方向転換。最初は少しずつ対応してリリースしようと思ったのですが、Swift Concurrencyは一気に全て変更しないといけないことが判明し、そのように方向転換をしました。 次に、並行してメルペイのコードをGitリポジトリに統合するプロジェクトが進んでおりまして、その影響をお話します。最後にプロジェクトを中断した理由と、そこから得られた学びを発表します。 まず、そもそもSwift Concurrencyとはどういうものかを説明します。 Swift Concurrencyは、Swift5.5から登場した、言語レベルの並行処理の機能です。並行処理を簡潔に記述でき、Data raceを防ぐことができます。Data raceは、複数スレッドで同じデータを読み書きしたときに、データが不整合になってしまう状態です。それをコンパイル時にチェックする機能です。 キーワードとしては、async/await/Task/actor/@MainActor/Sendableなどがあります。 現在のSwiftは、リリースがSwift 5.8、ベータ版のXcode15ではSwift5.9が載っています。 Swift 6になると、Concurrencyのチェックが厳密になって、適応してないコードはコンパイルエラーになってしまいます。そのためSwiftコアチームは、今のSwift 5から段階的な適用のため、Swift 5系でも使えるコンパイルオプションを提供しています。 Swift 6になると、Concurrencyに対応してないソースはビルドができなくなるのは困りものです。そのため、早めに準備をしなければなりません。 参照: https://forums.swift.org/t/concurrency-in-swift-5-and-6/49337 具体的なコンパイルオプションはこちらです。 Swift 5.6まではOTHER_SWIFT_FLAGSに-warn-concurrencyと-enable-actor-data-race-checksを指定できました。-warn-concurrencyはSwift 6ではエラーになるコードを、Swift 5系でワーニング・エラーで教えてくれるオプションです。これを使って、Swift 6の準備ができます。-enable-actor-data-race-checksは実行時のデータ競合を診断するオプションです。 -warn-concurrencyは強いオプションなので、Swift 5.7から段階的に指定できるように、新しくSWIFT_STRICT_CONCURRENCYという専用のフラグができました。minimal、targeted、completeの3つが指定できます。 minimalが一番弱いオプションで、Sendableとactor分離を明示的に書いているところで、Concurrencyのチェックをします。Xcode14からはデフォルトのオプションになっています。 targetedはもう少し制約が強くなります。actor分離と、Sendableを明示的に書いているところで、Concurrencyのチェックをします。minimmalとの違いは、actor分離を正しく書くのを強制されているところです。ただしSendableのコードを書いてなかったらチェックはしません。 最後にcompleteが一番強いオプションです。モジュール全体でactor分離とSendableのConcurrencyのチェックをします。適切に書いていなければ、エラーかワーキングが出てしまいます。 completeと-warn-concurrencyは同じ意味です。Swift 5.7でも引き続き-enable-actor-data-race-checksを使えるので、指定します。 それでは、メルペイにおけるSwift Concurrency対応プロジェクトについて説明します。 これはMerpayiOSコードにSwift Concurrencyのビルドオプションを追加するプロジェクトになります。 目的は、Swift 6で必須になるConcurrency対応の事前準備です。現状のコードがSwift 6ではコンパイルエラーになるので、時間のあるときに対応していこうという意図があります。Sendableのエラーが出ないようにしていくのが目標です。 コンパイルチェックで、並行処理の不具合を減らす目的もありました。Swift Concurrencyの本来の目的をメルペイでも取り入れていきたいと思い、このプロジェクトを進めました。 ここで、メルペイコードのモジュールの構成を説明します。メルペイはSDKとしてモジュール化され、メルカリに組み込まれています。QRコードを出すQRモジュールや、クーポンを出すクーポンモジュールなどの各Featureのモジュールに、Sharedモジュールという形で、CoreモジュールやAPIモジュールがあり、それぞれのFeatureが依存しています。Coreは、基本的なプロトコルや、Dependencyを定義するものです。 プロジェクト当初のロードマップを説明します。 まずは、それぞれのFeatureモジュールに対応します。20以上の各モジュールにビルドオプションを渡し、それぞれビルドオプションを渡してビルドエラーを直し、Concurrency起因のワーニングをなるべく修正して、それぞれリリースします。その後コアのモジュールを対応していくという、少しずつリリースしていくロードマップを引きました。 ビルドオプション追加後、どんなエラーが出てどう修正しているのかを具体的に見ていきます。例えば、MainActorが付けられていないメソッドでUIKitのViewのプロパティを変更するものです。 UIViewとUIViewControllerはクラスにMainActorが付けられているので、メソッドの呼び出しやプロパティの更新は、MainActorのメソッドやクラスで行わないとエラーになります。 この例では、UILabelのTextプロパティを変えているのですが、MainActorがないと、コンパイルエラーになってしまいます。 それを直すには、Task@MainActorで囲うか、そもそもメソッドをMainActorにして更新する必要があります。 ワーニングの修正の一部も紹介します。例えば、DispatchQueueのasyncのクロージャーは Sendableのクロージャーなので、変数はSendableになる必要があります。 元のコードでは、asyncを実行する前にvarで変更可能な変数を定義し、クロージャで更新していたのですが、ワーニングが出てしまったので、別途変更したいデータはActorなどで全部定義した後で、クロージャ内で値を変更する必要がありました。 この対応でコードの書き方も変えました。メルペイでは、MVVMアーキテクチャを採用していて、各画面にビューモデルを実装しています。中身は薄いクロージャーでビューのイベントを検知したら、HTTP通信などして結果をクロージャーでビューに伝えます。 メルペイのコードはまだUIViewControllerで実装されているビューと接続するときには、全てMainActorが必要です。ViewModelはViewに近い操作ということで、型ごとViewModelにMainActorを追加しました。 また、Swift Concurrencyのプロトコルには少し厄介な仕様がありました。メルペイではCoreモジュールにプロトコルを定義して、それを各モジュールで準拠しています。例えばInputAppliableがCoreで定義されていて、使う側はそれを読み込んでいたのですが、例えばSubViewがUIViewを継承すると、SubViewがMainActorになります。 そこでInputAppliableのプロトコルのInput applyメソッドを実装すると、ワーニングが出てしまいます。MainActorのapplyメソッドはプロトコルに準拠していないということです。 プロトコルにはMainActorがないのですが、SubVirwのapplyメソッドには暗黙的にMainActorがついてしまうので、ワーニングが出てしまいます。 これが厄介です。各FeatureモジュールはCoreモジュールに依存しているのですが、InputAppliableの他に、Coreモジュールでプロトコルをいくつか定義していました。そのため、コアモジュールがプロトコル@MainActorにするまでは、各依存でワーニングが出てしまいます。 そのため、今回のConcurrency対応プロジェクトで各Featureにワーニングがたくさん増えてしまうという事態に陥りました。 そこで、ロードマップの方向転換を決めました。 各Featureモジュールを対応したらそれぞれリリースするのではなくて、全てのモデル対応が終わったら、リリースすることにしました。 これが、プロジェクト失敗の原因だった思います。一発リリースにすることで、プロジェクトの難易度は上がってしまいました。 そこで、ロードマップの方向転換を決めました。 各Featureモジュールを対応したらそれぞれリリースするのではなくて、全てのモデル対応が終わったら、リリースすることにしました。 これが、プロジェクト失敗の原因だった思います。一発リリースにすることで、プロジェクトの難易度は上がってしまいました。 さらにConcurrency対応と並行してGitリポジトリ統合のプロジェクトも始まりました。メルカリのGU Appのプロジェクト後に、メルペイもリポジトリを統合することになりました。 今まではリポジトリを分けてmerpay-ios-sdkというリポジトリにMercari GU Appを組み込んでいたのが、mercari-groundup-iosという一つのリポジトリにすることになりました。 Concurrencyプロジェクトは2022年9月から進んでいましたが、Gitリポジトリの統合プロジェクトによって、11月・12月はお休みし、2023年1月からConcurrencyプロジェクトが再開しました。 Gitリポジトリ統合プロジェクトが終わると、メルペイ画面をSwiftUIに書き換えるプロジェクトが始まりました。今までの画面はレガシーコードとして保守することになりました。ただ、Swift Concurrency対応のプロジェクトは、レガシーコードが対象でした。 今までのコードはレガシーコードとして扱われ、UIKit・MVVMアーキテクチャでなるべく更新しないようにする方針でした。それをGround UP Appアーキテクチャに変えようというプロジェクトです。 SwiftUIでCombineによるGround UP Appのアーキテクチャで、新規画面はこっちで実装しようという話になりました。 その後Swift Concurrencyの実装が完了しました。ただ、いろいろな問題が発生しています。 一気に書き換えたので、GitHubのファイルチェンジが1250ファイルと更新規模が膨大になってしまいます。 また動作確認したところ、不安定な挙動が頻発しました。例えばメインスレッドで動作すべき処理が別スレッドで動いていたり、別スレッドで動作すべき処理がメインスレッドで動作していたり。QRコードを読み込むカメラの処理で、AVFoundationのセッションをスタートするときに、誤ってメインスレッドで動いてしまうこともありました。 このように、品質を保証するのが難しい状態で、レガシーコードは保守運用チームの方針と矛盾する形になってしまいました。バグを直すかプロジェクトを中止するかの判断が問われる事態になりました。 ただSwift ConcurrencyはSwift 6の準備のために始めたプロジェクトです。Swift 6のリリーススケジュールを把握してないと、こちらの都合でプロジェクトを辞めたとしてもSwift 6がリリースされたらすぐ対応しなければなりません。 しかし調べてみると、Swift 6のリリーススケジュールはまだ発表されておらず、2023年はConcurrencyの他にオーナーシップに取り組む予定だと、ブログに書かれていました。またswift-evolutionでも、Swift 5.9のリリースをアナウンスされていますが、まだSwift 6のリリーススケジュールは出されていません。少なくとも2023年中にSwift 6がリリースされることはなさそうでした。 参照: https://www.swift.org/blog/focus-areas-2023/ Swift 6のリリーススケジュールとメルペイのConcurrency対応の現状を踏まえて、2023年3月にチームで話し合いをしました。 Swift Concurrencyのスレッド間で不具合がなくなるとはいえ、レガシーの積極的な更新をすべきではありません。また、一気に書き換えたSwift Concurrency対応のコードで不具合がたくさん見つかってしまっている状態です。さらに、Swift 6がリリースされても、しばらくはSwift 5モードでコンパイルする手段が提供される見込みであると発表されていました。 もちろんSwift6のどこかのバージョンでこの機能が消される可能性はありますので、最終的には対応すべきですが、Swift 6が出た当初はまだ時間がありそうです。 さらに、Xcode14.1、Swift 5.7ではUIキットWKNavigationDelegateやAVFoundationなどのConcurrency未対応のクラスやフレームワークが多い状態でした。そのため、まだまだSwift Concurrencyの書き換えは時期尚早と思われました。これらを踏まえ、Swift Concurrency対応は、SwiftUI書き換えプロジェクトの後でいいという判断になりました。 引き直した後のロードマップはこちらです。SwiftUI書き換えプロジェクトを2024年いっぱいまで終わらせ、その後にSwift Concurrencyプロジェクトを行う形にしました。 これは私の勝手な予想ですが、Swift 6のリリースはおそらく2024〜2025年の間です。SwiftUI書き換えプロジェクトが終わってからでも、この順番でできそうだと思います。 当てが外れて2024年にSwift 6がリリースされたら、書き換えプロジェクトとSwift Concurrency対応を同時にしなければなりませんが、ひとまずは書き換えの後にSwift Concurrencyの対応を考えています。 メルペイのSwift Concurrencyプロジェクトは、コードを一気に変えるという方向転換とチームとしてコードベースが変わるという影響でプロジェクトは中断されました。 チームの方針の影響はありますが、プロジェクトの方針として、一気に変える方針をとってしまったのも、中断の原因となりました。一気に変えると、影響範囲が見えにくくなって、QAが長引く原因になります。 誤算だったのは、Swift Concurrencyを一気に書き換えないと、ワーニングが増えてしまうことです。今回はワーニングが入ることで各モジュールリリースから全て書き換えのリリースに変えましたが、書き換えのベネフィットとチームの状況を見つつ進める必要がありました。 とはいえ、今思えば細かくリリースして早くコード反映した方が良いと思います。影響範囲が狭くなりますし、QAしやすいし、バグが出ても修正がしやすくなります。今回の出来事を通して、一気に書き換えるプロジェクトの難しさを痛感しました。 ワーニングが出てもチームを説得して細かいリリースをした方が、Concurrency対応を少しでも入れられたと思います。今回難しかったのはSwift Concurrency自体が時期早尚であることと、意外とSwift 6までの猶予期間があることでした。 チームによってコードの状況も変わる中で、プロジェクト中断はそれはそれで良い判断だと思いますけれども、プロジェクトリーダーとしては、不確実性を減らすために、細かいリリースを死守すべきだったと思います。 教訓は、大きな機能も細かなスケジュールを立てようということです。この経験が皆さんの参考になれば幸いです。 ご清聴ありがとうございました。
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 1週間リリースを支えるAndroid自動テスト運用のその後 」の書き起こしです。 @kenken:それでは、「1週間リリースを支えるAndroid自動テスト運用のその後」について発表します。 簡単に自己紹介をします。 @kenken:メルペイAndroidチームの@kenkenと申します。2021年5月にメルペイへ入社しました。現在はメルペイのあと払いをはじめとした、与信領域の機能開発やリグレッションテストの自動化などを担当しています。 @shinmiy:同じくメルペイAndroidチームの@shinmiyといいます。2021年12月に入社し、Androidのエンジニアとして、支払いタブやクレジットカード関連の開発、テストの自動化などを担当しています。 @kenken:それではまず、メルカリアプリの現在のリリースサイクルとリグレッションテストの自動化フローについて説明します。この内容は、2021年12月にMerpay Advent Calendarで公開された「 1週間リリースを支えるAndroidテスト運用 」というブログでも紹介しています。 現在、メルカリアプリでは、年末年始などを除いて基本的に毎週リリースが行われています。こちらの図は、リリースまでの流れを表しています。 まず、一番右のリリース日の4営業日前に、リリース用のブランチが作成されます。このブランチに含まれているコードが、リリースの対象となります。 従ってリリースしたいコードに関するQAがこのタイミングまでに完了し、かつメインブランチにマージされている必要があります。その後、Androidアプリ・iOSアプリともに、1営業日をかけてリグレッションテストを実施し、クリティカルな不具合がなければ、各ストアへ申請を行います。このリグレッションテストの一部をE2Eテストとして自動化しています。 現在は毎週行われているリリースですが、以前は隔週で行われていました。 当時の隔週のリリースサイクルでは、QAの完了からリリースまでに最長2週間待つ必要があるため、実装が完了した機能をお客さまに届けるまでのタイムラグが大きくなってしまう、Hotfixが必要になったときのリリース日の調整コストがかかってしまうなどの課題がありました。 そこで、現在のようにリリースサイクルを毎週に変更することが検討されました。また、Hotfixが必要になった際は、よほど大きな影響がない限りは、翌週のリリースまでに対応する方針も検討されました。 ここで判明した課題の一つが、リグレッションテストにかかる期間です。リリースサイクルが短縮されたとしても、リグレッションテストの実施内容は以前と大きく変わらないため、リリースサイクルのアップデートを実現するためには、2日にわたって行っていたリグレッションテストを1日に収める必要がありました。 この期間を短縮するために、リグレッションテストの自動化が求められるようになり、今回話す取り組みが始まりました。 参考記事: メルカリ・メルペイで行ったリリースサイクルのアップデート このような経緯があり、メルペイではリリース前に行うリグレッションテストの一部をE2Eテストとして自動化しています。 テストコードは、Espressoというフレームワークを使って書いており、CI上で特定のラベルが付いたプルリクエストをフックしたり、夜間にE2Eテストを実行したりしています。 テスト自体はFirebase Test Labというクラウド上でテスト端末などを提供するサービスを使って、並列に実行しています。 そして、Firebase Test Labでテストした結果をTestRailというテスト管理ツールにAPIを介して記録しています。この流れでE2Eテストを実行しています。 細かい部分でもいくつか工夫をしています。CIの実行にはお金と時間がかかるので、全てのプルリクエストに対してE2Eテストを実行するのではなく、特定のラベルやコメントを付けることで、必要なテストを必要なときにだけ動かしています。 こちらの例では、GitHubのコメントに「mp-uitest-filter dashboard」とコメントすることで、dashboardというパッケージのテストコードのみが実行されるようになっています。 また、今回の発表では詳細は割愛しますが、テストユーザー作成用のuser-tkoolという社内ツールを使うことによって、特定のユーザーを使い回さずにテストを行えるようにしています。こちらは 過去のブログ記事 でも触れているので、興味ある方はご覧ください。 次に、リグレッションテストを自動化するまでの流れをお話しします。リグレッションテストの自動化はQAチームと連携して行っています。 パターンとしては、新しくテストケースが作成される場合と、既存機能の改善に伴い、テストケースを更新する2つのパターンがあります。いずれの場合でも、TestRailとJiraというタスク管理ツールを使ってやり取りしています。 テストの実装については、TestRailに書かれている内容をもとに行います。左から順に、QAチームがテストケースを作成・更新して、内容をTestRailに反映します。TestRailでは、テストケースの実行種別でmanualかautoを指定できるようになっており、最初はmanualを指定します。その後、Jiraチケットを作成し、該当のケースへのURLを記載します。 チケットが作成されたら、エンジニア側でチケットに記載されているTestRailのテストケースを確認して、自動化が可能か、テストケースとしてケースの粒度が適切かなどの確認を行います。 この時点で自動化が難しいと判断した場合は、該当のチケットをクローズします。自動化が可能と判断した場合は、テストケースの実装を行い、該当のチケットをクローズし、TestRailのテストケースの実行種別をmanualからautoに変更します。 リグレッションテストの結果、autoのテストケースのうち、失敗率が高かったものに関しては、QAチームがマニュアルで該当のテストを再実行します。 次に、ブログ公開から現在までの約1年半の中で変化したことについて話します。 この期間に、メルカリ・メルペイではいくつかの大きな変化が起こっています。私たちの取り組みに影響する部分としては、大きく2点あります。 メルカリでは、GroundUP Appと題したリアーキテクチャプロジェクトを2020年から続けていて、2021年の後半にリリースをしています。これは、メルカリアプリをイチから書き直したもので、コードベースを今のアーキテクチャの潮流に合った形に置き換えています。 Androidアプリとしては、UIに関する部分をJetpack Composeというライブラリに置き換えています。しかし、メルペイの機能に関するコードについては、事業成長のための機能開発・改善を優先するために、GroundUP Appプロジェクトのリリース当初は、Jetpack Composeへの移行は行っていませんでした。現在では追従するように、機能ごとに順次Jetpack Composeへの移行を行っています。 メルペイとしては、最初に支払いタブのリニューアルを行い、リニューアルのタイミングでJetpack Composeに置き換えています。支払いタブというのは、右側にある図の画面です。このあたりについても、昨年のMerpay Tech Fest 2022で、取り上げているので、よろしければご覧ください。 参考記事: 【書き起こし】段階的Jetpack Compose導入〜メルペイの場合〜 – Junya Matsuyama【Merpay Tech Fest 2022】 開発体制においては、メルペイは昨年末より、「プログラム体制」をとるようになりました。 それまでは、プロジェクトと職種の2軸をもとに担当を決める「プロジェクトマトリックス体制」をとっていて、Androidチームのメンバーも、四半期ごとにさまざまなプロジェクトにアサインされる形をとっていました。 現在では、いくつかの機能を種別ごとにまとめたプログラムに他の職種のメンバーと一緒にアサインされるようになり、それぞれが担当のドメインを持つようになりました。Androidチームの各メンバーは、右側の図にある各プログラムのいずれかに所属しています。 これらの変化に対処して、メルペイAndroidチームとしても変化が起こっています。 支払いタブのリニューアルに伴って、UI部分の技術スタックは、Android ViewからJetpack Composeと変わり、リニューアルのタイミングで画面構成や機能にも大幅に変更がありました。 それに伴い、E2Eテストも修正する必要がありました。特に支払いタブは、メルペイが持っているほぼ全ての機能の入口となる画面でもあるので、この部分を修正しないと、E2Eテストの大部分が失敗するという状況でした。 そのため、復旧が急務となり、AndroidチームとしてはチームOKRの一部に組み込む形で、課題に取り組むことにしました。 また、プロジェクトマトリックス体制からプログラム体制へ移行したことに伴い、E2Eテストの実装に関わるメンバー構成も変更しました。具体的には、図の枠で囲った4つのプログラムから、1名ずつE2Eテストの実装に関わるようにしています。各ドメインの機能に精通したメンバーが参加することで、実装時に困った点を解決するまでのスピードが以前と比べて上がりました。 また、実装の優先度を決める際などに、「この画面には近いうちにこういう変更が入る」といった情報をキャッチしやすくなるといった、副次的なメリットもありました。 @shinmiy:こうした変化に対応してチームとして運営していく中で、いろいろな工夫をしています。 弊社で使っているSlackにはハドルという通信機能がありまして、他の会議ツールよりも気軽に集まって話せるようになっているのが特徴です。 この機能を使って1週間の中で定期的に集まる時間を作って、作業通話をしています。私たちの場合は毎週火曜日の午後に、全員が集まれる時間を「わいわい会」と称して作り、その時間に全員でハドルに入ってそれぞれの作業を進めます。 各々が困ったことがあったら、画面共有をしながら全員で問題解決を試みています。特にComposeについてはまだまだ新しい技術なので、手分けをして調べたりアイディアを出し合いながら、うまくテストケースを満たせる実装を探っていっています。 また、メルペイ自体が複雑な機能を持っているということもあり、知らない機能のテスト自動化を担当することもあります。ただ、全員が別々の機能群を担当しているので、お互いに質問し合って、テストケースへの理解を深め合っています。 お互いの忙しさがそれとなく確認できる場でもあるので、作業の進捗を確認して担当するタスクを調整したり、応援したりしています。 タスクの調整には、簡易的なカンバン方式を使っています。社内ツールとしてはJiraを使っているので、テストの追加や修正が必要な場合には、必ず1件ずつJiraでチケットを用意して週の進捗をカンバン方式で管理しています。 あくまでもサブプロジェクトの立ち位置ではあるので、他の大規模なプロジェクトのように、朝会や本格的な進捗確認会は行っていませんが、常に進捗自体は確認できるようにはしています。 最初に、目標として全体で取り組むチケット数やざっくりとしたアサインはメンバー内で決めて、進めていく中でメインの業務のタスクに応じて、定期的に担当を調整しています。 現在の状況を可視化して、メンバー間でお互いに補えるようにすることで、サブプロジェクトながらしっかり目標を達成できるような運用を可能にしています。 E2Eテストの作業では、似たような細かいタスクを大量にこなしていく形になります。普段はメインのタスクの合間に各々がテストを実装するのですが、並行して別々の実装を進めているので、似たような問題に遭遇しやすい状況です。 誰かが問題を解決した一方で、解決策を知らない他のメンバーが類似の問題に直面し、苦労してしまうという悲しいことが起こっています。 解決策をきちんとドキュメント化することも可能ですが、それだけで途方もない時間がかかってしまうので、それぞれが気軽に書き込める「雑にUIテストの知見を記録するメモ」を用意しました。 雑に課題と結論だけを書くドキュメントで、タイポしやすい間違いや、特定のユーザーの状況の作り方まで、実装中に気づいたことやコツ、間違いやすいポイントなどの知見が集まっています。 この知見がテストの実装に役立つことが多く、見返すことで、テストやメルペイ自体の仕様への理解も深まります。苦労して実装した結果を吐き出す場としても機能しており、読んでいくとストレスの発散の跡が見られます。 プルリクエストにもちょっとした工夫をしています。 メルカリ・メルペイの機能はかなり複雑な上に、テストの手順もどうしても言葉だけだと伝わりづらいものが多いので、テストの実装をしている間にテストが動作する様子をキャプチャし、プルリクエストに動画として載せています。 こうすることで、作業者が実現しようとしていることをレビュアーが理解しやすくなる、少なくとも作業者のローカル環境では、テストが通っていることの証拠にもなります。 ローカルでは動いているのにCI上で失敗している場合でも、この動画自体は比較対象として機能するので、どのステップで失敗したかが明確になって、修正にも役立ちます。 最後に、達成会です。有志で集まっている以上は、明確にゴールがあるとモチベーションが保ちやすく、みんなで一つの目標に向かっていくという一体感が出やすくなります。 もちろんチームとしても、「テストの自動化をいくつ完了させる」などの目標は立てていますが、それと合わせて、チームの間で「ここまで完了すれば、達成会を開催しよう」というサブ目標を立てることにしました。 こうすることで、メインの担当のタスクが重なってつらいときでも、「あと何個テストを書けば打ち上げだ」という形でモチベーションが保てるようになりました。 個人的には、TDD(Test-Driven Development)と呼んでいるのですが、あまり浸透はしていないですね。今回は、写真の通りとにかく肉を食べました。 テストの自動化には楽しく取り組めた一方で、大変なことや、課題に感じている改善ポイントもあります。 一つは、とにかく実装に時間がかかること。メルカリアプリの規模に起因する点でもありますが、フルビルドに大体15〜20分ぐらいかかるので、他の作業やミーティングの合間にブランチを切り替えて少しテストを書くという気軽さでは対応できません。 各々作業する時間を確保してテストを書くのですが、どうしても始めるときに「さあやるか」という意気込みとともにビルドボタンを押して、10分ほど待ち、休憩してから作業に戻ります。 また、E2Eの特性上仕方がないことではありますが、結果が不安定なことが多いのも大変な点です。想像以上に時間がかかってテストがタイムアウトしたり、画面遷移の際にうまくタップ対象を認識できなかったりと、安定して成功しないことが多いです。できる限り対策を行うんですけれども、現実的に解決できない問題も多く、ある程度の諦めが肝心です。 特に今の状況では一つのテストがとにかく安定することよりも、自動化されているテストの数を増やすことで、手動テストの負荷を軽減することを目指しています。 それから、仕様変更の部分です。仕様変更によって、せっかく自動化したテストが壊れることもあります。今の仕組み上、仕様変更で実装を変えたときは機能QAを通してリリースするんですが、テストの自動化した部分を直すのはリリースした後で、テストが壊れたのを確認して起票して直すというプロセスを行っています。ここは今後見直していきたいです。 それぞれのメンバーにメインの担当業務があるため、時間の捻出が難しいという課題もあります。プロジェクトの進行上仕方がないので、どのような進め方であれば効率がよいか、いろいろと試すしかないと考えています。 例えば集まる時間を1日にして集中的に実装する、物理的に顔を合わせながら実装して、コミュニケーションコストを下げる日を作るなどいろいろなアイディアはあるのですが、これからいろいろと試していくつもりです。 メルペイでは、リリースサイクルの変更をきっかけにE2Eテストの自動化にずっと取り組んできました。GroundUp Appとともに支払いタブのリニューアルを経て、テストが大幅に壊れた時期もありましたが、Composeのテストの取り組みを始めてテストの追加を頑張ってきた結果、一時期11%程度だったカバレッジが今では約50%と以前と同水準にまで回復させることができました。 ですが、これで終わりではありません。今後も引き続きテストのメンテナンスは必要だと思います。 組織的にも変更がありましたが、有志で集まって工夫をしながら進めた結果、ある程度の土台作りはできました。これからは、コードの変更に対応したテストの運用をしていけるように取り組みたいと思います。 ありがとうございました。
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 WYSIWYGウェブページビルダーを支える技術的マジックの裏側 」の書き起こしです。 @Hal:みなさん、こんにちは。私たちは、Merpay Growth Platform Frontendチームです。今日はFigmaのようなWYSIWYGツールの使いやすさにコンポーネントの合成や条件付きレンダリングのような強力な機能を追加した、私たちが取り組んでいるプロジェクトについて紹介します。 始める前に、このプロジェクトを支えるチームを紹介します。 まず、Tech LeadのArvinです。彼は、チームをリードし、メンバーの生産性を維持すると同時にこのプロジェクトや他のプロジェクトに貢献しています。 次に、Benです。彼は私たちのWYSIWYGツールにおける高度な機能の多くを概念化し、ソースコードに大きく貢献しツールのユーザーであるマーケターをサポートしています。 Jasは比較的新人ですが、基盤技術の大規模なリファクタリング、アーキテクチャの変更など、私たちのソフトウェアの多くの面を担当しています。 私は、チームのマネージャーであるHalです。問題解決に向けて関係者と話し合い、チームの成功に必要なことを調整します。 今日は私たちのウェブページビルダーである「Engagement Platform Pages」というツールについて、皆さんとともに興奮を分かち合いたいと思います。 このプロジェクトに取り組むことは毎日ワクワクしますし、とてもチャレンジングでもあります。フロントエンド技術の基本を深く掘り下げなければならないので、私たちは多くのことを学びました。 その前に@arvinhvからこのプロジェクトの背景とここまでの経緯について説明してもらいます。 @arvinhv:まず、数年前を振り返ると、このスライドにあるキャンペーンページを作成するためには、マーケター、デザイナー、エンジニアの多大な労力が必要でした。マーケターがキャンペーンのテーマや内容を決め、デザイナーがUIをデザインし、CSSやHTMLを使ってゼロからウェブページを作ります。最後にエンジニアがJavaScriptを組み込み、統合されたページに仕上げます。 平均して月に30のキャンペーンページの作成が必要です。ほぼ毎日、1ページを作成します。この3者が関与するので、何度もやり取りをしなければならず、全員に負担がかかっていました。 みんなの仕事をもっと楽にする方法はないのでしょうか?エンジニアとして問いかけ、この状況を改善するために、私たちは第1世代のCMSツールを作りました。 このツールは、JavaScript、HTML CSSをコンポーネントにカプセル化することでデザイナーが必要なコーディングの量を最小限に抑えることができます。 このツールはエンジニアによって始められたもので、このプロジェクトにリソースを投入できるよう、チームのロードマップの一部にしました。 このツールがどのように見えるかをお見せしましょう。これが第1世代ツールのユーザーインターフェースです。右側にプレビューエリア、左側に設定フォームがあります。 あらかじめ組み込まれたコンポーネントのリストから、コンポーネントの追加ができます。それがプレビューエリアに表示されるため、すぐに見た目を確認できます。また、コンポーネントのフォームからコンテンツの色の変更もできます。 つまりページを作成する方法は、これらのコンポーネントの設定であり、ページを構成するコンポーネントはいくつでも追加できます。 ここでわかるように、新しいコンポーネントは前のコンポーネントの後に追加されています。このツールはわかりやすいもので、これまでデザイナーがHTMLやCSSを書いていた問題が解決されました。マーケターが自分でウェブページを作成できるようにもなりました。 第1世代のCMSツールですが、すでに私たちの目的を達成しているように見えます。マーケター、デザイナー、その他ページを作る必要がある誰でも自分でページを作ることができるようになりました。 シンプルで、基本的にページ内にあるものが画面に表示され、各要素は設定可能なビルドを使って表せます。うまく機能していますよね。 他に何が必要だったのでしょうか?最初は、これは究極の解決策だと思ってました。しかし、多くの社内メンバーであるユーザーがツールを使い始めるにつれて、いくつかの問題に気づきました。 システムにコンポーネントを追加し、コンポーネントフォームにフィールドを追加していくと、ページを作成するときに巨大なフォームが表示され、ユーザーが修正したいフィールドを見つけるのが難しくなります。 第2に、新しいコンポーネントやコンポーネントの新しいフィールド追加など、新しい要件をサポートするために、エンジニアリング能力が必要でした。例えばコンポーネントにペインティングフィールドを追加するといった小さな変更の場合でも、リリースが必要であり、全てのパイプラインの通過が必要で、スピードも遅くなります。 さらに、要求がPMからエンジニアに、エンジニアから最終的な実装へと伝えられるプロセスでコミュニケーションギャップが生まれます。 各ステージごとのバイアスによりアウトプットが不正確になり、エンジニア、デザイナー、PMがフィードバックややり取りの調整に多くの時間を費やしていました。エンジニアとしてここは改善したいと思いました。 そこで思いついたのが、ツールをもっとカスタマイズできるようにして、マーケターがエンジニアに依存せず、エンジニアはシステムの改善に集中できるようにしたらどうだろうということでした。 そのやり方で、マーケターはこのシステムを使ってビジネス要件に対処できます。そうすれば頻繁なやり取りは不要になります。 この例を使って、考え方を説明しましょう。つまり、マーケターが既存のコンポーネントに新しい種類のログを追加したい場合、第1世代のシステムでは、チケットを作成し、エンジニアがチケットにスケジュールを設定し、リリースしなければいけません。 このプロセスには小さな変更であっても通常数日はかかりますよね。なぜなら、要件を確認し、検証し、マーケターの承認が必要だからです。 では、マーケターがページから直接何かを選択し、新しいログやアクションをページに追加できるようにしたらどうでしょうか?プロセスの生産性がそれによって大幅に向上します。 このアイディアを練るために1クォーターを費やし、アプリケーションのモックアップを作成しプレゼンテーションを行いました。 今でも覚えているのは、ミーティングを開いたり、ごはんを食べながらのOpendoorを開催したりして、多くのメンバーを集め、この新しいCMSツールの必要性を伝えていきました。なぜなら、これらの技術が大きな影響をもたらすと信じていましたし、非常にエキサイティングでもあったからです。 新しいメンバーが加わり、2、3ヶ月に及ぶ活発な開発を実行し、第2世代のシステムが完成しました。 この第2世代のものは大きく刷新されたものです。システムのコンポーザビリティやエディターの動き方、見た目を改善しました。スライドスクリーンショットをご覧いただければ、その違いはおわかりいただけるかと思います。 @jasにこの新しい変更について詳しく説明してもらいましょう。 @jas:コンポーザビリティについては、粒度を細かくすることで、柔軟性が増し、多様なコンポーネントを作成できるようになります。 以前は、コンポーネントを編集する際に二つの課題に直面しました。まず機能ごとに別々のコンポーネントを作成することは、拡張性も効率性も良くありません。 例えば、機能やスタイルが異なるボタンごとにエンジニアが開発し、エディターで使用する前にさまざまなプロセスを経る必要がありました。時間がかかりました。 二つ目の課題は、単一のカラムLayoutにしか対応ができないことです。 第2世代のエディタでは、四つの基本コンポーネントを提供します。Layout、Text、Image、Markdownです。これらのコンポーネントを組み上げることで、エディターは開発やリリースを待つことなく、複雑な機能を持つコンポーネントを作成できます。スライドの右側は、コンポーネントのスタイルコントロールパネルです。 スタイルコントロールは、Tail window CSSを使用しています。つまりCSSの機能のほとんどをコンポーネントに適用してより複雑なビジュアルスタイルやLayoutを作成できます。 さらに、異なるページの状態やユーザーの環境に応じて、異なるコンテンツを表示できるロジックコントロールコンポーネントも追加し、それによって、よりパーソナライズされた体験を提供できています。それはWHENコンポーネントです。例えばユーザーがログインしていないときにログインボタンを表示をしたり、APIのレスポンスに応じたコンテンツを表示できます。 最後に、アクションコンポーネントも導入しました。アクションコンポーネントは、ダイアログの表示やAPIのリクエストなど、多くのアクションをサポートしています。 では、実際の画面を見てみましょう。エディタを使って簡単なページを作り確認してみましょう。 これがエディタです。まず、ADDボタンをクリックして、メニューからLayoutコンポーネントを選択しましょう。 このLayoutをお客さまがウェブブラウザを使用するときに表示されるコンテンツのをコンテナとして使用します。ですので、これはウェブコンテンツと名付けます。 続いて、QRコードのコンポーネント、Textのコンポーネントを挿入して、お客さまにアプリのダウンロードとインストールを求めるブロックを作成しましょう。 次に、アプリを利用するお客さまのためのコンテンツを保持するために別のLayoutコンポーネントを追加します。 モバイルコンテンツと名付け、その中にボタンを設置しましょう。全てのコンテンツを作成した後、WHENコンポーネントを使用してそれらをラップし、さまざまな環境に基づいてそれらを表示する条件を追加します。 これはアプリのお客さま向けです。そこで、モバイルアプリを使用している条件を適用します。 ウェブブラウザを使っているお客さまのためにもう一つWHENコンポーネントを追加しましょう。ブロックの一つだけを表示して結果を確認してみましょう。 これはアプリのお客さまが見るものです。 こちらがウェブブラウザのお客さまに押されるものです。コンディションレンダリングができました。 ログインしていないお客さまに対してのみ、両方のコンテンツを表示したいとしましょう。これを実現するにはアクションコンポーネントを使用して、AuthサービスにAPIのリクエストを行い、お客さまのログイン状態を確認します。 その後、全てのコンテンツをゲストユーザー条件付きのWHENコンポーネントでラップしてログインしていないお客さまだけにコンテンツを表示できます。最後にお客さまがクリックしたときに、ログイベントを拡張するためにボタンにアクションを追加します。 @Hal:おそらく、これまで持っていたCMSツールよりも直感的になっていると思います。しかし、そんなに簡単に学べそうには思えません。 機能が多くて、マーケターはどうやってツールを使い始めたのでしょうか? @ben.hsieh:おっしゃる通りです。プロジェクトをローンチしたあと、マーケターの方々からたくさんの問い合わせが来ました。そのため、日々ハンズオンのセッションを行いました。たくさん開催しましたね。 これはみなさんにツールの使い方を学んでいただき、同時にフィードバックをもらうためでもあります。このときに、ユーザビリティが問題なのだと気づきました。 第2世代のシステムを作り始めたときに、私たちは柔軟性を考慮していました。それは、マーケターの方々にパワーを与えたかったからです。 彼らが、エンジニアからの手伝いをもらわなくてもできるようにしたかったからです。しかし、システムの柔軟性を高めると、適切に使うためには技術的な知識が必要になります。なので、その二つのバランスが必要になります。 ページエディターを作る上で、かなり労力を割いています。今日はいくつか例を使いながらその道筋を紹介していきたいと思います。 まず、例としてLayoutシステムをあげます。 ここでは、 Tail window CSS を使って柔軟なLayoutシステムを実現しています。ページエディターは、どんなLayoutでも作れるようになっています。CSSを裏側で使っているからです。 ですが、前提条件として、Tail window CSSクラスネームをかけるようにする必要があります。 これがすごく大きな問題です。マーケターの方々は、CSSの書き方がよくわからないからです。初めて紹介したときにマーケターの方々はすごく混乱しました。 そこでお手伝いをするために、CSSクラスネームビューを小さなものに分けたり、色付けをしたりしたらどうかと考えました。 それによって、使い方がわかり、クラス名を適切なフィールドに入力できるようにし、適切なクラスネームを把握できるようにしようとしました。 新しいバージョンをマーケターに見せたときに、また混乱が起こりました。 ドキュメンテーションを見て、クラスネームを少しずつ把握する必要があったからです。 そこで、もう一つ、新しいアイディアを見つけました。これは素晴らしいアイディアだと思いました。例えば IntelliSense のようなものを作ることです。デベロッパーはIntelliSenseが大好きだからです。 クラス名などが入力するごとに自動補完で表示されるようにしたら、マーケターはドキュメンテーションを調べなくてもいいじゃないかと思いました。 このスクリーンショットのように、何かを入力すると、クラス名が表示されるだけではなく、クラスネームの説明も表示されるようになります。そうすることで、マーケターは使いやすくなりますし、Tail window CSSを少しずつ使いながら学べると思いました。 これはすごく有効だと考えたんです。しかし、驚いたことに実際にマーケターの方々に試してもらったところ、また混乱してしまいました。 「CSSを知らなくてはならない」という前提は変わらないからです。クラスネームを作るプロセスが簡単になったとしても、使うための知識は必要です。なので、根本的な問題は完全に払拭できていませんでした。 その結果、Figmaあるいはブラウザウェブツールなどを作っていくことにしました。このソリューションは受け入れられ、上手く機能しました。 マーケターは、このGUIのLayoutエディタでやり取りをすると、裏側ではこの入力をTailwind CSSのクラスネームに変換しているんです。なので、元々のソリューションを諦めているのではなく、エディターの裏側に隠れているのです。 このGUIのLayout Editorはまだまだ制約があって、このクラスネームを使うことで、できることもあるけれども、GUIエディターできないこともあるので、エンジニアの方々は事前に設定をする上で使ったり、緊急の要件を満たすために使うことができます。 つまり、いろいろな技術レベルに応じて、いろいろな使い勝手が生まれます。 もう一つの例がCondition Systemです。先ほど申し上げましたように、私たちの新しいシステムは、条件に応じてコンテンツのレンダリングができます。その裏側ではJavaScriptのExpressionを使って、一部のコンテンツをレンダリングするかを判断しています。 これを作るときにこれらのコンディションはすごくシンプルで、JavaScript Expression1〜2行だろうと思っていました。このスクリーンショットにあるように、store?.user?.profileのようなものだと思っていました。 ですが、実際に幅広く使い始めてみたところ、この条件がかなり複雑で、10行以上になってしまうことがよくありました。 場合によっては、nullの検証やフォーマットのコンバージョンをしなければならなくなり、Expressionがさらに長くなります。 コンポーザビリティを増やすことによって、コンポーネントがネスティングできるようになります。そうすると、コンディションがあまりにも複雑になってしまって、マーケターは自分で設定ができなくなり、エンジニアが関わる必要が出てきます。 私たちのソリューションは、Layerとシステムとほぼ同じですが、複雑な部分をラップする作り方にしています。 よって、マーケターは機能へシンプルにアクセスできるようにしています。例えば、コンディションについてですが、マーケターに自分たちで条件を書くのではなく、GUIツールを作って一般的に使われているコンディションをテンプレートとして提供しています。 マーケターは、いくつかのコンディションから選びます。例えば、iOSアプリを利用するお客さまにだけ示したいときには、iOSアプリを利用するお客さまを選びます。そうするとGUIフィルターで条件を自動入力できます。 また、テンプレートの引数も提供していますので、多くの場合、柔軟に使えるようになっています。例えば、コンテンツとして、お客さまが販売しているものの個数に応じて表示する場合、マーケターがテンプレートを選ぶと別のフィールドが表示されて個数を入力するようになります。マーケターは、数字を入力し、テンプレートの条件を完成させます。 二つ目は、ネステートコンフィギュレーションレンダリングです。ここでもマーケターの方々が、再使用可能なコンポーネントを自分たちで作れるようにしています。 第1世代ではエンジニアがコンポーネントを書く必要がありましたが、エディターでコンポーネントを作って、彼らが再使用して、カスタム変数を使って振る舞いをカスタマイズしたり、見た目をカスタマイズできるようにしています。複雑なページのコンピレーションを将来的には再利用して、一部カスタマイズできるようになります。 二点目ですが、コンセプトは大体同じです。高い柔軟性から始めて受け入れられるレベルまで徐々に調整をしていきます。 これが、例です。高い柔軟性を提供した結果、ユーザビリティの問題がありました。しかし、高い柔軟性は開発の初期段階ではいい選択肢だと思います。オンデマンドで将来的にいろいろなレベルの柔軟性を提供できるからです。 2点目として、柔軟性とユーザビリティの問題に対応するためには、まずは小さなPoCからはじめることをおすすめします。巨大なソリューションから始めるべきではありません。マーケターが気に入ってくれるかどうかわからないからです。 IntelliSenseと同じように労力を割いているけれども、うまく使えなかったケースもあり得るからです。 3点目として、WYSIWGエディターを作るときには課題があることを覚えておいてください。技術的なものだけではなくて、さまざまな課題が発生します。ですが、1回やると、すごく学んですごく成長できると思います。 @Hal:教訓が、いくつかあります。まず問題があったときに、再発しそうな問題の場合は、効率を改善するやり方を考えてください。 例えばテンプレートの作成や自動化したり、この仕事をしなければならない人をエンパワーしたりすることを考えてください。2点目としては、エンジニアは興味のあるプロジェクトに関わった方が効率が上がります。 まとめです。 問題があり、そこに対してのソリューションを作りました。つくってみると拡張性や利用する人の能力における問題が新たに発生し、そこに対応するためにソフトウェアを再開発する必要がありました。良いバージョンのものを半年で作り、ツールの使い方をマーケターにオンボーディングし、新しいツールの確固たるファンデーションを作り、テクノロジーの使用を拡大しようとしています。 ご清聴いただきましてありがとうございました。何か新しいものを学び、勇気を持ってぜひ仕事の仕方の改善に役立てていただければと思います。
Merpay & Mercoin Tech Fest 2023 は、事業との関わりから技術への興味を深め、プロダクトやサービスを支えるエンジニアリングを知ることができるお祭りで、2023年8月22日(火)からの3日間、開催しました。セッションでは、事業を支える組織・技術・課題などへの試行錯誤やアプローチを紹介していきました。 この記事は、「 fake clock microservice -時刻をハックしてテストする方法- 」の書き起こしです。 @vvakame:「fake clock microservice -時刻をハックしてテストする方法-」というセッションを始めたいと思います。よろしくお願いします。 @vvakame:僕は@vvakameと申します。メルペイ Solutions Teamで社内ツールなどを作っている関係上、いろいろなマイクロサービスの時刻に関わる設定を変更した上でデータを作りたいというニーズがある当事者の1人でございます。 @hiraku:スライドの真ん中に写っている、@hirakuです。メルペイではCredit Designというチームに所属してまして、メルペイのあと払いや与信関係のサービスのバックエンドエンジニアをやっております。 @tanaka0325:@tanaka0325と申します。2021年1月にメルペイに入社して、今はCredit Design Teamのバックエンドエンジニアをやっています。日々信用を創造して、なめらかな社会を作っています。よろしくお願いします。 @vvakame:おふたりはCredit Design Teamからということで、メルペイの中でも最も業務ドメインが複雑と言われるCredit Design Teamが、いかにして今まで苦しんできたかという話を今日していこうかなという感じですね。 本セッションの構成は、最初に前提となる時刻とテストの問題について解説をし、それに対する解決策・fakeclock serviceについてご説明して最後に我々3人でトークセッションをしていこうと思います。まずは前提の共有からやっていきたいと思います。 @hiraku:最初に、まずこの問題のことを前提知識としてインプットしていただければと思います。現在時刻に対応するロジックはあちこちにあると思います。 これはメルペイのあと払いのヘルプページから取ってきた画像です。8月1日に購入して、8月31日に締めがあって、9月30日までに支払うという2ヶ月間のライフサイクルがあるみたいなことが、金融領域を扱う我々メルペイにとってありがちなんです。これを現実時間で、もしテストしようとしたら2ヶ月間のQAが期間が必要になってしまいます。 修正したら、すぐリリースしたいので、素早く効率的にテストしようと思うと、「時刻をいじってしまおう」と考えるわけです。 8月1日に時刻をいじった状態で購入をテストして、9月1日に変更して請求のバッチをテストします。9月20日を超えて10月1日になると、延滞状態になりますので、その状態をテストするというイメージです。 これは、実際にメルペイの社内でもあちこちで実装されていて、テスト環境限定のAPIがあります。debug.SetNow APIが各所に実装されており、日付時刻を設定してあげると、その通りに時刻を固定できます。 この方法には、いくつか実は問題点がありました。 まず一番大きいのが、弊社はマイクロサービスアーキテクチャを採用していて、マイクロサービスが複数あることがすごく問題になっています。一つの機能を実現するのに何個もマイクロサービスが関わっているので、それぞれに対してSetNowを叩いていかないと求めた状態になりません。また、設定漏れも起きがちです。そして、それぞれのマイクロサービスでAPIの実装するのも、無駄だという問題がありました。 もし一つだけ設定を忘れた場合、デバッグがとても大変になります。 本番だと絶対にあり得ないのでそういうことを配慮したコードはなかなか書いてないんです。他のマイクロサービスと時間がずれてるという状態が、いかなる問題を引き起こすのかは、起きてみないとわからないレベルです。 昔あったのが、スナップショットのレコードを保存しようとしてたんだけど、時間が完全に固定されていたので、2件挿入しようとすると、レコードが重複してエラーになってしまったことがあります。 もう一つの問題が、テスト環境全体に対して時刻を設定しているため、テスト担当者が複数人いて、同時に複数のテストケースを実行しようとすると、Aさんが8月1日に、その直後にBさんが8月15日に日付を上書きすると、2人とも困ってしまいます。 これを並行してテストするために、テスト環境をそれぞれ人数分用意し、頑張って実行しています。環境をいっぱい用意するのは大変ですし、無駄が多いなという問題があります。 @vvakame:Aさんの環境は安定しているけど、Bさんの環境は不安定で、これはバグなのか迷ってしまうこともあります。 @hiraku:まとめていくと、この辺を求めているわけです。並行してテストしたいので、一度の操作で、各マイクロサービスの時刻を一気に変更したいし、環境ごとではなくてリクエストごとに時刻を操作したい。環境をいっぱい用意するのではなく気軽に時刻を操作できるようになりたいということです。 そこで我々の方でいろいろ検討し、タイトルにもあったfake clock serviceに行き着きました。 それまでにあがった検討案として、最初が「環境をいっぱい用意する」の亜種という形で「必要なタイミングでマイクロサービス群を複製する」という案がありました。ボタンを押すと、マイクロサービス群が一気に立ち上がるような環境があればいいんじゃないかということは、アイディアとしてありました。これは本番環境にすごく近い状態にできますし、安定してるのではないかと考えました。しかし、環境を1から立ち上げようとするとどんなに最適化しても数分はかかってしまうので、なかなか気軽にテストできる状況にはなりませんでした。 もう一つが、「メタデータとして伝播させる」ということ。 マイクロサービスのサービス内容は、たいてい何らかのリクエストから始まります。HTTPのリクエストだったらHTTPヘッダー、そういったメタデータ部分に、現在時刻の情報を含め、最初に受け取ったサービスがメタデータを後ろのマイクロサービスに伝播させれば、全てのマイクロサービスで、リクエスト単位で時刻設定できるんじゃないかという考えに至りました。 これでうまくいくと思ったのですが、1個問題がありました。社外システムが途中に挟まっているというケースがあったのです。 我々だけで作っていない部分がいくつかあります。メルペイの社内であれば融通が利くのですが、社外のシステムにおいてはそうはいかず、社外システムのコールバックが本当の現在時刻で返ってきてしまいました。 あと社内であっても、どこかのサービスが工数や優先度の問題で、メタデータ伝播の実装がなかなかできないとなると、裏側のサービスがいつまでたってもメタデータを受け取れないという問題がありました。部分的に導入していくというのが厳しいという問題になりましたね。 そして出てくるのが、マイクロサービスを立ててしまおうという案です。マイクロサービスアーキテクチャの問題はマイクロサービスを立てれば解決するというアイディアです。 真ん中にfake clock serviceという新しいマイクロサービスを1個立てます。これが、全ての時刻のマスターのように振る舞います。ただ、一個のサービスがマスタークロックを持ってます、というだけでは他のサービスが全部同じ時刻に切り替わってしまって並列度が上げられないので、時刻の管理をユーザー単位にしようということで、ユーザーIDをキーにして時刻を取れる仕組みにしました。ユーザーさえ違えば、別の時刻帯をそれぞれ管理できるようにしました。 大体良さそうだったんです。ユーザー単位で大体テストしているので、並列度が欲しければ、ユーザーをいっぱい作ってしまえばいいという話です。 メタデータの問題だと外部システムが途中に挟み込んであるので困ったことがありましたが、こっちの案はもし外部システムから戻ってきたタイミングで、改めてfake clock serviceに問い合わせしに行くと時刻を強制的に復元して、また元のロジックに戻っていけるというメリットがあります。 また、外部システムと同じで途中に未実装のサービスがあっても、導入済みサービスだけでも恩恵がある状態を作れるので、部分的に導入しやすいという面もあります。 ただ、問題としては、こんなサービスを本番には作るわけにはいかないので本番環境と構成が異なります。また、このfake clock serviceがテスト環境限定の単一障害点となり、これが落ちると全部テスト環境がうまく動かなくなってしまうというデメリットがあります。 現状は、導入を進めている最中です。 今ちょうどこれから各マイクロサービスに導入していくフェーズです。運用が開始されてからの知見が実はないんです。ステータスとしてはSDKとマイクロサービス本体が実現されているのと、user-tkoolに関しては稼働しています。 @vvakame:user-tkoolとは、社内用のデバッグ操作をSlackコマンドでできる便利なサービスです。オプションを設定するインターフェースはすでに作ってあるというイメージです。 参考記事:テスト用お客さまデータ作りツール user-tkool の近況 @hiraku:user-tkoolの中でいろいろ時刻をセットして、一つだけ購入したことのあるユーザーを作ることもできるので、内部的に時刻を操作する部分を使っています。 ただ、マイクロサービスに導入するときに、検証をするのが大変なので、導入が止まっているのが現状です。 @vvakame:ここで、質問をいただいています。「内部のアクセスが1hop増えるからレスポンスが遅くなる可能性があるのではないですか」という質問がありました。 これについてはとりあえず機能を達成してQAの工数を圧縮できるのがまずは優先で、将来的にそうなったらメタデータ型との複合で、サービスに設定値を取りに行かなくてもメタデータにあればすぐ返せるという実装も考えています。 @hiraku:負荷テストで性能を測定したい場合は、テスト環境であってもfake clock serviceの設定を切ることもできるのでその辺で調整していこうかなと考えています。そもそも一度の負荷試験で日付をまたぐことはないと思います。 @vvakame:次の質問です。「マイクロサービスは、現在時刻を取るときに常にユーザーIDを渡していますか?」。そうですね、マイクロサービス間の通信には内部的なアクセストークンが発行され、そこにuser customer IDが常に含まれているので、gRPCインターセプターなどのLayerでアクセス元のIDを確認できるようになっています。 次の質問「各マイクロサービスはどのタイミングで fakeclockにリクエストするんでしょう?」というのも大体gRPC インターセプターでサーバーにリクエストを受け取ったタイミングで1回だけ取りに行きます。 @tanaka0325:今はユーザーIDでとりあえず始めていますが、ユーザーIDがキーじゃないサービスもあるかも知れません。一意のキーであれば何でも良いので、今後はその対応もしていこうかなという話は出ています。 @vvakame:ここからはパネルディスカッションに入ります。 トピックはこちらです。まずは、「今どこまで進んでいるのか」。先ほど話がありましたね。 言い訳をさせていただくと、Merpay & Mercoin Tech Festのスピーカーが募集されたタイミングで、「fake clockはどうですか」と打診されたとき、その頃には最低一つか二つぐらいのマイクロサービスには導入が終わってるだろうと高を括っていましたが、案外進みませんでした。 @hiraku:マイクロサービス本体は@vvakameさんが入ってきてくれてからは、サクサク進んでそれは問題なかったんですけど、導入側が大変でした。 @vvakame:次のテーマ「導入時のQAどうするのか問題」ともつながります。一応一つのマイクロサービスに対して導入のプルリクエストは作りましたが、これをマージするときにどうやってQAをするのかという課題が持ち上がりました。 @tanaka0325:単純に考えると影響範囲があるところはQAしたいという気持ちがあるので、どこが影響範囲なんだというと、時刻は取り扱うところはありとあらゆる箇所に散らばっているので極論全部という話になってしまいます。 それを全部やると、いつまでたってもリリースできないので、これは何か考えないとなということで今議論しています。 @vvakame:SetNowを呼ぶところは構造上は少ないんですけど、Goのtime.Now()のようなものはコード上にたくさん散らばっているので、その無影響確認と、本当に時刻が変更できているという影響確認の両方が難しいです。 @hiraku:過去のQAに関しては、当然時刻操作しながらするQAシナリオがいっぱいあったので、元のマイクロサービスごとに実装されていたfakeclockのシステムを使っていたのですが、それを置き換える形になるので、テスト自体にも影響があります。 書き換えたコード自体もテスト対象だし、テスト自体も書き換えないといけない。単純な無影響確認とも言い切れません。 @vvakame:品質担保は我々金融の決済領域なので、非常に神経質に行っています。QAは工数が厳しそうですよね。とはいえ、fakeclock serviceの導入はQAの効率化のためにもQAのエンジニアの方々からも切望されているので、何とか前に進まないといけませんね。 @tanaka0325:ここで、関連の質問をいただきました。「進まなかった理由はありますか」という質問です。今話した部分で、金融だからQAは大変なのと、テスト自体も直すという作業があること、そしてこれとは別に今まで通りの施策は進んでいて、その作業もありつつ、プラスアルファでこのような作業を行うという点で、バランスをとっていくことが難しかったからです。 @hiraku:導入に関しても、プルリクエストで一気に書き換えてリリースするのではなく、もう少しプロジェクト的に考えて、少しずつ分割してやっていかないと厳しいということで、作戦を変更して進めています。 @vvakame:ではマイクロサービスとE2Eテストについてはいかがですか?E2Eテストがしっかり揃っているとやりやすいけど、でもE2Eをいっぱい書くためには、便利なfake clock serviceが必要という問題があります。 @tanaka0325:厳しいですね。今もE2Eテストはあって、fake clock serviceの前はどうやっていたかというと、環境が人数ごとにあったように、E2E用にもありました。とあるサービスによっては、fake clockで時刻をいじるためだけに複製した環境が何十個もあったりしました。 環境をメンテナンスするだけでも大変だったので、E2E観点でもマイクロサービスは早く移行したいという気はしています。 @hiraku:逆にE2Eテストがコードベースで仕上がっているマイクロサービス機能群に関しては、あちこちでSetNowを叩きまくらないといけない件に関しても、そんなに困りません。そのため、優先度を下げてもいいという温度感になっています。 手動テストがメインな部分はE2Eテストが欲しいですが、手動テストがメインだと、こういう置き換えがとてもしづらいというデッドロックがあります。 @vvakame:続いて、グループ全体から見た位置づけについて話しますか。 グループ全体から見た位置づけとしては、メルペイの特にCredit Design Teamが非常に複雑なので、Credit Design Teamの要求を満たせるサービスであれば、グループ全体の要求を満たせる可能性が高いというコメントをもらったことがあって、納得しました。 ただこれが全体に広がるかは、Credit Design Teamのユースケースをケーススタディとしてちゃんと使えるかが関わってきます。 @tanaka0325:あと払いは、絶対に時刻が関係するので、Credit Design Teamが一番使うと思います。メルペイ自体の機能が増えてきたり、複雑度が増してきて、他のマイクロサービスがCredit Design Teamに依存したり、時刻に関連するマイクロサービスができたりしていて、今後はより他のチームでも必要性が増してくると思います。なるべく早くCredit Design Teamで成功事例を作って、他のチームでも使えるように広げていきたいです。 @vvakame:最後に、質問をいただいています。「修正したNowから徐々に時間が経過してほしいという、相対的な時間指定ができるようになりますか?」ということです。これは今回の実装からできるようになりました。 続いて、「実装優先を決断するのはどなたですか?」という質問をいただいています。Credit Design Teamはどういう感じですか。 @hiraku:意見を出すという意味では、みんな関わってはいますよね。 @tanaka0325:優先度づけのときに事前にエンジニアリングのヘッドや、PMのヘッドなど、いろいろな人が集まって各状況を整理してみんなで優先度を決めるので、特段誰かが決めるというよりは、割とみんなで決めることが多いです。 @vvakame:fakeclock serviceのような新しい解決手段を提案したり考えたりするのは、メルカリグループの場合はボトムアップ的に行っています。そういう意味ではこういった新サービスを作ろうというのは我々で決断して勝手に実行します。 我々はこういったことを一緒にやってくださる仲間の募集しています。「新しいソリューションを考えたい」という方がいらっしゃったら、ぜひ応募してください。 最後の締めとして、新しくこういった時刻系の実装をしなければいけない人たちに対して一言ずつアドバイスをいただけますか。 @tanaka0325:DBのカラムでcreated_atなどのシステム時刻が自動で入るものがよくあると思うのですが、あれはシステム時刻のためのもので、ロジックにあれを使うと、時刻を操作したいときに操作できなくなってしまうんです。 その場合は専用のカラムを準備して、アプリケーション側で操作できるようにしておくことは大事だと思います。 @hiraku:後から導入しようとするとすごい大変だぞということを伝えたいです。早い段階で、時刻操作の問題が今後どんどん厳しくなっていくから、早めに解決手段をとりましょうという判断ができていたら良かったと思います。 @vvakame:僕からの皆さんのアドバイスとしては、マイクロサービスをやらないと組織がどうしようもならなくなるまでは、モノレポや一つのリポジトリでやった方が時刻操作も楽なので、マイクロサービスにしないで良いのであればマイクロサービスにするのはやめましょうということです。 以上、fakeclock serviceについての発表とパネルディスカッションでした。ありがとうございました。
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 以上です。ご清聴ありがとうございました。
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人でお送りいたしました。皆さん、ご清聴ありがとうございました。
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】 発表は以上です。ありがとうございました。
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というサービスの導入を進めており、それによって会計帳簿サービスへの依存を減らす方針で進めています。 以上で、今回のセッションを終わりにしたいと思います。ご清聴ありがとうございました。
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になっており、誰でも使えるようになっているため、ぜひ使っていただいてフィードバックをお待ちしています。 それでは本発表を終わります。ご清聴ありがとうございました。
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というマイクロサービスを開発することで処理の共通化をしています。 以上です。ご清聴ありがとうございました。
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コードを読み込んで、応募いただければと思います。 本日はご視聴ありがとうございました。
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をお試しください。
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のプライオリティの調整はなかなか大変ですが、今後も成長していきたいと考えております。こういったセッションは、ぜひ来年もやりたいです。 以上です。ありがとうございました。
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からインフラを抽象化したツールなどを提供することでサービスの開発と運用を促進してきました。一方で課題感としては、抽象化しているツールが増えてきたことで、学習コストや開発者の認知負荷が高くなってきてるというのがあって、それらを開発解決するために、よりシンプルなインターフェイスのようなものが必要になっています。 今後、そういった課題に対しても、より良いものを取り入れて改善していけるといいなと考えております。 本日はご清聴いただきありがとうございました。
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:ありがとうございます。以上でこのセッションを終わりにします。ありがとうございました。
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マイクロサービスの導入と独立のお話をしました。参考になれば幸いです。 以上で、本日のセッションを終わりにします。ご清聴ありがとうございました。
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:では、以上でパネルディスカッションを終わりたいと思います。それではご視聴ありがとうございました。
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:以上が、テストケースフォーマット標準化プロジェクトで取り組んだ内容です。ご清聴ありがとうございました。