トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、モバイルオーダー「トレタO/X」などを運営するトレタの開発メンバーによるブログです。

トレタO/XのtoCアプリをリニューアルしたら諸々整理できてよかったという話

こんにちは、パパエンジニアのkentaroです.

2022年2月、トレタO/Xをご利用いただいているワンダーテーブルさまの「よなよなビアワークス」向けのモバイルオーダーアプリ(以下 toCアプリ と呼びます)をFlutter WebからReactにリニューアルしました。

なお、「トレタO/X」については代表のnoteをご覧ください。

note.com

背景

当時のtoCアプリはFlutter1系で作られており、いくつか問題点を抱えていました。代表的なことの1つはNullSafety対応されていないことです。もう1つは状態管理も現在デファクトスタンダードになっているライブラリ(Riverpod)への乗り換えが必要ということです。
(ちなみにスタッフ向けアプリはFlutter2系・NullSafety対応済み・Riverpod採用しています)
ほぼ作り直しとなることが見込まれたので機会を見計らっていましたが、iOS15でFlutter Webが動作しなくなったことがきっかけで一気に検討が進み、最終的にはReactで作り直すという意思決定をしました。

参考までにチームメンバーが作成してくれたIssueをご紹介します。当時もワークアラウンドで回避可能でしたが、これによりリニューアルの議論が進むきっかけになりました。

github.com

なぜReactなのか

当初はモバイルアプリ化する可能性があったため、Flutter Webを採用していましたが、その後の事業方針でtoCアプリはモバイルアプリ化しないことになりました。

他法人向けtoCアプリはAngularで作っていましたが正社員採用や業務委託契約による体制拡大を考えた際、より人を集めやすいReactで作り直すことになりました。

リニューアルプロジェクト

2021年9月からアプリのリニューアルプロジェクトが始動しました。

最初の1ヶ月程は開発環境の構築と並行し、Flutter版toCアプリの仕様策定や、複雑なロジックの図解をしました。
プロジェクト序盤に現状を整理して可視化したことにより、過剰に複雑になっていた仕様をできるだけシンプルにすることができました。振り返ってみた際にとても有効な取り組みだったと感じています。
例えばアプリ起動時の状態判定が複雑だったのですが、ここをある程度シンプルな形にできたため、メンテナンス性が向上しました。

そこから11月末までは実装フェーズでした。
フロントエンド開発が得意なメンバーはcomponentの量産に集中し、デザイナーと連携してUIの実装を推し進めてくれました。
自分は今回が初のWebフロントエンドの開発業務でしたが、Flutter版toCアプリの開発に携わっていたのでドメイン知識はチーム内でも豊富な部類でした。
そこでなるべくロジック寄りの実装を担当し、不慣れなWebフロントエンドの開発でも実装のスピードを落とさないように工夫しました。
メンバーそれぞれの強みを活かし、チームとしての成果を最大化できたと感じています。

12月・1月はQAとテストで出た不具合の対応をしつつ、残タスクの消化やリリース準備を行い、2月のリリースに漕ぎ着けました。

プロジェクトメンバー全員が何かしらのO/X別プロジェクトと兼任している状態ではありましたが、リリース遅延することなくやりきることができました。

React版で追加した機能

基本的にはFlutter版をReact化する、というプロジェクトだったのですが1つだけ新しい機能を追加しています。
これまでのクレジットカードによる支払いに加え、Apple Pay / Google Pay に対応しました!是非ご利用ください!

よなよなビアワークス向けトレタO/XのtoCアプリでApple Payボタンが表示されている画像

振り返ってみて

チームメンバーに「このプロジェクトを振り返ってみてどうでしたか?」というインタビューをしました。

プロジェクトマネージャー

  • PoCで手探りで作ってきた部分をきれいに作り直すいい機会だった
  • 転職市場やフリーランス市場ではFlutterエンジニアよりReactエンジニアのほうが多いので、長い目で見て保守しやすくなったと捉えている

デザイナー

  • 画面・コンポーネントの名前が人によって呼び方が人によって異なっていたが、それを統一できたためコミュニケーションがしやすくなった
    • 例: 「注文リスト」を「カート」と呼ぶ人もいたが、「注文リスト」に統一
  • 画面遷移フローの図をわかりやすくすることができた
  • コンポーネントの整理ができた

QA

  • FlutterのIntegration Testについて、当時のバージョンではWebに対応していなくて書けなかった
  • Webの多様なE2E Testing Framework使えるので、今後テストの自動化を進めていくことができる
  • 仕様整理しながらプロジェクトを進めることができた

エンジニア

  • (プロジェクトマネージャーと同じく)PoCで手探りで作ってきた部分をきれいに作り直すいい機会だった
  • O/Xを開発するにあたって理解しておくといいことをドキュメント化することができたので、今後新しいエンジニアが来てもスムーズにオンボーディングができそう

個人的な感想

  • 業務でのWebフロントエンドの開発に挑戦できた

この辺りの話は トレタO/Xの開発にジョインしてやってきたこと という記事の後半にも書いています。

tech.toreta.in

それぞれの目線でコメントもらいましたが「諸々整理できたのでよかった」というのは職種関係なく感じていたようです。

終わりに

プロダクトを作りエンハンスを続けていると、細かいところに綻びが出ていることに気がつきはするのですが、立ち止って整理するという意思決定に至らないことも多いのではないかと思います。
トレタでは新しいプロダクト開発に取り組んでいますが、今回のリニューアルプロジェクトで得た知見・ドキュメント等が非常に役に立っています。
中長期的に考えると事業をさらに発展させていくために、短期的に立ち止まり、整理したり仕切り直したりすることは必要なのだと感じています。

今回は良いきっかけに恵まれましたが、一方で施策を前に進めることも必要です。プロジェクトや企業の状況に応じて判断する必要があることなので、ステークホルダーとロードマップを握りながらリファクタリングを組み込んでいくのが良いように感じました。

お約束の

最後に、一緒に走ったり立ち止まったりしてくれる仲間を大募集中です!
とりあえず話を聞いてみたいという方、カジュアル面談もウェルカムですのでお気軽にお問い合わせください。

www.wantedly.com

トレタに入社してみて

はじめに

はじめまして、2022年1月にトレタに入社したエンジニアの葉坂です。

トレタO/Xの決済基盤周りを担当しています。 www.toreta-ox.com

入社して2ヶ月ほど経ちましたので、トレタに入社してみての感想を述べていこうと思います。

特に、現在転職を考えている方の参考になれば幸いです。

簡単な経歴

エンジニア歴としては約5年ほどで、サーバーサイドエンジニアをやっています。

新規サービスの立ち上げから成熟したサービスの保守・運用まで幅広く携わってきました。

直近の技術スタックとしてはRuby, PHP, Flutterです。

ちなみに現在はGoを習得中です。

入社してみての感想

オンボーディングが手厚い

メンター制度があるという話は聞いていたので、そこまで入社への不安はなかったのですが、想像していたよりオンボーディングが手厚く、嬉しい驚きでした。

入社1ヶ月前

まずは、入社前にメンターとの顔合わせMTGがありました。

実際の業務に入ってからの顔合わせだと、つい業務中心の話になり堅苦しくなってしまいますが、入社前MTGということで、意識しすぎることなく話ができました。

おかげで、実際に入社してからも大きな感覚の相違なく業務ができています。

また、上記の顔合わせMTG以外にも、チームの雰囲気をつかめるようにと、サーバーサイド定例MTGにも参加させてもらいました。

メンターや、一緒にお仕事していくメンバーと入社前に、がっつり顔合わせをするのは初めてでしたが、良い経験でした。

入社初日

基本フルリモートではありますが、入社初日は出社での勤務でした(希望に応じて入社初日からリモートすることも可能)。

すぐさま業務にあたるのではなく、まずは丁寧な会社案内がありました。

各部署の担当者がそれぞれ、社内ルールや社内で利用しているツール、会社のミッション、事業戦略や組織の役割等、時間をかけて案内してくれました。

どの担当者の方もその都度、僕の疑問に対してすぐに回答をくれたりと、終始真摯に向き合ってくれました。

特に、ツールへの理解を深めるためにと担当者がしてくれた対応がとても丁寧で助かりました。

複雑な操作に関して、実際に操作デモを行い時間をかけて解説してくれました。

入社2日目以降

入社2日目以降はリモートでの勤務でした。

実際にチームに配属され、サービスやアーキテクチャ全体の説明等、十分な時間を設けてくれました。

フルリモートでのコミュニケーションが疎かにならないよう、また、新人が不明点で行き詰まらないよう、オンボーディング用のslackチャンネルを作成してくれました。

もちろんメンターの方も終始サポートに入ってくれ、大きな不安もなく業務に入っていくことができました。

また、業務外でも、ウェルカムランチを実施してくれ、新しく入る人にも打ち解けやすい雰囲気作りをしてくれました。

他にも、下記のようなサポートもあります。

  • メンターとの1on1(初月は毎週、以降は月1回)
  • 入社後人事面談(入社後1ヶ月、3ヶ月、6ヶ月)

などなど、トレタには新入社員が早期にパフォーマンスを発揮できるようなサポートがたくさんありました。

社内勉強会が豊富

面接時に聞いていた通り、トレタは社内勉強会が充実しており、エンジニアのスキル成長の環境作りに力を入れていると感じました。

Go勉強会」、「RDB勉強会」、 エンジニアによる技術共有会の「テックトーク」、 「システム設計のワークショップ」など実に多くの勉強会が開催されています。

※こちらはすべて業務時間内での開催です。

note.com

www.wantedly.com

note.com

柔軟性の高い働き方ができる

フレックス(11時〜16時がコアタイム)とフルリモートを導入しているので、各々のライフスタイルに合わせて働けます。

時間的にも場所的にも自由度が高いので、非常に仕事がしやすいです。

この情勢を鑑みてすぐにフルリモートを取り入れたり、コロナワクチン副反応による特別休暇制度、 業務以外の目的(観光、帰省、気分転換)で自宅以外の場所に宿泊しながら働くことができる「どこでもトレタ」 制度を導入したりと、情勢や時代に合わせて柔軟かつ迅速に社内制度を整えていく組織力があります。

何より、僕が一番感じているトレタの魅力は、トレタ社員が皆さん温厚な方ばかりなことです。

心理的安全性が高いため、本心から働きやすい環境に感じています。

note.com

note.com

入社前は知らなかった変わった取り組み

トレタでは他社にはない面白い制度がありました。

なんと、社内ラジオがあり、毎週、社員がパーソナリティを務めて放送していたのです。

この社内ラジオは社員積極参加型のため、新入社員の自己紹介企画もありました。

僕ももちろんゲストとして参加しました。

こういった場で話すのは初めてで、とても緊張しましたが、面白い体験ができたと思います。

note.com

これから

入社して2ヶ月経ちましたが、忖度なしに入社前との悪いギャップはなく、トレタに入社してよかったなと感じる毎日です。

とはいえ、飲食という業界はコロナで一番打撃を受けている業界ですし、もちろん業務上は課題もたくさんありますので、 これからも自分が今まで培ってきた技術力でしっかりコミットしていきたいと思います。

さいごに

最後まで読んでいただきありがとうございます。

いかがでしたでしょうか。

トレタの雰囲気、伝わりましたでしょうか。

また、少しでもトレタに興味を持っていただけたでしょうか。

トレタではメンバーを採用中です!

先日資金調達を実施し、絶賛採用中です!

外食産業をもっとやりがいを持って働ける環境にするというミッションのために、トレタと一緒に成長してくれるメンバーを募集中です!

ご応募、ご紹介共にお待ちしております!

corp.toreta.in

トレタO/X toCアプリで行ったパフォーマンス観点の対応

こんにちは!トレタでフロントエンドエンジニアをしている shira です。

この記事ではトレタO/Xというモバイルオーダー事業のうち、自分が関わっているtoCアプリで行ったパフォーマンス観点の対応について紹介します。

トレタO/Xに関しては、次の記事をご覧ください。

note.com

前提

トレタO/XではtoB向けとtoC向けのアプリケーションがあり、toBは共通、toCは各法人別という構成になっています。

この記事ではトレタO/XのtoCアプリのうち、塚田農場(エー・ピー・ホールディングス)様向けtoCアプリ (以下「toCアプリ」という。)の紹介をさせていただきます。

この記事で紹介するtoCアプリは2020年末から開発しているWebアプリケーションで、小さくリリースを繰り返し、改善してきました。

この記事では、パフォーマンス観点で行った対応の一部をご紹介します。

パフォーマンス観点の課題と対策

1. 画像が多く、読み込みに時間がかかる

課題

toCアプリでは全てのメニューに対して画像を表示しています。そのため、パフォーマンス観点で一番気にしていた点は画像の多さでした。パフォーマンスに影響することが明らかなため、初期リリース前に最低限の対応を入れたいと考えました。

f:id:punipunityan:20220214015009p:plain
塚田農場メニュー一覧画面

対応方針

まず、画像サイズを小さくする方法を検討し、WebP を使うことにしました。

Googleによると、WebP に変換することで PNG は 26% 小さくなり、JPEG は 25〜34% 小さくなるとされています。期待大です。(参考:An image format for the Web

WebPは基本的にモダンブラウザで利用可能ですが、対応していないブラウザのために WebP の他に PNG もしくは JPEG 画像を用意する必要がありました。

前提として、運用上変更が必要になる画像は全てContentfulに登録しています。メニューの画像も同様です。

最初は登録時にそれぞれ2種類の画像を登録する必要があると大変だな、と思っていたのですが、Contentfulだと簡単にできる方法がありましたので、その方法を紹介します。

対応方法

Contentfulでは画像のファイル形式を簡単に変更することが可能です。

参考までに、具体的なコードを記載します。

Content Delivery API でデータを取得した際、画像の情報は以下の形式で取得することができます。

(以下、ドキュメントより引用)

{
  "fields": {
    "title": "Nyan Cat",
    "file": {
      "contentType": "image/png",
      "fileName": "Nyan_cat_250px_frame.png",
      "url": "//images.ctfassets.net/yadj1kx9rmg0/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png",
      "details": {
        "image": {
          "width": 250,
          "height": 250
        },
        "size": 12273
      }
    }
  },
  "metadata": {
    "tags": [
      {
        "sys": {
          "type": "Link",
          "linkType": "Tag",
          "id": "nyCampaign"
        }
      }
    ]
  },
  "sys": {
    "id": "nyancat",
    "type": "Asset",
    "space": {
      "sys": {
        "type": "Link",
        "linkType": "Space",
        "id": "yadj1kx9rmg0"
      }
    },
    "createdAt": "2016-12-20T10:43:35.772Z",
    "updatedAt": "2016-12-20T10:43:35.772Z",
    "revision": 1
  }
}

fields.file.url が画像のURLになります。 ファイル形式を変更したい場合、fm パラメータを使います。WebPにするには、画像のURLに?fm=webpをつけ [fields.file.url]?fm=webp のようにするだけでOKです。

アプリケーションで画像を指定する際は以下のように指定しました。

<picture>
  <source  srcset="//images.ctfassets.net/yadj1kx9rmg0/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png?fm=webp'" type="image/webp" />
  <img src="//images.ctfassets.net/yadj1kx9rmg0/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" alt="" />
</picture>

<picture> 要素内の<source> 要素に type="image/webp" を指定し、srcset には [fields.file.url]?fm=web 形式のURLを指定しています。img タグには WebP非対応ブラウザ向けに元々のURL fields.file.url(PNG / JPEG 画像)を指定します。 これにより、WebPに対応しているブラウザではWebP形式の画像を表示し、そうでない場合は元々の画像を表示するようになりました。

さくっと対応できる上、効果が大きいので、とても便利でした!✨ ✨ ✨

今後の課題

WebPに対応することである程度改善できましたが、Contentful側に登録してある元々の画像が大きすぎるケースが発生しており、その点が課題です。画像を登録する方に気を付けていただく方法もありますが、同じ画像を異なるレイアウトで表示している部分もあるため、toCアプリ側での対策も検討したいと考えています。Contentful の Images API を使って、画像をリサイズできるため、デバイスやレイアウトに応じたサイズの画像を返すような改修を将来的に入れたいと考えています。 また、一部WebP未対応箇所があるため、その点も今後改修予定です。

2. 動画がすぐに再生されない

課題

toCアプリでは、注文完了時ランダムに画像や動画を表示する仕様となっています。

f:id:punipunityan:20220309194207p:plain

この機能の開発中、動画の再生が遅れるという問題が発生しました。 インターネットの速度が速い場合は問題なかったのですが、あまり良くない場合に発生するようでした。

対応方針

まず、動画素材の調整を行いました。 具体的には、動画の長さ調整や画質的に問題ない範囲での圧縮などを行いました。(この対応はデザイナーが対応してくださいました。)

アプリ側では事前読み込みが効果的ではないかという仮説のもと、試してみることにしました。 具体的には、注文完了時に表示する画像・動画をアプリ起動時にpreloadで全て取得するよう対応しました。(最初prefetchを使おうとしましたが、safariで使えないようなのでpreloadを採用しました。)

アプリ起動時にpreloadを行うことにしたのは、ユーザーが必ず開く画面だからです。

結果、注文完了画面遷移時、動画がスムーズに再生するようになりました 🎉 🎉 🎉

今後の課題

この対応によって、必要ではないファイル(画像・動画)も取得してしまうという課題は残ります。

また、前項に記載したWebP対応が preload 対応部分の画像に関しては対応できていません。

いくつか改善の余地は残っている状況ですが、その点は今後検討していきたいと考えています。

3. BFFを導入するとレスポンスが遅くなった

課題

アプリの要件が複雑になってきたこともあり、BFFを導入する方針となりました。 BFFへの切り替え対応を行い、Vercelのプレビュー環境で動作確認をしたところ、レスポンスが明らかに遅くなっていることがわかりました。

前提として、toCアプリは以下と通信を行なっていました。

  • APIサーバー
  • Contentful
  • Firebase

BFF対応の際、APIサーバーへのリクエストとContentfulへのリクエストをBFF経由で行うようにしたのですが、そのうちAPIサーバーへのリクエストのレスポンスが明らかに遅くなってしまいました。 APIによっては、6秒弱かかっているケースもありました。

トレタO/Xは

toCアプリ <=> APIサーバー <=> 各バックエンドサービスという構成になっています。

f:id:punipunityan:20220214021125p:plain
トレタO/Xのシステム構成

BFFは、上記の図のtoCアプリとAPIサーバーの間に入るものとなっています。 具体的には Vercel の Serverless Functions を利用しています。 また、BFFでは一部情報をFirestoreにキャッシュして利用しているため、Firebaseとの通信も発生します。

対策

対策はいくつか考え、簡単に試せるものから試しました。 検討した案は以下になります。

  • VercelのServerless FunctionsのRegionを日本にする
  • まとめられるリクエストがないか見直す
  • 処理中にスピナーを出す
  • Firebaseをやめてupstash使う

結局上から3つを行いました。順番に、検討・対応した内容を紹介します。

VercelのServerless FunctionsのRegionを日本にする
Vercel の Serverless Functions の Region が sfo1 になっていたのを hnd1 に変更しました。sfo1 になっていたのはデフォルトのままにしていたためです。( 2021年1月14日より前に作成されたプロジェクトは、デフォルトで米国のサンフランシスコ(sfo1)になり、それ以降は新しいデフォルトの米国ワシントンDC(iad1)になるようです。 参考:Default Region

APIサーバーは日本にあるため、この変更によりBFFとAPIサーバーの物理的距離が近くなりました。

結論、この対応は一番効果的でした。この変更により、元々の速度と大差なく動くようになりました 🎉 🎉 🎉

Regionの影響の大きさを感じました🌏

参考:Regions for Serverless Functions

vercel.com

まとめられるリクエストがないか見直す
リクエストを直列で飛ばすとユーザーを待たせる時間が長くなってしまうため、並列でリクエストを飛ばせる箇所がないか見直しました。すでにある程度対応済みでしたが、見直したところ2箇所程度まとめられるところがあったのでまとめました。具体的には Promise.all() を使って並列でリクエストを飛ばすようにしています。

処理中にスピナーを出す
これは根本的な改善ではありませんが以下理由で対応しました。

  • BFFを挟んだことにより多少レスポンスが遅くなることはある程度仕方ないと考えられる
  • そもそも、あらゆる要因によってレスポンスが遅くなる場合があるが、その際、ユーザーに対してフィードバックがないという課題があった

ちなみに、これまでの通信中の表示制御は以下のようになっていました。(フィードバックを得て改善する前提で対応していました。)

  • APIとの通信時
    • 体感でサクサクだったので、GETは読み込み中の表示はなし、POSTはボタンの連打防止対応を入れていた
  • Contentfulとの通信時
    • 体感でやや待たされると感じられるため、「読み込み中...」文言を画面中央に表示

この改善により、体験のばらつきやレスポンス遅延時の懸念がある程度解消されました。

Firebase をやめて upstash を使う
Firebase にキャッシュするのをやめて、upstash を使うと早くなるのでは?という案がありました。ただ、他プロジェクトで試した方によると、100ms くらい早くなるけど体感はあまり変わらないとのことでした。それに加え、VercelのServerless FunctionのRegionの変更によって大幅に改善していたため、この対応は見送ることにしました。

まとめ

写真を見てお腹が空いた方、O/Xが気になった方、ぜひ塚田農場様に足を運んでみてください😊

この記事では、開発中に見つかったパフォーマンス観点での懸念と対策についていくつか紹介させていただきました。

toCアプリを開発し始めて1年以上経過しました。まだまだ改善したいことはたくさんあります。最近では日々の機能追加に加え、週1日改善Dayを設ける取り組みをはじめました。長くメンテナンスしていくためにコードの見直しを進めているところです。

課題を見つけて改善するのが好きな方、一緒に改善しましせんか!

© Toreta, Inc.

Powered by Hatena Blog