出前館のフロントエンドリプレイスで採用した技術スタックとその選定理由
出前館のフロントエンドエンジニアの奥村です。
2021年からLINEより出向して出前館の業務に携わっており、主にコンシューマー向けの画面の開発を行っています。
本記事では2021年4月から進めているフロントエンドの全面リプレイスについて、どのような思想で、どのような技術スタックを採用したかについて紹介します。
リプレイスに至った背景
出前館は1999年に設立された歴史ある会社です。システムの寿命も長く、仕様の把握に苦労することも少なくありません。また近年は、コロナ禍における需要の高まりもあって「フードデリバリー戦国時代」と言われており、競合との競争が激化しています。
そんな中、出前館では内製化に舵を切りシステムのモダナイズを進めています。これによりUI/UXの改善や商品をお届けする時間の短縮など、より良いプロダクトにすべく日々開発を進めています。
フロントエンドの内製化については私が参画したタイミングでスタートとなったのですが、このままシステムを引き継ぐのか、それとも全面的にリプレイスするのかを決断する必要がありました。
結論としては、全面的にリプレイスする方針としました。
―既存コードの問題点
出前館のフロントエンドは、PHPのCodeIgniterというフレームワークで開発されてきました。ざっくりとした構成は下記の通りです。
しかし問題点として、下記のようなものがありました。
- MVCフレームワークでありながらControllerが肥大化しており、巨大な1ファイルにロジックが全て集約されている。その結果、ロジックのネストが異様に深くなってしまっていたり、デッドコードが残り続けるなどメンテナンス性が悪化している
- フロントエンドに本来サーバにあるべきロジックが寄せられてしまい、結果フロントエンドにもアプリにも似たような処理が多数存在している
- 出前館/LINEにあまりPHPのエンジニアがいない(SPAに強いエンジニアの方が圧倒的に多い)
そこで、現在のコードベースから脱却し全面的にリプレイスする方針としました。ただし、冒頭に述べたように競合との競争が激化していることもあり、事業の成長を止めるわけにはいきません。したがって段階的にリプレイスを進める方針としました。
―段階的リプレイス
技術選定をするにあたり、新しいシステムのゴールを設定しそれを意識しながら選定を進めました。設定したゴールは以下の通りです。
- コードの見通しをよくしてメンテナンス性を向上させることで、バグの発生頻度を減らすとともにデリバリーを早くする
- エンジニアを確保しやすくする
- フロントエンド開発のベストプラクティスを適用できる環境にし、パフォーマンスをより向上させる
このゴールを踏まえたうえで、採用した技術スタックとその選定理由を説明します。
採用した技術スタックと理由
―React/Next.js
SPAのフレームワークとして、ReactとNext.jsを採用しました。
Reactは、Virtual DOMが採用されていて設計と速度が両立する点や、コンポーネント化の容易さなど多くのメリットがあり、また出前館アプリがReactNativeで開発されているなど、出前館全社として採用が進んでいる技術です。
Next.jsは、CSR/SSR/ISR/SSG の切り替えが容易で、CDNとの相性が良く、また自然に使うだけで一定のパフォーマンスを出すことができる点が魅力的だったため採用しました。
―TypeScript
スクラッチ開発の場合に、採用しない理由がない認識なので採用しました。静的解析で一定の品質を担保できる点が魅力的で、Swagger/OpenAPIと組み合わせることでAPIチームとのInterfaceコミュニケーションを容易にしてくれました。
―BFF/GraphQL
先ほどの「既存コードの問題点」で述べた通り、現在フロントエンドにもアプリにも似たような処理が多数存在しています。本来サーバにあるべきロジックは少しずつサーバ側に移植を進めているものの、それでもフロントエンドとアプリで似たような処理が存在するのは避けられません。
そこで、BFF(Backend For Frontend)を設けて共通のロジックについてはその層で実装する構成としました。具体的には、以下のような役割を担っています。
- API Gateway
- セッション管理
- 暗号化/復号処理
- 表示のための整形
なかでもAPI Gatewayについては、サーバ側がマイクロサービス化を進めていることもあり、重要度が高い部分です。そこで、フロントエンド/アプリとBFF間のプロトコルにGraphQLを採用し、クライアントから柔軟な形でクエリできる構成としました。また、graphql-codegenを使用することでType Scriptの型定義を自動生成し、開発効率を高められるようにしました。
結果、構成図としては下記のような形となりました(APIは便宜上一つの箱で記載していますが、実際にはマイクロサービス化が進んでおり、BFF層で複数のAPIを呼び分ける形となっています)。
―テスト
出前館では実装 → 開発者テスト → QAテスト → リリースというフローで開発が進められています。QAテストではブラックボックステストが網羅的に実施されるものの、開発者テストで行うべき部分もあります。
現在の開発者テストの方針は以下の通りです。
- ロジックのテストは行っています。Reactで使用するロジックについては、ロジックをReact Componentに直接書くのではなくutilやcustom-hookに切り出すことで、jestとReact Testing Libraryを使用してテストしやすい状態にしています。
- UIテストは行っていません。開発側でのメンテナンスコストが高いため、QAチームのブラックボックステストでカバーする方針としています。またQAチームで自動化も検討されています。
ただし、Storybookを活用したスナップショットテストやビジュアルリグレッションテストなど、より自動テストが可能な範囲を増やす取り組みは継続的に進めています。
―インフラ周り
出前館のインフラはインフラチームのサポートを受けつつ開発チームで構築しています。
フロントエンドの環境は基本的にAWSで作成しており、S3やECSなどを活用しています。リソースの作成/適用についてはTerraformを使用しています。
ログやパフォーマンスの監視などについてはCloudWatchやPrometheus、New Relicなどを使用しています。
CI/CDについては現在Jenkinsを利用していますが、徐々にGithub Actionsに移行しています。
まとめ
この記事では、出前館のフロントエンドリプレイスで採用した技術スタックについて一通り紹介しました。もう少し深堀りした内容やリプレイス以外に取り組んでいる内容については別途紹介させてください。 一緒に作っていくメンバーを募集中
出前館のフロントエンドチームでは、より良いユーザ体験/開発者体験のために継続的に改善を続けています。その一方で、リプレイスは道半ばで挑戦したいことはまだまだ山のように残っています。
この記事では紹介できませんでしたが、2022年1月からはReactNativeを採用する出前館アプリチームと合体し、フロントエンドエンジニアもアプリ開発に携わる体制(逆もまた真です)に変えていく取り組みや、デザイナーとともにデザインシステムを整備する取り組みも始めています。
そんな出前館ではエンジニアを大募集中です。特に以下のような方におすすめしたい環境です。
フロントエンドを軸にBFFやアプリ開発、AWSなど多方面にスキルを伸ばしたい方
コードや仕様のリファクタリングに興味のある方
デザインの整備に興味のある方