こんにちは、GraciaのCTOの林です。
今回はTANPのパフォーマンス改善の取り組みについて書こうと思います。自社サービスを提供されている企業様にはベーシックなものばかりかもしれませんが、TANPでも安定性のある使い勝手の良いサービスを提供していくため、地道に取り組みを重ねています。
パフォーマンス監視について
Graciaの開発部ではパフォーマンス監視のため、主にDatadogやPageSpeed Insightsを用いた継続的な計測を行なっています。
モニタリングは主にUXチームのPdMや自分を含めたインフラ担当数名で行なっており、デイリーでの確認に加え、何らかのリリース直後や繁忙期には特に注意してモニタリングを行なっています。
1:Datadogでのパフォーマンス監視
TANPのインフラの監視にはDatadogを使用しており、Datadog APMでアプリケーションのパフォーマンス監視を行っています。ここでは極端に実行時間が長いものなどボトルネックとなっているクエリを特定し、改善に繋げています。
また、主要ページのパフォーマンスに関しては、時系列での変化も追えるようモニタリング用のダッシュボードを作成して定期的にチェックを行なっています。冒頭でも記載の通り、新しい機能や告知のリリース直後、繁忙期などは特に注意してモニタリングを行なっていますが、その中でも主要ページのパフォーマンス低下はサービスに与えるインパクトが大きいため、変化をいち早くキャッチできるよう注視しています。
2:PageSpeed Insightsでの点数計測
主要ページについては、PageSpeed Insightsでの点数も定期的に確認しています。特に「Core Web Vitals」項目における指標はGoogleが検索ランキングのロジックに組み込むと発表していることもあり、改善の優先度を上げています。
画像出典:https://developers.google.com/search/blog/2020/05/evaluating-page-experience
改善への取り組み
ツールを利用してパフォーマンスの変化を追い、改善ポイントを洗い出し具体的な改善に繋げていく、というサイクルを重ねていくのが大枠の流れとなりますが、具体例として、実際に行った改善について一部を記載します。
- Webフォントの最適化
- サーバーサイドのクエリキャッシュ
- DBの負荷分散
- テキスト・コンテンツ類の圧縮有効化、静的リソース配信の最適化
- 画像圧縮、配信の最適化
1. Webフォントの最適化
TANPではフォントに「Noto Sans JP」を採用しており、元々はWeb Font Loaderを用いてGoogle Fontsから非同期で読み込みをしていました。しかしながら、この方法ではフォントの読み込みの為だけにWeb Font Loaderのダウンロードを行う必要があり、さらにGoogle Fontsが提供しているダイナミックサブセッティングを実現するためのCSSが大きいなどの課題がありました。
これを回避するため、フォントファイルを事前にサブセット化してサイズを2MBから350KB程度に削減し、自前でホストしてpreloadする方法へ変更しました。headタグ内でpreloadすることで読み込み開始のタイミングを早めることができ、fontファイルをそのままホストすることで2回目以降の読み込み時にはキャッシュを利用できるため、以前の読み込み方法と比べパフォーマンスの向上に貢献しています。また、これらの方法を適用することでFOUTの発生も抑えることができています。
サブセット化やWOFFへの変換には以下のツールを使用しました。
- サブセット化:https://opentype.jp/subsetfontmk.htm
- WOFFへの変換:https://opentype.jp/woffconv.htm
2. サーバーサイドのクエリキャッシュ
前述の通り、主要ページに関してはDatadog APMで定期的なリクエストの監視を行っており、不要なクエリや重いクエリの特定に繋げています。
処理時間が長いクエリの例
クエリは可能な限り結果をキャッシュしておく、重いクエリは実行計画に沿って適切なインデックスを貼りながらチューニングしていく等、地味ではありますがこちらも地道に取り組んでいます。
レスポンスタイムが改善した例
3. DBの負荷分散
TANPのアプリケーションサーバーはオートスケーリングの設定を行なっており、特にインパクトが期待できるメディア露出の前やプッシュ配信の前には事前にインスタンスを増やすなどの対応もしているのですが、別途データベース側についてはボトルネックにならないように注意する必要がありました。
TANPのDBはAuroraを利用していますが、書込み1台 + 読込み複数台のクラスターを作成し、アプリケーション側で読込み処理を読込み用インスタンスに向けることで負荷分散を行っています。
当然ですが、読込み用のエンドポイントに書込みを行うとエラーになりますので、その点に関してはコード側でケアを行う必要があり、エンジニアチーム内の規約としてコネクションの切り替えはアプリケーションの一番上のレイヤーで行うよう定めています。
インフラに関しては以前記事を公開していますので、是非こちらもご参照ください。
4. テキスト・コンテンツ類の圧縮有効化、静的リソース配信の最適化
サーバーが返すHTMLファイルや、CSS、JavaScript等の静的ファイルはgzip等で圧縮した上で返すようにしています。
TANPではサーバー(EC2)をElasticBeanstalkで管理しているため、HTMLの圧縮に関しては.ebextensionsでApacheの設定ファイルにgzip圧縮の設定を追加する方法で実現しています。
また、CSSやJavaScript等の静的ファイルに関しては、元々は各EC2インスタンスに置いて配信していましたが、現在はS3に置いてCloudFront経由で配信するようにしているため、CDN配信で最適化しつつ、CloudFrontの圧縮設定をONにすることで圧縮も実現しています。(こちらも同じく「3.DBの負荷分散」に掲載した過去記事に詳細を記載しておりますので、よろしければ合わせてご参照ください。)
gzip圧縮の確認(ChromeのDevTool/Networkタブ)
また、ファイル本体のサイズを下げるため、不要なライブラリの削除や処理の見直し、ページ毎にファイルを分割して必要箇所でのみ読込みを行うなど、細かな取り組みも定期的に行なっています。その結果、ファイルサイズを4分の1程度まで削減できた例もあり、日頃の開発と並行して定期的な見直しを行なっていくことが大切だと感じています。
5. 画像圧縮、配信の最適化
TANPでは商品や記事の画像はS3にアップロードし、Cloudinaryを経由して配信しています。Cloudinaryでは、同一リソースを元にPCとSPで画像サイズを変える等、画像の動的変換を簡易に行うことができるのですが、具体的にはhttps://res.cloudinary.com/[アカウント識別子]/image/fetch/c_fill,f_auto,q_auto,h_[height],w_[width]/[S3のURL]のように、S3の画像に対してheightやwidthを指定して読込むことで、サイズ変換を行なっています。
また、ブラウザを認識して自動で最適な拡張子(ChromeならWebP形式等)に変換してくれたり、CDNでの配信も可能であったりしますが、コストがそれなりに掛かってきますので、パフォーマンス改善によるメリットや内製した場合のコストと比較して検討する必要があるかなと思っています。
まとめ
パフォーマンス改善への取り組みを始め、サービスの改善は全てが劇的な変化をもたらすものばかりではなく、非常に地道な取り組みを積み重ねていくこと、各社が当然のように意識していることを学んで反映していくことが結果に繋がっていくのではないかなと考えています。日々の開発に集中することも大切ですが、新しい取り組みに集中するあまりパフォーマンスへの意識が疎かになってしまうと結果的にお客様の体験を損ねてしまう可能性もあります。
Graciaの開発チームでは、日々意識されるべき「当たり前」の水準を高めると共に、それらの取り組みを継続的に行えるような仕組みづくり、体制づくりを行なっていくことで、より多くのお客様に使いやすいと思っていただけるようなサービスづくりができるよう、日々メンバーで試行錯誤しています。
今後さらにサービス品質のベースラインを押し上げてくれるエンジニアの方を絶賛募集中ですので、少しでも興味を持っていただけた方は是非お気軽にご連絡をいただけると嬉しいです!
エンジニア採用サイト:https://gra-cia.co.jp/engineer
Gracia Twitter:https://twitter.com/gracia_tanp
募集職種一覧:https://gra-cia.co.jp/careers
編集:広報