こんにちは。ソウゾウのSoftware Engineer(CTO)の@suguruです。連載:メルカリShops 開発の裏側 Vol.2の1日目を担当させていただきます。
去年、2021年に開始した メルカリShopsの技術スタック についての記事を書きましたが、今回はリリースまでに採用した技術スタックが、半年通してどのようにアップデートしてきたかを共有したいと思います。
ローンチ時に採用した技術が、実際の運用でどのように変遷したのかを共有することで、技術スタックを考える際の何らかの参考になれば幸いです。
monorepo
メルカリShops ではサービスに必要なコードを1つに集約する monorepo を採用しています。リリース後半年たってコード量はかなり増えてきましたが、monorepo に対する満足度は非常に高く、うまく機能しています。
サービス全体の見通しが良くなることと、すべてのソフトウエアエンジニアが常にサービス全体のコードを自然に最新に保つことができることが、チーム開発をしていく上でとても都合が良いことが多いです。
例えば、新しいチェックをCIなどに追加したときに、サービス全体のコードに浸透させることがとても容易なのです。技術のアップデートや開発方針などが常に全体に行き渡りやすくなることは、サービス全体の開発に大きな利点となっています。
メルカリShopsでは、言語ごとに Github Actions のワークフローが1つ存在します。このワークフローに手を加えることで、言語全体に関わるチェックや変更をサービス全体に浸透しています。
.github
└ workflows
├ ...
├ go.yaml
├ ...
├ java.yaml
├ ...
├ typescript.yaml
├ ...
├ python.yaml
Bazel
monorepo のビルドシステムとして Bazel を使ってきています。 Go, Python, Java 言語については Bazel でのビルドを活用しています。Java, Python については Bazel が壁となって難しくなる場面は何度かありましたが、Bazel でビルドが完結するというメリットは開発において大きな利点となっています。
一方で、 TypeScript は Bazel の利用を諦めました。いくつか理由がありますが、yarn workspace に対応していないため、レポジトリ拡大に伴って依存関係の問題の回避コストが高くなったからです。また、monorepo 内の様々なwebツール類を Bazel に対応するコストが大きいことも諦めた理由の1つです。
一部の言語だけを Bazel から除外することは全体の一貫性を失いますが、TypeScript の本来の開発にフォーカスすることができるようになり、後述する turborepo の導入を可能にしたため、結果としては良い選択でした。
Next.js と NestJS
メルカリShopsでは、フロントエンドに Next.js, BFF に NestJS を利用していますが、今の所大きな問題は起きていません。
NestJS で遭遇した課題としては、grpc に独自のラッパー層を持っているため、ピュアな grpc クライアントをDIに登録しているわけではないため、Client Interceptors などを利用する際に問題が起きることがありました。
Turborepo
Bazel を利用しない代わりに、TypeScript のビルドシステムとして Turborepo を導入しました。
turborepo は Next.js を開発している vercel が買収を発表したため、 Next.js を取り巻くビルドシステムとしての発展を期待して導入を検討しました。特に、独自のキャッシュシステムは、monorepo 環境でのビルド速度を大幅に改善することが期待できます。Bazel と同様のリモートキャッシュも備えており、ソフトウエアエンジニア同士やCIのタスク間でキャッシュを共有することができます。
Next.js だけでなく、バックエンドで利用している NestJS でも利用できますし、ビルドの依存関係も定義できるので今の所非常に便利かつ高速に動作しています。
turborepo はまだ発展途上で機能は限定的ではありますが、TypeScript monorepo のビルドシステムのデファクトになる可能性を秘めている技術だと感じています。
Serverless Architecture
メルカリ Shops は、Cloud Run を活用したサーバレスアーキテクチャでスタートしました。その後も様々な機能を開発してきており、kubernetes が持っているような機能があればいいなと思うことはありました。しかし、サーバレスの恩恵が大きいため、今後も Cloud Run を中心に展開していく予定です。
幸い、Cloud Run にもいくつかの機能追加(always-on CPUなど) が実施され、制約事項が少しずつ減ってきています。目下の課題は、サイドカー機能の不在です。クリティカルではありませんが、コンテナの運用やサービス間通信などでアプローチが必要なケースは増えてくるため、サイドカーの登場が待ち望まれます。
Microservices
Microservices は順調に増えており、2022年2月時点で約50の Microservices が存在します。チームはまだ小規模ですが、monorepo のおかげもあり、メンテナンスや存在が放置されるようなケースは起きていません。Microservice を作るためのコストを下げていることもあり、用途ごとに細かく分割されています。責務ごとの分割と、それによる Observability の向上の恩恵を受けています。
Microservicesの増加によって、docker-compose を利用して稼働していたローカル開発環境で、すべてのサービスを稼働させることは困難になってきました。今後は開発環境を改善し、Microservcies が増加してもローカルで手軽に動作確認ができる仕組みを検討中です。
Feature Toggles – Unleash
サービスローンチ後に、迅速で柔軟なデリバリーを行うために、 Feature toggles システムの需要が増してきました。メルカリ Shops では、Unleash を Feature Toggles のコアシステムとして採用しました。さらに、 Unleash をバックエンドサービスとして配置し、BFF のレイヤーから GraphQL を通して Feature Toggles を取得する方式を取っています。クライアント側が Unleash に依存しない方式を取り、Toggles のフェッチを BFF を通じて実行することが目的です。
また、Unleash のストラテジーをいくつか実装し、社内ネットワークやVPN経由のみでONになるフラグを用意したり、社員のデバイスだけ有効になるような仕組みも導入してフラグの利便性を高めています。
Enterprise Elastic Search
メルカリShops は検索システムを独自に持っておらず、メルカリ本体の検索を通じて検索機能を提供しています。しかし、機械学習の結果を活用するケースや、メルカリShops独自の検索方法(結果のスコアリング方法や独自プロパティの対応など)が必要になったため、内部にも柔軟な検索を可能にするシステムが必要になりました。
検索システムとしては Elastic Cloud 上に構築した Elastic Search クラスターにある App Search を使っています。 App Search は Elastic Search をよりシンプルな検索エンジンとして使うためのAPIを提供するプロダクトで、シンプルな REST API でドキュメントのインデクスや検索が可能になります。日本語形態素解析をサポートしていない(現時点ではbigramのみ)などの難点はありますが、とりあえず複雑な条件の検索が可能になるという点で Enterprise App Search を活用することにしています。
PostgreSQL
PostgreSQL は今の所問題なく CloudSQL 上で稼働していますが、やはりサービスを運用していく上で、メンテナンスウィンドウの存在が厄介です。メンテナンスウィンドウが存在しない、かつスケールアウトが柔軟に行えるDBの必要性は日々高まっています。
Cloud Spanner PostgreSQL Interface のような技術や CockroachDB Serverless などが登場してきており、選択肢は増えています。ただ、まだベストな移管先は決断できていません。
Visual Studio Code Remote Development
サーバー上で稼働するIDEとして code-server の環境を用意していましたが、結果として対応していないプラグインの存在や Visual Studio Code以外のIDE需要もあり、ローカル環境の方を好むソフトウエアエンジニアが多いというのが現状です。
Visual Studio Code Remote Development という機能があり、Visual Studio Code のプラグイン等の機能はそのままに、開発用のプロセスやツール類をサーバー上で稼働させることができます。Remote via SSHを使えば、Google Cloud Platform の提供する IAP経由でアクセスができるため、セキュアにクラウド上の開発環境を提供することができます。
ローカル環境を好むソフトウエアエンジニアが code-server や Visual Studio Code Remote Development を活用するためには、ローカル環境に近い開発柔軟性が必要だと感じているため、改善に取り組んでいます。
monorepo が巨大化し、全体のコードベースが大きくなると、クラウドIDEでの開発が必要となることは間違いありません。引き続きクラウド上でのIDE利用については改善と研究をしていきます。
まとめ
こうして見ると半年だけでも結構なアップデートがありました。技術とプロダクトは常に変遷していきます。こうしたアップデートができたのも、初期の技術スタックで考えすぎなかったことと、変化を前提として組んできたことが良かったと思っています。
技術スタックを考える際には、より柔軟に変化できることを念頭に考えておくことが大事だなと感じた半年でした。これからも技術スタックの改善を継続し、急速に成長していくサービスを支えていきたいと思います。
Links
ソウゾウではメンバーを大募集中です。メルカリShopsの開発やソウゾウに興味を持った方がいればぜひご応募お待ちしています。詳しくは以下のページをご覧ください。
- Software Engineer
- Software Engineer, Site Reliability
- Software Engineer, Machine Learning
- Software Engineer, QA Test
またカジュアルに話だけ聞いてみたい、といった方も大歓迎です。こちらの申し込みフォームよりぜひご連絡ください。