株式会社ブックリスタ プロダクト開発部の開発・運用を担当している片山と申します。
今回は、弊社が包括的なパートナーシップを結び開発を行なっている「auブックパス (運営:KDDI株式会社)」のフロントエンドの技術スタックについて記載させていただきます。
auブックパスのフロントエンドは、開発の内製化にともない、2022年11月にjQuery/CakePHPの構成から、React/Next.jsの構成にリプレイスしました。リプレイスしてから1年ほど運用を続けているため、リプレイスしてどのような効果があったかも記載させていただきます。
言語
TypeScript
TypeScriptは豊富な型に関する表現をもつ静的型付け言語です。コンパイルすることでJavaScriptとなります。
アプリケーションの実装だけでなく、AWS CDKを使用したインフラの環境構築も含めてTypeScriptで統一しました。
リプレイス前のJavaScript/PHPのソースコードには以下のような問題がありました。
- 可読性が低い
- API・関数・ビューテンプレートのIN/OUTの型が明確になっておらず、中身の実装を読まないと型が分からない
- 保守性が低い
- 型の誤りやNull参照エラーなど全てのエラーは実行時にしか分からない
リプレイス後のTypeScriptのソースコードは以下のように改善しました。
- 可読性が高い
- any型の使用は原則禁止としたので、API・関数・コンポーネントのIN/OUTは型定義の実装部分のみ読めば分かる
- 保守性が高い
- 型の誤りやNull参照エラーなどコンパイル時にある程度エラーが分かる
TypeScriptの豊富な型に関する表現を一度使ってしまうと、もうJavaScriptには戻れません。
ライブラリー/フレームワーク
フロントエンドのライブラリー/フレームワークは、React/Next.jsを使用しています。
React
ReactはUI構築のためのJavaScriptライブラリーです。
Vue.js、Angularではなく、なぜReactなのかというと、Reactの経験者がチーム内に居たからというのが理由です。Vue.js、Angularでもきっと問題はなかったのですが、開発者の経験というのは大事な財産であるので、その財産を活用するために、Reactを採用しました。
リプレイス前のCakePHPのビューテンプレートとjQueryを使用したソースコードには、以下のような問題がありました。
- ビューテンプレートの粒度が大きく、適切に分割されていない
- 1つのビューテンレートのソースが長い
- 重複したソースコードが多く存在する
- ソースコード間の関連が分かりにくい
- イベントの発生箇所とイベントリスナーの登録箇所がわかりにくい
- 変更時の影響範囲がわかりにくい
リプレイス後はReactを使用して、以下のように改善しました。
- Atomic Designを採用することで、コンポーネントの粒度が小さくなり、適切に分割されている
- 1つのコンポーネントのソースが短い
- 重複したソースコードが少ない
- イベントの発生箇所とイベントリスナーの登録箇所が分かりやすい
- ReactはonClickなどのイベントをHTML要素に直接定義するので一目瞭然
- ソースコード間の関連が分かりやすい
- import/exportを使用したため、モジュール間の関連が明確
- 影響範囲がわかりやすい
上記は、Reactを使ったから改善したというよりも、リプレイスのために設計し直した効果の方が大きいですね。
Reactのコンポーネントは、原則は関数コンポーネントで作成し、状態管理や副作用の実行などはReact Hooksを使用しています。React Hooksはレンダリングのたびに呼び出されるということに慣れが必要ですが、慣れてしまえば分かりやすいコードを記載できます。
Next.js
Next.jsはReactベースのWebアプリケーションフレームワークです。
ゼロからReactでWebアプリケーションを開発するのはやることが多く結構大変です。Webサーバーを用意したり、webpackなどを使ってトランスパイルの処理を作ったり、ローカルで開発するための仕組みを作ったり、ルーティングの定義を作ったりする必要があります。Next.jsには、Webサーバー・トランスパイル・ローカル開発環境・ファイルベースのルーティングが最初から用意されていて、自分で用意する必要がありません。
また、Next.jsには、SSR・SSGによるプレレンダリング、画像最適化など有益な機能が豊富にあります。
インフラ
auブックパスのインフラはAWSを使用しており、構成としては以下の図のようになります。 ( 今回の図では分かりやすくするために最小限のサービスのみ絞り込んでおり、実際にはもっと多くのAWSサービスを使用しています )
CloudFrontで最初にリクエストを受け付けて、ALB/FargateとS3にリクエストを振り分けます。
ALB/Fargateには動的コンテンツ、S3には静的コンテンツを配置しています。
動的コンテンツ(/api配下、SSR、SSG)のために、Fargateのコンテナインスタンスの中でNode.jsを使ってNext.jsのWebサーバーを起動しています。負荷分散のためにコンテナインスタンスは複数起動しているので、ALBでロードバランシングしています。
リプレイス前はEC2インスタンス上でサーバーを起動していたのですが、リプレイス後はサーバーのコンテナ化を実現できました。
環境構築
AWS CDK
インフラの環境構築は、AWS CDKを使用し、TypeScriptで実装しています。
リプレイス前はインフラのコード化は実現できておらず、同じ環境の構築は不可能で、変更履歴も分からない状態でした。
リプレイス後はAWS CDKでインフラのコード化を実現したので、コードを実行するだけで、新たな環境が作れるようになりました。インフラの変更についても、コードを変更して、そのコードを実行するだけで、インフラが変更できるようになりました。コードなのでGitの履歴を見ればインフラの変更履歴が分かります。
インフラの構築だけでなく後述するAWS CodePipeline/AWS CodeBuildを使用したデプロイ環境の構築もAWS CDKでコード化しています。
CI/CD
GitHub Actions
GitHub ActionsはGitHub上でワークフローを自動化できるGitHubの機能です。
リプレイス前は継続的インテグレーションを実現できていませんでした。
リプレイス後はGitHub Actionsにてプルリク作成時にビルド、Unitテストの実行、lintを実行することで継続的インテグレーションを実現しています。
AWS CodePipeline / AWS CodeBuild
AWS CodePipelineは継続的デリバリーを実現するためのサービスです。
AWS CodeBuildはコンパイル・テスト・デプロイを自動化するサービスです。
AWS CodePipelineにてGitHubの特定のブランチの変更を監視し、AWS CodeBuildを呼び出し、AWS CodeBuildでコンパイル・デプロイを実行しています。
監視
Datadog
Datadogはサーバー監視・分析サービスです。
auブックパスではDatadogにてログ監視、サーバー監視、アプリケーション監視、リソース監視を行なっております。
Amazon Connect
Amazon Connectはコンタクトセンター向けのクラウドプラットフォームです。
auブックパスでは障害発生時の自動オンコールを実現するためにAmazon Connectを使用しています。
詳細はこの記事に記載しています。
まとめ
以上のように、auブックパスのフロントエンドはリプレイスにより比較的新しい技術を使用した構成になっています。auブックパスにはまだ古い技術を使用した部分は残っているため、今後もリプレイスを継続いたします。
今回はauブックパスのフロントエンドにおける代表的な技術スタックだけをピックアップして記載させていただきました。
次回以降にもっと具体的なリプレイス内容・効果や、今回は記載できなかったその他の技術スタックについて記載させていただきます。