こんにちは。メルカリのSoftware Engineerの@tanashoです。連載:Mercari Hallo, world! -メルカリ ハロ 開発の裏側-の6回目を担当させていただきます。
メルカリ ハロのWebアプリケーションは複数存在し、Webフロントエンドチームが横断的に開発をしています。本記事では、その前提を踏まえ、スピードと品質をどのように両立させて開発しているかを紹介します。
プロジェクトの概要とWebフロントエンドの担当領域
メルカリ ハロは「あたらしい出会いを繋ぎ、信頼と機会をひろげる」がミッションで、いますぐ働き手が欲しいパートナー (事業者) と、いますぐ働きたいクルー(働き手)を繋げるサービスです。クルーは自身のスキルや時間を活用して働くことができます。
メルカリ ハロは複数のアプリケーションが存在し、そのなかでWebフロントエンドが関わる領域として以下の3つがあります:
- はたらくタブ
- 事業者管理画面
- CS Tool
それぞれのアプリケーションの概要は以下の通りです。
はたらくタブ
「はたらくタブ」は、メルカリアプリ内に用意されている、クルーを対象とした機能です。「はたらくタブ」は、スポットワークの経験がない人や、時々働きたいライトなユーザーに向けた機能で、この機能を使うことで、メルカリ ハロの専用アプリと同様に仕事を見つけて働くことができます。またすでにメルカリを使っているお客さまにも利用していただくことで、「メルカリ ハロ」の迅速な認知拡大が期待されています。
関連記事:『メルカリ ハロ』の成長を加速させる最重要タッチポイント、「はたらくタブ」はこうしてつくられた
この「はたらくタブ」はiOSおよびAndroidのメルカリアプリ内のWebView上で動作します。各OSごとに開発する必要がなく、Web開発のみで対応できるため、開発工数を削減できました。
また、リリース時にはアプリストアの審査が不要となるため、柔軟にリリースを行うことが可能です。
さらに、既存のメルカリアプリ内に存在するためアクセス数が多い特徴もあります。
事業者管理画面
事業者管理画面は、メルカリ ハロにおける求人や募集の作成など、パートナー向けのWebアプリケーションです。権限管理が必要な点や、フォームを使った登録・更新の機能が多い点が特徴です。
CS Tool
社内のメルカリ ハロのカスタマーサービス向けのWebアプリケーションです。
お問い合わせに対応するために、クルー検索などの機能が備わっています。
スピードと品質を両立して開発するための取り組み
メルカリ ハロを展開するにあたって、連載の最初の記事でも紹介したように、開発のスピードを重要視しています。これはスポットワーク市場の拡大の波に沿って事業を推進するためです。また、最初から正しい仮説を持つことは難しく、仮説の立案、検証、改善のイテレーションを高速に回すことが大事だからです。
またスピード感をもった開発が求められる一方で、高い品質を保つことも重要です。
現在、メルカリ ハロのWebフロントエンドチームは「はたらくタブ」「事業者管理画面」「CS Tool」の3つのWebアプリケーションの開発を担当しています。
この状況下でどのように工夫をして、開発スピードと品質の両立を達成しているかについてご紹介します。
柔軟なアサイン
「はたらくタブ」「事業者管理画面」「CS Tool」を開発するにあたって、特定のWebアプリケーションに優先度の高い機能開発の案件が集中することがあります。これに対応するため、Webフロントエンドチームでは特定のWebアプリケーションに担当を固定せず、横断的にアサインが可能な体制にしています。例えば、「事業者管理画面」に優先度の高い機能開発の案件が多くなった場合、その開発にリソースを集中させます。状況に応じて柔軟にアサインを変えられる体制にすることで、優先度の高い機能をスピード感もって開発することができました。
技術スタック・開発ルールを可能な限り統一
柔軟なアサイン体制の下で生産性と保守性を上げるために「はたらくタブ」「事業者管理画面」「CS Tool」の技術スタックやアプリケーションの構造、開発ルールなどは可能な限り統一しております。
ただし、技術的な問題、アプリケーションの仕様の違いなどにより、一部に差異が生じる箇所も存在しています。
「はたらくタブ」「事業者管理画面」「CS Tool」で扱っている主な技術スタックは以下の通りになります:
- Next.js (App Router)
- React
- TypeScript
- ESLint
- Apollo Client ※
- Tailwind CSS
- Storybook
- React Hook Form
- Jest
- Playwright
- pnpm
- Datadog
統一の結果、普段担当していない別のWebアプリケーションにアサインされた場合でもスムーズに開発を行うことができました。例えば「事業者管理画面」を開発していたメンバーが「はたらくタブ」の開発を任された場合でも、ほとんど同じ技術スタックや開発の作法を活用できるため、追加の学習コストを抑えて開発に取り組むことができました。また、開発ドキュメントもある程度共通化することができるため、ドキュメントの保守性も向上しました。
さらに、メルカリ ハロではmonorepoを採用(関連記事)し、異なるWebアプリケーションを同一リポジトリで管理しています※。これにより、Webアプリケーション間の行き来が容易になったり、lintのルールの設定などがpnpmのworkspaceを使って共有可能になりました。
...
├── dart
├── go
└── typescript
├── apps
│ ├── partner-portal-web //事業者管理画面
│ ├── work-tab //はたらくタブ
├── libs //共通の関数やlintのルールの設定
...
これらの取り組みによって開発生産性と保守性が向上しただけでなく、誰かが開発で困ったときに他のメンバーが助けやすい体制が整い、チームとして支え合う文化が一層強まったことも大きなメリットだと思います。
以降、その統一された技術スタックでどのように開発しているか紹介します。
UI開発
UI開発において生産性を上げるために社内のメルカリデザインシステム(関連記事)を採用しています。
メルカリデザインシステムはFigmaで提供されており、デザイナーはデザインシステム上のトークンやUIコンポーネントを参照して画面を作成しています。フロントエンド開発では、Figma上で使用すべきコンポーネントや色が明示されているため、迷わず開発できるようになっています。また、カスタムテーマの設定で、メルカリのデザインシステムのトークンをTailwind CSSに統合しています。これによって、レイアウトの調整やデザインシステムが提供していないUIコンポーネントを作成する際に、簡単に一貫性のあるスタイルを適用することが可能です。
メルカリデザインシステムにもとづいて画面を作成することで、UIコンポーネントの開発工数を削減し、デザイナーと開発者間でUIの細かい挙動についての認識も一致させやすくなりました。
さらに、デザインレビュー時にはプルリクエストの段階でテスト環境にデプロイし、その環境で画面の動作を確認してもらうことができます。実際の画面を操作することで、デザイナーと開発者の認識を更に一致させることができました。
バックエンドとのやり取り
メルカリ ハロのフロントエンドとバックエンドとのやり取りはGraphQLで行っており、そのAPI Clientとして社内で利用実績が多く、キャッシュ管理などの豊富な機能を持つApollo Client を採用しています※。ここで取り入れた仕組みや活用している機能についていくつか紹介します。
Apollo ClientのHooksを自動生成
ページに必要なAPIのフィールドをGraphQLのスキーマファイルをもとに定義し、Apollo ClientのHooksを自動生成しています。
monorepoを採用しているため、同一リポジトリ内のフロントエンドの開発ディレクトリからバックエンドの開発ディレクトリに配置されているGraphQLのスキーマファイルを直接参照でき、それをもとにApollo ClientのHooksを自動生成するといった仕組みです。
これにより、バックエンドからデータを取得する際には、その自動生成されたApollo ClientのHooksを呼び出すだけで済み、開発効率向上につながりました。また、ページに必要なデータのフィールドのみを取得し、APIの呼び出しも一回にまとめられるため、ネットワークのコストを抑えることができました。
Apollo Clientの機能の活用
Apollo Clientはデータ取得以外にも多くの機能を持っています。一例として、キャッシュの機能です。実行したqueryのレスポンスデータがローカルのインメモリ上にキャッシュされるため、そのキャッシュを活用することができます。例えば、useQueryのfetchPolicyがデフォルトのcache-first の場合ですが、fetch時にメモリにキャッシュが存在していたらそのデータを返します。ただし、存在しない場合はサーバーから取得します。キャッシュを優先しているため速度を重視する場合には有効かと思います。またこのfetchPolicyの設定は用途に合わせて変更可能です。
「事業者管理画面」では、データの表示速度も重要ですが、募集の応募状況など最新の情報を求められることが多く、データの新鮮さも重要です。そのため、キャッシュを活用しつつ、同時にサーバーから最新のデータも取得・更新するcache-and-networkの設定をデフォルトでしています。
さらに、Apollo ClientにはLinkという機能があります。これはApollo ClientとGraphQLサーバー間のデータフローをカスタマイズするための仕組みです。特にサーバーからのエラーハンドリングにおいてLinkを活用しています。例えば、Unavailableのエラーを返した場合にメンテナンスページにリダイレクトしたり、認証が切れたらtokenをリフレッシュする処理を実装しています。
モック開発
バックエンドのAPIが開発中であっても、フロントエンドの開発を進めたい場合があります。
その際に、まず先にバックエンドからGraphQLのスキーマファイルを共有してもらい、そのスキーマをもとにMSWを利用してAPIをモックし開発しています。この結果、フロントエンドとバックエンドが並列して開発でき、生産性の向上につながりました。
自動テスト
リグレッションの自動検知を目的に自動テストを導入しています。
導入にあたって自動テストに費やせる時間と人手では限られているため、効率的・効果的にリグレッションを防ぐためのテスト設計が必要でした。
そこで一つの観点として、他のチームよって品質が担保されているテストと被らないことを重要視しました。以下のテストに関してはすでに他のチームで行われていました。
- UIコンポーネントのテスト
- 前述の通り、メルカリ ハロのUIコンポーネントはメルカリデザインシステムを使っており、そのチームよって自動テストが行われている
- E2Eテスト
- QAチームが手動および自動で(フロントエンドからバックエンドまでの疎通を含む)E2Eテストを行っている
この観点のもと、Webフロントエンドでは以下の自動テストを設計・運用しました。結果として、他のテストでカバーできていないテストを書く運用になり、効率的に品質を担保することができました。
- 単体テスト
- Jestを利用
- 共通関数の詳細な挙動を担保するため、条件分岐を網羅したテストを実施
- ページ単位の統合テスト
- Playwrightを利用
- 機能が仕様通り動いているかを主にページ単位でテストを実施
- バックエンドへの通信を行わず、必要なAPIのデータはモックし、フロントエンドに閉じた形で実施
運用にあたって、単体テストについては、共通関数として切り出したときにテストを書く運用がチームメンバーに浸透していたため、特に問題はありませんでした。
一方でページ単位の統合テストに関しては、対象となるページ数が多く、様々なテストシナリオが考えられるため、どの統合テストを重視して書くべきかが課題でした。例えば、特定のレスポンスが返ってきた際のページの表示が正しいかどうか、入力したフォームのバリデーションが正しく動作するかどうかなどです。そのため、どのテストを優先して書けば大きな効果を発揮するか検討する必要がありました。
そこで「はたらくタブ」「事業者管理画面」「CS Tool」それぞれのアプリケーションの性質に合わせて統合テストの方針を決めました。
例えば「事業者管理画面」では、フォームをSubmitした後のAPIのリクエストが正しいかのテストを第一優先としました。これは管理画面の性質上、募集作成など重要なデータの作成機能が多いため、意図しないリクエストが送信されて登録されてしまうと大きな問題が発生するためです。
このように、他で品質が担保されていない箇所を単体テスト・統合テストで担保し、統合テストのなかでアプリケーションの性質に合わせて方針を決めることで、効率的・効果的にリグレッションを防ぐことができました。
おわりに
スピードと品質を両立させるためのWebフロントエンドの取り組みについて紹介しました。
「はたらくタブ」「事業者管理画面」「CS Tool」のアプリケーション間で可能な限り統一した技術を扱い、フロントエンドチームメンバー内で状況に応じた柔軟なアサインによって、お客さまが求める重要な機能をスピードと品質を両立させて開発し続けられる体制になりました。また、同じチームで性質の異なる3つのWebアプリケーションを経験することは、エンジニアにとって楽しく、やりがいのある挑戦でもありました。
更にこの体制によって、誰かが開発で困った場合でも他のメンバーが助けて支え合う「All For One」な文化が一層強まってると日々感じております。
その「All For One」な文化はメルカリグループ全体からも感じています。メルカリのデザインシステムがあらかじめ用意されていたり、 monorepo戦略がその一例です。自チームにとどまらず全体最適になるよう取り組んでくれたおかげで、この開発スピードと品質の両立が実現できてると感じてます。
この取り組みは終わりではなく、今後もチームやプロダクトの状況を見ながら、前向きに改善し続けることが重要です。引き続き、チームと話し合いを重ねて改善に努めていきたいと思います。
Links
連載:Mercari Hallo, world! -メルカリ ハロ 開発の裏側-
メルカリではメンバーを大募集中です。メルカリ ハロの開発やメルカリに興味を持った方がいればぜひご応募お待ちしています。詳しくは以下のページをご覧ください。
- Software Engineer, Frontend – Mercari/HR領域新規事業 (Mercari Hallo)
- Software Engineer, Backend – Mercari/HR領域新規事業 (Mercari Hallo)
- Software Engineer, iOS/Android (Flutter) – Mercari/HR領域新規事業 (Mercari Hallo)
- Software Engineer, Site Reliability – Mercari/HR領域新規事業 (Mercari Hallo)
- QA Engineer – Mercari/HR領域新規事業 (Mercari Hallo)
- Engineering Manager – Mercari/HR領域新規事業 (Mercari Hallo)