こんにちは。メルペイ Payment Core Teamで2ヶ月間インターンシップをした@taichiです。
この記事は、Merpay & Mercoin Tech Openness Month 2025 の22日目の記事です。
はじめに
私は4月の中旬から6月の中旬の間、 バックエンドエンジニアとしてメルペイのインターンシップに参加しました。今回はインターン期間中に取り組んだタスクを振り返り、 そこで得た学びをまとめたいと思います。
この記事が、 メルペイのインターンに挑戦してみたいと考えている未来のHackerの参考になれば幸いです。
取り組んだタスク
私が担当したタスクは大きく分けると3つあります。
- 外部パートナーへの接続に関するCredentialの管理方法の変更
- Re-arch中のソースコードへのPub/Sub基盤統合
- 個人情報難読化ポリシーの実装
以下で1つずつ話していきます。
外部パートナーへの接続に関するCredential管理方法の変更
背景
私が所属するPayment Coreチームでは、決済基盤マイクロサービスである『Payment Service』の開発を担当しています。このサービスは、メルカリ、メルペイ、メルコインが展開する多数のマイクロサービス群から参照されており、グループ全体の決済ドメインにおけるコアな責務を担っています。
メルペイでは決済機能の一部で外部パートナーさまのAPIを活用しているため、そのCredentialを適切に管理する必要があります。
私がタスクに取り組むまでの運用では、 新しく追加したCredentialを暗号化しSpannerにSQL raw queryを叩くことで保存していました。
従来の運用方法は以下に示す危険性と面倒さを有しています。
- 加盟店追加のたびにSQLクエリを叩く必要がある
- 加盟店追加後にSQLクエリを発行し忘れる可能性がある
やったこと
上記の課題を解決するために、 以下のような設計と実装を行いました。
- 外部パートナーの加盟店さまのパスワードの格納先をGoogle Secret Managerに変更
- Spannerに直接パスワードを保存せず, SecretのKeyとVersionだけを格納する
- Secretの情報を入力として渡すだけで, SQLが走ってSecretのKeyとVersionをSpannerに保存するK8sのJobテンプレートを作成
- SecretManagerを通して加盟店さまのパスワードを取得できるようにClientCodeを修正
最初はCLIを作ってチームに提供することも考えましたが、 メンテナンスの負荷が新たに発生すること、 K8sのJob基盤がすでにチームに存在することを理由にCLIは避けました。
K8sのJobテンプレートはこちらが参考になると思います。
インターンに参加して1週間くらいで設計を行いドキュメントを作成したのですが, 設計書のレビューが手厚くチームメンバーと技術的な議論を繰り返すことでタスクやPayment Serviceの全体像を掴むことができました。
Re-arch中のソースコードへのPub/Sub基盤統合
背景
私が所属していたPayment Coreチームが開発しているPayment Serviceは、そのソースコードが非常に複雑なため、大規模な再構築プロジェクト、通称「Re-arch(リアーキテクチャ)」が進められていました。
このRe-archプロジェクトの目的は、既存のPayment ServiceのソースコードをClean Architectureのような設計思想に基づいて書き直すことです。
現状のPayment Serviceでは、非同期処理のためにGoogle Cloud Pub/Subが利用されています。しかし、Re-arch後の新しいソースコードには、Pub/Subを利用するための基盤がまだ整備されていない状況でした。
やったこと
私はRe-arch後のソースコードのコンテキストにマッチするようにPub/Subの基盤を統合しました。
Pub/Sub基盤の設計は、 Payment ServiceがPub/SubからSubscribeしか行わないことを前提にメンターと進めました。
Subscriberに渡すHandlerのInterface設計や、 Usecaseに渡す依存関係を一括で管理するContainerとの親和性を考慮して設計する経験は非常に勉強になりました。
Re-archのPRは変更が大きいものもあるので、 Conflictの解消やContextを理解し直すのに苦労したこともありましたが、 あれほど大規模なソースコードを読むこともないのでとても良い経験になりました。
開発体験としても、 Payment ServiceではMockの生成はmoq.goを使っているので、 interfaceだけ設計すればMockを簡単に生成できるので、 素早くTestableなコードを書くことができました。
個人情報難読化ポリシーの実装
背景
個人情報保護法の改正を受け、メルペイ全社で「PII Deletion(個人情報難読化)プロジェクト」が進行中です。これに伴い、Payment Serviceもこの対応を行う必要がありました。
個人情報の難読化はメルペイ全体で取り組むべき課題であるため、すでにそのためのマイクロサービス「PII Deletion Service」が構築されていました。
しかし、Payment ServiceからPII Deletion Serviceを叩きに行くことができない状態でした。
やったこと
PII Deletion Serviceのアーキテクチャは下図のようになっています。
上図を解釈すると, 処理の流れとしては以下になります。(Payment Serviceは上図における右端に位置すること, 各マイクロサービスはgRPCで通信を行うことを念頭においてください)
- PII Deletion Managerから難読化すべき個人情報の情報がPub/SubにPushされる
- Payment ServiceがPub/SubからPullして難読化する対象を見つける
- 難読化する
- 難読化が成功したかのステータスをPII Deletion Managerに返す
1はすでに仕組みとして存在するので、 私は2-4を実装すれば良いことに気づきます。
以下ではステップ2についてどのように対応したかを述べます。(3、 4はそこまで難しいことがないのでスキップします。)
Pub/SubからPullして難読化対象を見つける
PII DeletionのHandlerはRe-arch後のソースコードに実装するので、 私が統合したPub/Sub基盤を使用すればすぐに実現できるので簡単に思えます。
しかし、 Pub/SubのSubscriberが行う処理をそのまま記述しようとすると2点好ましくない点があります。
普段慣れ親しんでいるgRPCエンドポイントと異なる体験で開発しないといけない
Subscriberのロジックが他のAPIのロジックから独立しがち
これらの課題を避けるために、 メルペイはPub/Sub gRPC Pusherという内製化サービスを持っています。Pub/Sub gRPC Pusherの仕組みは簡単で、 以下のようなアーキテクチャになります。
gRPC Pusherはマイクロサービスの代わりにPub/SubからPullし, gRPCリクエストに変換してマイクロサービス側のエンドポイントを叩いてくれます。
gRPC Pusherを使うことでメルペイのエンジニアは、Pub/SubのSubscriberロジックを慣れ親しんだgRPCエンドポイントとして実装でき、Pub/Subという特定のInfrastructureを意識しなくて良くなります。
今回はこちらのgRPC Pusherを利用するためのInfrastructureリソースをTerraformで作成し、 個人情報難読化を行うロジックはgRPCエンドポイントとして実装を行いました。
ただ、gRPC Pusherを使うならいろいろと考えるべきことがあります。
Pub/SubのPull型Subscriptionの大きな利点は、Pullする側のスケールやワークロードの都合に合わせて処理を実行できる点にあります。gRPC Pusherはその都合をPullするマイクロサービスの代わりに受け持っていると考えることもできます。
Kubernetesをはじめとしたスケーリング技術は、必要になった時にすぐにスケールするわけではないので、ワークロード量によってはgRPC Pusherの使用は適切でない場合もあります。しかし、PII Deletionのリクエストはスケールが追いつかないほど大量のリクエストが飛んでくることは想定し難いため、gRPC Pusherの使用を決断しました。
全ての個人情報を難読化するところまでは完了できませんでしたが、 基本的なロジックは全て実装し終えました。
学んだことと感想
ハード面
使用した技術としては以下です。
- Kubernetes
- Terraform
- Google Cloud (Pub/Sub, Secret Manger, Spanner)
- gRPC
- Go
どの技術も触ったことはあったものの深く触ったことはなかったので勉強になりました。
特にTerraformには興味があるので、 大学院の研究が落ちつく7月は何かしらのProviderを自前で実装するつもりです。Kubernetesに関しても基本的な概念やリソースの役割のみならず、 カスタムコントローラの実装等、 面白い部分はたくさんあるのでこれからさらに深く勉強していこうと思います。
また、 Payment Serviceのソースコードは大規模かつ複雑だったので読み解くのに苦労しましたが、 パフォーマンスと冪等性を意識した設計になっているのでとても勉強になりました。
ソフト面
インターンを通して自身の英語スキルが向上したと感じました。
Payment Coreチームでは、 チームのStandupも月曜日から木曜日は全て英語で行われます。
また、私が参加していたPII Deletion ProjectのMeetingやGitHub上のやり取りも基本全て英語ですし、最終成果発表も全て英語で行いました。普段の業務から英語と身近に触れられたことは自身の成長に大きく繋がったと感じています。
それから, チームメンバーはもちろん、他のチームの方々ともコミュニケーションを積極的にとることも心がけました。チームメンバーはもちろんのこと、他チームの方々も私に親切にしてくださり最終成果発表にも参加してくださいました。
インターンシップを通じてメルカリのカルチャーを存分に味わえて本当に楽しかったです。
メルカリグループは全社的にAI活用を推進しており、私も積極的にAIを活用しました。私は以前からAIを使ってソースコードを生成することに違和感を覚えていました。
Junior EngineerはIntermediate、 Seniorとタイトルを上げていく必要があります。タイトルはエンジニアの各ソースコードのレベルだけで決まるわけではないですが、当然相関はあります。Juniorである私がAIを使ってソースコードを書いてしまったら、成長する機会がなくなりいつまで経っても自らのスキルが伸びないのではないか?と考えていました。
ですが、Payment Serviceの莫大なドメインと複雑なソースコードを理解するには到底2ヶ月では足りないため、効率の良いキャッチアップが必要です。チームメンバーに相談してみると、彼らは皆AI(Cursor)を使って効率よくドメイン知識を吸収したり、UnitTestを書いたりしていました。彼らの助言を受けて私もインターン中にCursorを徹底的に活用し、AIと協調して、今までよりもより本質的な作業に時間を使えるようになりました。
AIを使用しても出力されるコードや価値は本人の能力にキャップされるため、依然として強くなるために勉強は必要です。
私が最初に抱いていた違和感は今でも間違っていないと思います。
しかし、成長する機会は自分でいくらでも作り出せるので、仕事と成長をイコールで結ばず両方全力で取り組めば、より早く、より大きな価値を届けられるエンジニアになれると考えを改めました。
インターンを通して最も大きく変わった部分はここだと思います。
最後に
チームメンバーをはじめ、たくさんの方々にお世話になりました。
メルカリのカルチャーを存分に体感しながら技術的に難しい課題に取り組まさせていただき、本当に感謝しています。
2ヶ月間ありがとうございました。