メルカリ ハロの技術スタックとその選定理由

こんにちは。メルカリ ハロのSoftware Engineer (Engineering Head)の@napoliです。連載:Mercari Hallo, world! -メルカリ ハロ 開発の裏側-の2回目を担当させていただきます。

2024年3月上旬にメルカリ ハロという新しいサービスが公開されました。メルカリ ハロは好きな時間に最短1時間から働ける「空き時間おしごとアプリ」です。

この記事ではメルカリ ハロを作るにあたり、どういった技術スタックやアーキテクチャを選定したのか、さらにその背景と意思決定をご紹介したいと思います。

この記事で得られること

  1. メルカリ ハロで採用されている技術スタックやアーキテクチャの全体像
  2. その意思決定の理由とプロセス
  3. これから新規サービスを立ち上げるうえでのヒント

主な技術スタック

メルカリ ハロで利用されている主な技術スタックは以下のとおりです。

  • バックエンド

    • Go
    • Google Cloud Platform (GKE, Cloud SQL for PostgreSQLなど)
    • GraphQL
    • gqlgen
    • ent.
  • フロントエンド

    • React / TypeScript
    • Next.js
    • Apollo Client (React)
  • モバイルアプリ (メルカリ ハロ専用アプリ)

    • Flutter / Dart

また、バックエンドのアーキテクチャとしてはモジュラーモノリスを、リポジトリの管理方法としてはmonorepoを採用しています。

モジュラーモノリス (Modular monolith)

メルカリグループとして「スポットワーク領域」と呼ばれる領域に参入するため、2023年4月頃に新しいチームを立ち上げました。発足当初はあくまで「PoC (Proof of Concept)」という立ち位置で、この領域でメルカリならではの価値を提供できるかどうか、その検証をしてからサービスを成長させていくという戦略で進められたため、サービスを少ない人数で急速に立ち上げることが求められました。(最初期はエンジニアが1~2名ほどしかいませんでした)

こういった背景を踏まえ、バックエンド(サーバ)はモジュラーモノリスのアプローチを採用しました。メルカリグループの主力サービスであるフリマアプリ「メルカリ」は成長過程でモノリスからマイクロサービスに進化してきました。モジュラーモノリスはこれら2つのアプローチの中間に位置する戦略で、端的に言うとモノリスシステムの中にマイクロサービスの戦略を統合する考え方です。結果的に、この選択は正解だったと思います。

容易なサービス間連携

モジュラーモノリスではひとつのサーバにAPIサーバとして求められるすべての機能を含めます。すべての機能は同じプログラムで動いていますが、サーバの中では実際には「モジュール」という単位で機能は独立しています。そして各モジュールが連携することでAPIとしての機能を提供しています。(「モジュール」はメルカリ ハロでは実際には「サービス」と呼んでいます)

ここでいうひとつとは「サーバプログラムとしてひとつ」という意味です(「デプロイの単位としてひとつ」とも言えます)。ひとつのサーバにすべてのサービスが実装されているため、当然ながらサービス間のRPC (Remote Procedure Call)は不要です。ひとつのAPIを提供するために複数のRPCを利用する可能性のあるマイクロサービス アーキテクチャとは異なり、プログラム内で関数を呼ぶことで機能を完結させることができます。サービス間のプロトコル定義やネットワークエラー時のハンドリングなどを考慮する必要がなくなり、実装量や設計の難易度を大幅に減らすことができます。

単一のデータベースとトランザクション

バックエンドがモジュラーモノリスであることに加え、メルカリ ハロではメインとなるデータベースのインスタンスはひとつです。この構成の場合、データベースのトランザクション機能をフル活用することができます。メルカリ ハロにおいてもお給料に関する情報など、データの整合性が重要なケースがあります。その点でデータベースのトランザクション機構はやはり非常に強力で、マイクロサービスアーキテクチャで大きな悩みごとであったサービス間のデータ不整合の問題の大部分を気にしなくて良くなります。こちらも実装量と設計の難易度を大いに減らしてくれました。

少ないインフラの記述量

メルカリ ハロではIaaSとしてTerraformを採用しています。モジュラーモノリスは基本的に1つのサーバで運用するためマイクロサービスと比較してインフラ関連の記述量を減らすことができます。APIなどアプリケーションに専門性を持つエンジニアにとってはインフラの設定やその動作確認は思ったよりも時間が掛かることが多いと思います。少ない記述量でAPIの実装に集中できることはメルカリ ハロのクイックな立ち上げにおいて大きなメリットがありました。

気をつけるべきこと

モジュラーモノリスはメルカリ ハロにおいて良い選択肢だった一方で、気をつけるべきこともあります。

大きな懸念のひとつは初期設計の難易度が上がりやすいという点です。何も考えずに作ってしまうと、単なるモノリスなシステムになってしまう可能性が大いにあります。正確に言うとモノリスであること自体が問題なのではなく、システムのモジュールやサービスが適切な責任範囲で分離されていないことが大きな問題になり得ます。適切な分離が行われていないシステムでは機能の再利用が難しかったり、一部の改修が思ってもみないところに影響を及ぼしたりします。複雑に相互依存した(絡み合った)システムは理解も難しいですし、テストも難しくなります。理解もテストも難しいということは障害が発生する可能性も高くなるということです。結果として時間が経てば経つほどスピーディな機能開発が困難になってきます。

マイクロサービスアーキテクチャの利点の一つは、この「モジュール/サービスの分離」がインフラレベルで「強制される」点だと思います。プログラムの単位が違うことに加え、データベースも一般的にはマイクロサービスごとに独立していることが多いため、あるサービスの変更は別のサービスには直接影響を与えません。もちろんどの粒度でマイクロサービスを分けるかにも依りますが、開発者は半ば強制的に「モジュール/サービスの適切な単位」を考えなければいけません。サービスとして独立しているため、責任範囲が明確にもなりやすいです。大規模組織にも相性が良く、例えば「このマイクロサービスはこのチームがオーナーを持つ」と言った戦略を取りやすくなります。

一方で、モジュラーモノリスではこの「強制」が良くも悪くもありません。ですが「モジュール/サービスの適切な分離」はマイクロサービスと変わらず重要な関心事です。モジュラーモノリスでは初期の設計者が慎重に設計を行い、各開発者が節度と理解を持って機能を実装していく必要があります。この点に難しさがあると思っています。

とはいえ、メルカリ ハロのように一定規模の新規プロダクトをクイックに開発するうえではモジュラーモノリスはおすすめできるアプローチだと思います。最初から大規模になることが約束されたプロダクトを作るのであればマイクロサービスアーキテクチャのような分散システムを採用するのも効果的だと思いますが、ほとんどの場合、システムを物理的に分離させるのはビジネス的にもプロダクトの規模が大きくなってからでも遅くはないでしょう。

なお、メルカリの別プロジェクトにおいてもモジュラーモノリスの採用例があります。メルカリ ハロの事例とは異なる「既存のモノリスからモジュラーモノリスへ移行する」というアプローチですが、こちらも参考にして頂ければと思います。
メルカリの取引ドメインにおけるモジュラーモノリス化の取り組み

monorepo

メルカリ ハロではmonorepoを採用しています。monorepoは、バックエンドやフロントエンドなど、システムを構成する複数のコンポーネントの独立性を保ちつつ、全てのコンポーネントをひとつのリポジトリで管理する手法です。

monorepoを採用してよかったと思う点をいくつか挙げてみます。

システム全体の見通しの良さ

monorepoはシステムに必要なコンポーネントが全てひとつのリポジトリに集約されていることが大きな特徴です。これはシステム全体の見通しがとても良くなります。メルカリ ハロの立ち上げ期は開発メンバーの数が少なかったため、ひとりのエンジニアがバックエンドやフロントエンド、モバイルアプリを横断して実装することもありました。その際にコードが集約されていることは開発のしやすさに大きなアドバンテージがあります。「フロントエンドの仕様どうなっているんだろう?」といった確認を行いときに、自身のIDEやEditorのファイル検索機能を使えばすぐ該当の実装に辿り着きます。「別リポジトリに切り替えて、git pullして、ウインドウを切り替えて…」といったことをする必要がありません。言語の違いによる理解の難しさは当然ありますが、素早くシステム全体を調査することができます。

コードレビューのやりやすさ

ひとつのGitHubリポジトリ上にプルリクエストが集まるため、異なる職種間でもレビューがしやすくなります。専門的な実装に関しては専門の知識を持つメンバーがレビューしたほうが良いですが、簡単な修正なら他の職種でも可能なことが少なくありません。メルカリ ハロではmain branchへのマージはプルリクエストへのApproveを必須としているので、レビューの速さは重要です。mainにマージできるまでの時間が短いとコンフリクト解消に掛ける時間も減り、QAもしやすく、本質的な作業に集中しやすくなります。もちろん複数レポジトリ(Multi Repository)でもできないことはないですが、monorepoのほうがやりやすいのは間違いないと思います。

GraphQLスキーマファイルの共有

メルカリ ハロではバックエンドとフロントエンド/モバイルアプリとの通信に(後述する)GraphQLを採用しています。バックエンド側で生成したGraphQLのスキーマを同一のリポジトリで共有できるため、それをもとにフロントエンドのGraphQLのクライアントコードを自動生成したりなど、楽に連携をすることができました。GraphQLスキーマファイルに限らず「必要なファイルをリモートから取得する必要がない」というのは何かと便利ですし、開発環境が安定します。

一緒に開発している感

急にふんわりとした話になってしまいますが、バックエンドやフロントエンドといった職種間でもなんとなく「一緒に開発している感」が出るような気がします。「システム全体の見通しの良さ」にも繋がる話ですが、他の職種の人達がどういった頻度、温度感で日々作業しているかがわかりやすくなります。この感覚は密にコミュニケーションが必要な開発では意外と重要だと思います。目には見えなく数値化しづらいですが、メルカリ ハロの開発体制では良い効果をもたらしていたと思います。

monorepoのリポジトリ構成

メルカリ ハロではGo, dart, TypeScriptが主な言語として使われており、リポジトリルートの直下に各言語ごとにディレクトリを配置しました。これによりエコシステムやCI/CDの管理をしやすくなります。また普段の開発においても、例えばバックエンドを開発する人間は基本的にgoディレクトリ以下のみに絞って作業することができ、同じリポジトリでも独立した環境のように開発できるメリットがあると思います。

独立したビルド環境

メルカリ ハロのmonorepoではバックエンドやフロントエンドなどの各コンポーネントでのビルドの手段は基本的に独立しています。Bazelのようなビルドを一元的に管理できるツールもありますが、メルカリ ハロでは採用していません。幸いなことにメルカリ ハロの立ち上げ期には各職種で専門性の高いメンバーが居たため、馴染みのある(標準的な)ビルドの手法を採用していました。各メンバーにとっては追加の技術を学習するコストがない分、スムーズにビルド環境を構築できたと思います。運用面でも今のところ大きく困ったことはありません。コンポーネント間でビルドを一元的に管理する手法はメリットもありつつ、かなりの難しさもあるため、明確な理由がなければ各コンポーネントごとに独立してビルド環境を構築するアプローチのほうがおすすめできるかなと思います。

monorepoについて、いくつかのメリットやメルカリ ハロでの具体的な構成例を挙げました。monorepoの一般的なデメリットはリポジトリサイズが大きくなりやすいところですが、昨今のネットワーク環境やローカル環境を踏まえると相当に大規模なサービスにならない限りほぼ気にすることは無いかなと思います。他にも細かいデメリットはありますが、総じてメリットのほうが大きく上回っていると感じます。新規サービスの立ち上げにおいてはおすすめできるアプローチだと思います。

インフラの全体像

メルカリ ハロではインフラストラクチャにGoogle Cloud Platformを全面的に採用しており、簡単な全体像は以下のようになっています。

バックエンドとなるGraphQLサーバ(Go)はGoogle Kubernetes Engine (GKE)を利用してひとつのサーバとして動いています。同じくNext.jsと、APIの前段となるGateweyもGKE上で動いてます。データベースはCloud SQL for PostgreSQL、メモリストアにはRedisを利用しており、CDNはFastly、 画像最適化(変換)サービスにはCloudflareを採用しています。

Google Kubernetes Engine (GKE)

メルカリ ハロではバックエンドのインフラにGoogle Kubernetes Engine (GKE)を採用しています。主に下記の2つの理由で選定を行いました。

メルカリグループでの実績とノウハウ

メルカリグループでは多くのサービスをGKEにて運用しており、Platformと呼ばれるチームが運用・保守を行っています。一般的にGKE(kubernetes)はインフラを専門としないエンジニアにとっては難解なことも多いですが、メルカリグループでは初期設定や開発を効率的に行うためのツールやドキュメント、ベストプラクティスが充実しており、Platformチームからの手厚いサポートを受けることもできるため、この点において困ることは比較的少なかったと思います。

エコシステムとの統合

メルカリグループの多くのサービスがGKEを採用しており、同じクラスタ内でgRPCによるサービス間通信を行っています。これにより、既存のサービスをセキュアかつ効率的に利用することが可能です。メルカリ ハロはいくつか既存のメルカリのマイクロサービスを利用する必要があったため、簡単かつセキュアにサービスを利用できることには大きなアドバンテージがありました。

他の選択肢

上記のとおり、メルカリ ハロではグループ内のサポートが充実していたことと、既存のエコシステムとの連携が重要だったためGKEを選択しました。ただ、やはり構築と運用において難易度の高さはあるため、ゼロから独立したサービスを作る場合や、専門のエンジニアが居ない場合はCloud Runのような構築や運用が簡単なServerless環境も選択肢としては大いにありだと思います。

バックエンド / Go

バックエンドの実装はGoを採用しています。メルカリグループでの標準的な言語であり、メルカリ内で開発を行う上ではノウハウやリソースアロケーションの面で多言語と比べ圧倒的な優位性があります。また、API開発に適した言語であり、実行速度が速く、Go routineによる並列処理は非常に強力です。

シンプルで読みやすいことも良い点で、そのシンプルさゆえに誰が書いても同じようなコードになります。これは多人数開発ではメリットが大きく、実装の理解やコードレビューの負担を大きく下げてくれます。コードに問題がある場合も比較的気付きやすいと思います。

複雑なコードは、たとえ自分自身が書いたコードでも何を意図してそうしたのか、時間が経つとすぐ分かりづらくなります。そういった意味では「書き手より読み手にやさしい」言語かもしれません。読み手に優しいことは長期的にサービスを運営するうえで大きなアドバンテージになります。コードというのは時間が経てば経つほど「書かれている時間より読まれている時間のほうが長くなるもの」だからです。

個人的にもGoは好きな言語なので、仮にメルカリ以外でAPIを開発するとなっても当分は最有力候補になると思います。

Cloud SQL for PostgreSQL / ent. / atlas

DatabaseにはCloud SQL for PostgreSQLを採用しています。メルカリグループではGoogle CloudのSpannerを採用するケースが多いのですが、以下の理由でCloud SQL for PostgreSQLを採用しました。

学習コストの低さ

PostgreSQLのようなRDBMSの知識や経験を持つエンジニアは多く、そういったエンジニアとっては新たに学習すべきことは少ないです。それはつまり新しいメンバーが開発に入りやすく、即戦力になりやすいということに繋がります。

充実したエコシステム

PostgreSQLは歴史が長く、サードパーティ製のツールやライブラリが豊富です。ツールやライブラリが豊富であることは効率的な開発に繋がりやすく、小さくないアドバンテージとなります。高機能なGUIツールも提供されているため、データを直接調整しながらデバッグを行いたいときなどに非常に役に立ちます。

ポータビリティ性

PostgreSQLはDockerイメージとして提供されており、ローカルのDocker上で簡単に動かすことができます。そのためデータベースを利用するユニットテストもやりやすくなりますし、ローカルでもリモートの開発サーバと近い環境を構築しやすくなります。

メルカリ ハロのサービス特性

メルカリ ハロのサービスの特性上、Readが多く、Writeは比較的少ないです。そのため単一のインスタンスでも相当な期間、問題なくWriteを捌けるだろうと判断しました。ReadにおいてはRead replicaを必要に応じて増やしていくことでかなりのトラフィックを捌けるだろうと考えています。

一般的にはこれらに加えて「初期コストの低さ」もメリットになりうると思います。メルカリ ハロでは当初から一定以上の規模のお客さまを想定していたためあまり判断の基準にはなりませんでしたが、多くの新規サービスにとっては重要な観点ではないでしょうか。

ORM

ORM(Object-Relational Mapping)としてはent.を採用しています。Go言語向けの強力なORMフレームワークであり、メルカリグループ内でもいくつか採用事例があることから採用しました。コードファーストのアプローチを取っており、高度なクエリ生成機能もあるので、効率的にGoからDatabaseの操作を行えていると感じます。

一般的にはORMを採用すると最適化された柔軟なクエリを書きづらくなりますが、メルカリ ハロでは基本的に非常にシンプルなクエリの組み合わせでAPIを実現しています。その分クエリの発行数が冗長になることもありますが、一方で「理解しやすく、実装しやすい」という大きなメリットがあります。冗長なクエリが多いと心配なのはパフォーマンスですが、基本的にReadの処理はRead replicaを増やすことでスケールしますし、アクセスの頻度が相当多いAPIで無い限り、インデックスさえ適切に貼られていればクエリの数を多少増やしても問題になることはほぼありません。シンプルなクエリは正しくインデックスを貼るのも楽です。実際においても、いまのところメルカリ ハロはデータベースのパフォーマンスは大きな問題にはなっていません。

データベース マイグレーション

データベースのマイグレーションにはatlasを採用しています。ent.もauto migrationの機能を持っており、差分のDDLを自動で適用してくれたりしますが、いざサービスの運用が始まるとent.のauto migrationだけでは要件を満たさないケースが多く、基本的にはatlasによる管理に統一しています(本番環境においてent.のauto migrationはOffにしています)。atlasはent.と連動してスキーマの差分を自動的に生成してくれるなど、強力な機能を持っており、効率的にmigration作業を行うことができます。DMLにおいてもatlasを使って一部migrationしています。

GraphQL

モバイルアプリ含むフロントエンドとバックエンドとの通信にはGraphQLを採用しています。GraphQLはAPI開発においてモダンな選択肢のひとつであり、世の中の多くのサービスでも採用されています。フロントエンド側でフェッチするデータを動的に制御することができ、フロントエンドの仕様が変更になった際もバックエンド側の修正が不要になるケースもあります。クエリをネストすることができるため、フロントエンドはその画面において必要な情報の多くをひとつのAPI Callで取得することができ、不要なAPI Callを減らすことができます。また、静的な型システムを持つスキーマによってI/Fが定義されるため、バックエンドとフロントエンド間で厳密なデータのやりとりすることができます。IDE/Editorによる補完が効きやすいところも嬉しいポイントです。

gqlgen

バックエンド側ではGoのGraphQLサーバ実装のひとつであるgqlgenを採用しています。シンプルかつ必要十分な機能が揃っており、学習コストも低く使いやすいと感じます。

gqlgenはスキーマファーストのフレームワークであり、基本的にひとつのスキーマファイルでQuery/Mutationを定義するスタイルのため、メルカリ ハロでもひとつのSchemaファイルにすべてのQuery/Mutationが集約されています。そのため現時点でもかなり行数の多いファイルになっており若干の扱い辛さを感じるときもありますが、graphql-eslintを導入してファイルを自動整形したりアルファベット順にType/Query/Mutationを自動ソートするなどして、できるだけメンテナンス性が落ちないように工夫しています。

一方で、スキーマがひとつのファイルに集約されているメリットも多いと思います。見通しが良く、コード自動生成もしやすく、他チームにメルカリ ハロが持つAPIを紹介する際も「このスキーマファイルを見てください」と言えば済むこともあります。

シンプルで扱いやすいPlaygroundが提供されている点も大きいと思います。Playgroundを使うと実装したGraphQLのQuery/Mutationを実際に試すことができます。入力の補完が効いたりQuery/MutationのAPI Reference(Document)も自動で生成してくれます。これが非常に快適で、デバッグや動作確認でとても役立っています。gqlgenでは複雑な設定もなく簡単にPlaygroundを構築することができます。

一方で、gqlgenに限らずですが、GraphQLサーバ実装においてはいわゆるN+1問題に気をつける必要があります。この点においてはRESTなど比べて学習コストと実装コストはやや増えますが、GraphQLを採用する上でそこまで大きなデメリットにはならないかなと思います。対処法としてはdataloaderの採用が一般的で、メルカリ ハロではgraph-gophers/dataloaderを採用しています。

なお、メルカリグループで広く採用されているプロトコルにProtocol Buffers(gRPC)があり、こちらも優れた機能を持っています。ただ一般的なWebサービスを作るうえでは、フロントエンドとバックエンド間の通信プロトコルとしてはGraphQLのほうが総合的に扱いやすいのかなと感じます。(もちろんどういったサービスを作るかにも依りますが)

あとはRESTも候補になり得ますが、今の時代、明確な理由がない限り敢えてそれを選択するメリットは少ないかなと思います。

React / TypeScript / Next.js

メルカリ ハロではWebベースのフロントエンドも実装されています。メルカリアプリ内の「はたらく」タブはWebViewで提供されており、事業者様向けの「事業者管理画面」もPC向けにWebベースで提供されています。


メルカリアプリ内「はたらくタブ」と事業者管理画面

Reactの採用はすぐに決まりました。メルカリグループの他のプロジェクトで採用されているという点で、Vueも候補に挙がりましたが、初期の開発メンバーがReactに慣れていたことと、作りたいサービスに対して十分な機能を備えており、効率的に開発を進められるだろうと判断して採用しました。業界的なトレンド、人材のプールという意味でもReactにアドバンテージがあるだろうと判断しました。

TypeScriptについても迷うことはありませんでした。フロントエンドにおいても昨今の開発では静的型付けは必須と言って良いですし、開発を効率的に進めていく上でさまざまなメリットがあります。Javascriptと比較して若干の難しさはあるかもしれませんが、いまや情報も豊富ですし、一定以上の知識や経験がある開発チームにおいてはほぼ問題にならないでしょう。

Next.jsはメルカリグループでの利用実績や使いやすさ、Reactをベースとしていること、パフォーマンスの良さなどから採用を決めました。

「はたらく」タブに関しては、メルカリアプリとして高いレベルの体験の良さが求められるので、必然的に描画速度も求められます。いまはまだそこまでフル活用されていませんが、Next.jsはパフォーマンス向上のための設定が柔軟にできるため、今後必要に応じて積極的に活用していきたいと思います。

GraphQLのClientとしてはApollo Clientを採用しています。Web フロントエンドにおける人気のフレームワークのひとつで、優れた機能を豊富に持っており、効率的に開発を進めることができます。社内でも採用実績があったため今回も採用しました。Reactとの統合にはReact Hooksを利用しています。

Flutter / Dart

メルカリ ハロはメルカリアプリ内のサービスだけでなく、iOS/Android向けの独立したモバイルアプリも提供しています(ストアで「メルカリ ハロ」と検索してみてください)。


メルカリとは独立した「メルカリ ハロ」アプリ

その基盤としてFlutter / Dartを採用しています。開発初期の検討時点では他にも以下の選択肢がありました。

  1. iOS / Androidネイティブ (Swift/Kotlin)
  2. React Native
  3. WebViewベースのアプリ

モバイルアプリの技術選定にはWebフロントエンドに比べかなり時間がかかりました。それぞれ同じくらいメリット/デメリットがあり、特に1. 2.についてはメンバーや立場によって意見が様々で、メルカリ ハロのチームだけでなく、メルカリグループ横断的に議論を重ねる必要があったため、決断が難しかったです。主に以下のような点が論点となりました。

  • 開発コスト
  • メンバーの習熟度
  • パフォーマンス
  • 社内的なリソースアロケーション
  • サードパーティ製のライブラリを含む、エコシステムの充実度
  • 採用のしやすさ
  • メルカリグループとしてのノウハウの集約/分散

色んな論点はありましたが、その中でもやはり「開発コスト」はとても大きな関心事でした。開発初期のチームのメンバーは少なかった一方で、やはり昨今の市場状況を踏まえてクイックなリリースが求められていました。iOS/Android両方をネイティブで開発するとなると単純に考えて2倍近くのコストが掛かりますし、両プラットフォームを同じタイミングでリリースできるとも限りません。チームとしては独立した専用のモバイルアプリの提供と、iOS/Android同時リリースはなんとしても達成したかったため、ネイティブでの開発はスケジュール面でのリスクが大きいと感じていました。

一方で(メルカリ ハロアプリではなく)メルカリアプリはiOS/Androidネイティブで実装されています。リソースアロケーションという意味ではメルカリグループ内では圧倒的な優位性がありました。社外にも当然ながら開発できる人は多いです。しかし前述のとおり初期メンバーは数が少なく、当時は様々な事情により他のチームからメンバーを確保できる保証もありませんでした。(なお、US版のメルカリはReact Nativeで実装されており、こちらもノウハウの面で優位性がありました)

パフォーマンスについて懸念する意見もでました。この点についてはiOS/Androidネイティブが一番優れていることに議論の余地はありません。「Flutterのようなクロスプラットフォームで作っても結局ネイティブで作り直す必要があるのではないか」といった指摘もありましたが、現時点では最高のパフォーマンスを追求するよりもまずはリーズナブルにサービスを立ち上げ、お客様に利用してもらうことが何より大事だと判断しました。幸いにもサービスの特性上、iOS/Androidのパフォーマンスをフルに求められるケースは今のところ多くありません。なお、「メルカリアプリ」もサービス開始してから4年ほど経った頃にフルスクラッチでアプリを再開発しています。まずはサービスがそこまで軌道に乗ることが大事ですし、数年後にやってくるかもしれない再開発のタイミングで必要があればiOS/Androidネイティブに切り替えるでも良いだろうという判断になりました。

最終的にはこれらの論点を総合的に踏まえ、Flutterがメルカリ ハロにとっては一番マッチしそうという判断をしました。

メルカリ ハロというサービスだけでなく、メルカリグループとしてみたときにこの判断が本当に正解だったかは今も分かりません。ただ現状から考えると開発コストやパフォーマンスなど、総合的にバランスの取れた開発環境になっていると感じるので、妥当な決断だったのかなと思っています。

おわりに

メルカリ ハロで使われている技術スタックやアーキテクチャ、その意思決定に至るプロセスについて、ほんの一部ではありますが簡単にご紹介しました。

新規サービスを立ち上げるうえで技術選定は非常に難しいことだと思います。ビジネスを成功させるために様々な観点から意思決定を行う必要があります。さらに一度決めたものをあとから変更するのは現実的に不可能なことがほとんどであるため、責任は重大です。ただ、同時に多くのエンジニアにとって「楽しく、やりがいのある瞬間」でもあるはずです。

会社の規模やそれぞれの状況によって判断の基準が変わってくるため正解はありませんが、メルカリ ハロではこのように技術選定してきました。これからサービスを立ち上げるみなさんにとって少しでも参考になれば幸いです。

Links

連載:Mercari Hallo, world! -メルカリ ハロ 開発の裏側-

メルカリではメンバーを大募集中です。メルカリ ハロの開発やメルカリに興味を持った方がいればぜひご応募お待ちしています。詳しくは以下のページをご覧ください。

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加