Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
MAUが1年で292%に成長した「aumoのおでかけ比較サイト」における取り組み
Search
gree_tech
PRO
October 13, 2023
Technology
2.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
MAUが1年で292%に成長した「aumoのおでかけ比較サイト」における取り組み
GREE Tech Conference 2023で発表された資料です。
https://techcon.gree.jp/2023/session/TrackA-2
gree_tech
PRO
October 13, 2023
More Decks by gree_tech
See All by gree_tech
我々はどう生きるか
gree_tech
PRO
0
4
変わるもの、変わらないもの :OSSアーキテクチャで実現する持続可能なシステム
gree_tech
PRO
0
5.1k
マネジメントに役立つ Google Cloud
gree_tech
PRO
0
72
今この時代に技術とどう向き合うべきか
gree_tech
PRO
3
2.8k
生成AIを開発組織にインストールするために: REALITYにおけるガバナンス・技術・文化へのアプローチ
gree_tech
PRO
0
470
安く・手軽に・現場発 既存資産を生かすSlack×AI検索Botの作り方
gree_tech
PRO
0
470
生成AIを安心して活用するために──「情報セキュリティガイドライン」策定とポイント
gree_tech
PRO
1
2.4k
あうもんと学ぶGenAIOps
gree_tech
PRO
0
590
MVP開発における生成AIの活用と導入事例
gree_tech
PRO
0
620
Other Decks in Technology
See All in Technology
事業成長とAI活用を止めないデータ基盤アーキテクチャの設計思想
hiracky16
0
780
オートマトンと字句解析でRoslynを読む
tomokusaba
0
130
害獣害虫を自動判別! ペストコントロール支援ビジネス成功のヒント【SORACOM Discovery 2026】
soracom
PRO
0
130
AI Agent を本番環境へ―― Microsoft Foundry × Azure Serverless で作る Enterprise-Ready な基盤
shibayan
PRO
1
910
AI時代の強いチームの作り方
yuukiyo
14
8.3k
Claude Mythos、Fable...フロンティアAIの最新動向と企業のセキュリティ対策
flatt_security
0
170
現場をAIで動かす「フィジカル AI」の組み込み設計の考え方【SORACOM Discovery 2026】
soracom
PRO
0
150
データベース研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
710
Atlassian Cloudサポート業務でのAIエージェント活用事例
smt7174
0
120
ウォーターフォール開発案件のPMとしてAI活用を模索している話
hatahata021
2
230
toio・myCobotでフィジカルAIっぽいことを行うための検討(とりあえず調査) / フィジカルAI LT(IoTLTによる開催)
you
PRO
0
140
AI研修(Day2)【MIXI 26新卒技術研修】
mixi_engineers
PRO
2
1.5k
Featured
See All Featured
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
280
Six Lessons from altMBA
skipperchong
29
4.4k
Bash Introduction
62gerente
615
220k
Building Adaptive Systems
keathley
44
3.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
480
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
920
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
400
Transcript
MAUが1年で292%に成長した 「aumoのおでかけ比較サイト」 における取り組み アウモ株式会社 エンジニア 関谷恒甫 栗本拓弥
目次 • 発表者紹介 • aumoについて • フロントエンドをRailsのテンプレートエンジンからNuxt.jsに 移行した話 • フロントエンドにNGINXのリバースプロキシを設置してキャッ
シュを導入した話 • まとめ 2
自己紹介 3 • 名前:関谷恒甫 • 所属:アウモ株式会社 • 担当:メディアチームにおける開発全般 • 経歴:
◦ 2020年4月:グリーに新卒入社 ◦ 2020年4月:アウモに配属 ◦ 2020年6月:WFSに配属 ◦ 2021年12月:アウモに配属
自己紹介 • 名前:栗本拓弥 • 所属:アウモ株式会社 • 担当:メディアチームにおける開発全般 • 経歴: ◦
2022年4月:グリーに新卒入社 ◦ 2022年4月:アウモに配属 4
aumoについて
サービスの全体像
メディア事業
メディア事業の提供サービス
新規事業の取り組み
SaaS事業
SaaS事業の提供サービス
SaaS 事業の機能紹介
Fintech
Fintech事業の概要
マーケティングソリューション
マーケティングソリューションの概要
おでかけ比較サイトのフロントエンドを Railsのテンプレートエンジンから Nuxt.jsに移行した話 17
何をやったのか • aumo.jpの一覧ページ(例 aumo.jp/areas/241)のフロントエンドを、 Railsのテンプレートエンジン(slim)からNuxt.jsに移行した。 18
19 gourmet.aumo.jp aumo.jp なぜやるのか • aumoではaumo.jpドメインと3つのサブドメイン(gourmet.aumo.jp, leisure.aumo.jp, travel.aumo.jp)で一覧 ページを運営しています。
なぜやるのか (歴史的経緯のため)ドメインによって フロントエンドの実装が異なる • サブドメイン ◦ Nuxt.js • aumo.jp ◦
Railsテンプレートエンジン 20
なぜやるのか • 一覧ページを開発する際は基本的にドメイン4つ全てが開発の対象 ◦ サブドメインではNuxt.jsのコンポーネントを使い回すことができる が、aumo.jpドメインではそれらを使えないので、テンプレートエン ジンのコードも書く必要がある。。。 21
なぜやるのか • 一覧ページを開発する際は基本的にドメイン4つ全てが開発の対象 ◦ サブドメインではNuxt.jsのコンポーネントを使い回すことができる が、aumo.jpドメインではそれらを使えないので、テンプレートエン ジンのコードも書く必要がある。。。 22 2度手間!!!
移行の流れ ※アウモでは業務時間の1~2割程度を、各自がやりたい開発改善等の 時間に当てて良いということになってるので、その仕組みを今回は 利用しました。 23 1. アプリケーションコード変更 2. インフラ変更 3.
リリース
移行の流れ 1. アプリケーションコード変更 2. インフラ変更 3. リリース 24
アプリケーションコードの変更 • テンプレートエンジンのコードを、Nuxtに書き換える。 • 基本的には既存のNuxtのコンポーネントを使い回す。 • aumo.jpドメインのみに存在するUI等がある場合に、コンポーネントを新規 作成or修正。 • デザインが同じでもaumo.jpドメインとサブドメインで仕様が違う可能性があ
るので、コードを一つ一つ確認し差分があった場合は、PMと適時仕様をすり 合わせる。 25
移行の流れ 1. アプリケーションコード変更 2. インフラ変更 3. リリース 26
インフラの変更 • aumo.jpドメインには一覧ページ(https://aumo.jp/areas/241)だけで なく、記事ページ(https://aumo.jp/articles/145272)も存在する。 • 一覧ページへのアクセスのみをNuxtサーバに転送するように変更する必要 がある。 ◦ ALBのリスナールールを編集して、特定のパスパターン (例
/areas/*)の時のみリクエストを転送するように設定。 27
インフラ構成の変更 28 BEFORE
インフラ構成の変更 29 BEFORE AFTER
移行の流れ 1. アプリケーションコード変更 2. インフラ変更 3. リリース 30
リリース ここまでは順調だったが。。。 31
リリース1回目 レスポンス速度が悪化する 32
リリース1回目 レスポンス速度が悪化する 原因 • コード変更に伴い、リリースのタイミングでAPI側 で既存のキャッシュが使えなくなり、 Elasticsearchへのアクセスが増えて負荷が上 がった。 対策 •
元々Elasticsearchの負荷が高めだったので、 この機会にスケールアップを実施。 33
リリース2回目 相変わらずレスポンス速度が遅い状態が続く 34
リリース2回目 相変わらずレスポンス速度が遅い状態が続く 原因 • aumo.jpからリクエストが転送される分、Nuxtサーバへのリクエストが 増えたから? 対策 • サーバー台数を増やしてみる。 35
リリース3回目 相変わらずレスポンス速度が遅い状態が続く 36
リリース3回目 相変わらずレスポンス速度が遅い状態が続く 原因 • パフォーマンスチューニングをほとんど行っておらず、API側でN+1のク エリが複数発生していたから? 対策 • N+1のクエリをひたすら潰す。 37
リリース4回目 相変わらずレスポンス速度が遅い状態が続く 38
リリース4回目 相変わらずレスポンス速度が遅い状態が続く 原因 • 不明。何も思いつかず。 対策 • レスポンスが遅い原因が不明のままなので、問題を切り分けてみる。 • aumo.jpドメインのレスポンスのみが遅いのかサブドメインのレスポンス
も遅いのかを見分けるために、aumo.jpとサブドメインで使うコンテナを 分ける。 39
リリース5回目 aumo.jpドメインへのリクエストのみが遅く、 サブドメインへのリクエストは正常なことが判明 40
アクセスログの調査 アクセスログをよく見てみる • 最初の数分は問題なさそうだが、チラホラ遅い レスポンスが混ざっている。 • その後は全部のレスポンスが遅くなる。 • 遅いレスポンスをよく見ると、エリア番号が大き い傾向があることに気づく。
41
アクセスログの調査 アクセスログをよく見てみる • 最初の数分は問題なさそうだが、チラホラ遅い レスポンスが混ざっている。 • その後は全部のレスポンスが遅くなる。 • 遅いレスポンスをよく見ると、エリア番号が大き い傾向があることに気づく。
42
アクセスログの調査 43 アクセスログをよく見てみる • 最初の数分は問題なさそうだが、チラホラ遅い レスポンスが混ざっている。 • その後は全部のレスポンスが遅くなる。 • 遅いレスポンスをよく見ると、エリア番号が大き
い傾向があることに気づく。 エリア番号が関係してそうなコード を 探す。
問題のコード 44 computed: { targetAreaRegion () { return this.allRegions.find((region) =>
region.prefectures.some((pref) => pref.areas.some((area) => Number(area.id) === Number(this.targetArea) ) ) ) } } allRegions = [{ id: 1, name: '北海道・東北', prefectures: [{ id: 1, name: '北海道', areas: [{ id: 1, name: '札幌市' }, ...], }, ...] }, ...] ・allRegionsはregion->prefecture->areaという階層構造になっていて、階層構造を上か らiterateしていき、targetArea(例 札幌市)が属するregion(例 北海道・東北地方)を探す。 ・areaは全部で1600個程あるので、targetAreaが配列の後ろの方にある場合は探すのに 時間がかかる。 ・computedプロパティでキャッシュしてるので大丈夫だと思っていたが。。。
Nuxt.jsをSSRで利用する時の落とし穴 45 原因 • Nuxt.jsをSSRで利用する場合は、computedプロパティが キャッシュされない。 https://github.com/nuxt/nuxt/issues/2447 対策 • 計算が重い処理はcomputedプロパティではなく、storeに保存すること
で、レンダリング中に処理が走るのを1回だけにする。
リリース成功!!! 46 リリース6回目
学んだ点 • ログは超大事。生のアクセスログ、ALBのメトリクス、ECSのメトリクスなど色 んなログを見るべき。 • テストが充実してないと、リファクタリングのハードルが上がる。 • リファクタリングは辛いので、設計の段階でなるべく先まで見通して、リファクタ リングをそもそもしなくて済むようにできるのがベスト。 より詳細が知りたい方は、テックブログを見てください!
https://techblog.aumo.co.jp/articles/2233 47
おでかけ比較サイトのフロントエンドにNGINXのリ バースプロキシを設置して キャッシュを導入した話 48
何をやったのか • 一覧ページを表示しているNuxtサーバの前段に NGINXリバースプロキシを置いて、ページキャッシュを導入した。 49 既存の構成 リクエストが来るたび 大量のAPIを叩いていた リバプロ導入した構成 1回目のリクエストは
従来通り 2回目以降のリクエストは NGINXがキャッシュを返す
なぜやるのか • SEO対策として一覧ページのコンテンツをリッチにして、 MAUが大きく成長した! が、、 50 追加したコンテンツ例
なぜやるのか • SEO対策として一覧ページのコンテンツをリッチにして、 MAUが大きく成長した! が、、 51 追加したコンテンツ例 MAUの推移
なぜやるのか • しかし、ページがリッチになるにつれてレスポンス速度が遅くなってしまって いた 52
なぜやるのか レスポンス速度の悪化によりCoreWebVitalの指標が低下してしまった • CoreWebVitalとは ◦ Googleが定めるWebサイトのUXを測る重要な指標のこと。 ◦ PageSpeed Insightsというサイトで誰でも計測できる •
CoreWebVitalの主な指標 ◦ Time to First Byte (TTFB): ▪ レスポンスの最初のByteが返るまでの時間 ◦ First Contentful Paint (FCP): ▪ 視覚コンテンツの初期表示時間 ◦ Largest Contentful Paint (LCP): ▪ 最大コンテンツの表示時間 53
なぜやるのか 54 • CoreWebVitalが不合格だらけなので、これを改善することで、 MAUがさらに成長するかもしれない
なぜやるのか 55 • CoreWebVitalが不合格だらけなので、これを改善することで、 MAUがさらに成長するかもしれない ちくしょう。 速度改善だ!
なぜやるのか • 今後コンテンツがさらにリッチになっても、レスポンス速度の悪化を招かな いようにしたい。 • Nuxtのレスポンスを丸々キャッシュする「ページキャッシュ」を 導入すると、キャッシュ済みページへのアクセスは一瞬で返せる。 56
なぜやるのか • 今後コンテンツがさらにリッチになっても、レスポンス速度の悪化を招かな いようにしたい。 • Nuxtのレスポンスを丸々キャッシュする「ページキャッシュ」を 導入すると、キャッシュ済みページへのアクセスは一瞬で返せる。 57 ちくしょう。 ページキャッシュだ!
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 3. リリース 58
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 3. リリース 59
NGINXリバースプロキシ設置 - インフラ構成 - BEFORE
NGINXリバースプロキシ設置 - インフラ構成 - 61 BEFORE AFTER
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 3. リリース 62
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 1. 数千件の特定URLをキャッシュする 2. SPとPCでキャッシュを分ける 3.
リリース 63
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 1. 数千件の特定URLをキャッシュする 2. SPとPCでキャッシュを分ける 3.
リリース 64
NGINXでページキャッシュ導入 65 要件1 • 数千件の特定URLをキャッシュする 対応 • mapディレクティブで対象パスを制限 ◦ 条件分岐というとif文が頭に浮かびますが、NGINXではif文は邪悪と言わ
れておりなるべく使わないべきとされています。 そこで、mapディレクティブで条件分岐を行うようにしました。
NGINXでページキャッシュ導入 66 • mapディレクティブで対象パスを制限 map $host$request_uri $is_target_path { default 0;
include /etc/nginx/cache_target_path.map; } aumo.jp/prefectures/13/scenes/8 1; aumo.jp/prefectures/27/categories/a12 1; gourmet.aumo.jp/areas/466/categories/a15 1; /etc/nginx/cache_target_path.map
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 1. 数千件の特定URLをキャッシュする 2. SPとPCでキャッシュを分ける 3.
リリース 67
NGINXでページキャッシュ導入 68 要件2 • SPとPCでキャッシュを分ける 対応 • キャッシュキーにPCかSPかの情報を含める
NGINXでページキャッシュ導入 69 • キャッシュキーにPCかSPかの情報を含める ◦ PCかSPかの情報をもつ$deviceをmapディレクティブで用意する ◦ キャッシュキー(proxy_cache_key)に$deviceを加える ▪ キャッシュキーの例:aumo.jp/areas/13:sp
location / { ...... proxy_cache_key $host$uri:$device; ...... }
ページキャッシュ導入の流れ 1. NGINXリバースプロキシ設置 2. NGINXでページキャッシュ導入 3. リリース 70
リリース後の効果計測 71 • レスポンス速度 ◦ 0.00秒でレスポンスを返している!
72 • CoreWebVital指標 ◦ 合格!! リリース後の効果計測 指標 定義 キャッシュ前 目標値
キャッシュ後 全体 不合格 合格 合格 LCP メインコンテンツの読み込み速度 4.3s 2.5s 1.7s FID 操作を行ってから応答が発生するま での遅延時間 489ms 100ms なし CLS 読み込み時のレイアウトのずれ 0 0 0 TTFB サーバー初期応答時間 2.8s 0.8s 0.5s FCP 視覚コンテンツの初期表示時間 3.7s 1.8s 1.3s INP コンテンツの反応速度 3,943ms 200ms 2,263ms
73 • MAU ◦ MAUが成長! リリース後の効果計測
キャッシュについてのまとめ 74 • 速度改善にも種類がある ◦ バックエンド: DBアクセスのキャッシュ、N+1 ◦ フロントエンド: ページキャッシュ、CDN
• ページキャッシュを導入すれば、ページがリッチになってもレスポンス速度が速 いまま変化しない より詳細が知りたい方は、テックブログを見てください! https://techblog.aumo.co.jp/articles/2278
このセッションのまとめ 75 • フロントエンドをRailsのテンプレートエンジンからNuxt.jsに移行することで 開発工数削減ができた。 • フロントエンドにNGINXのリバースプロキシを設置してキャッシュを導入する ことでレスポンス速度の改善ができた。 • これからもサービスの質を高めて、より多くの人に使ってもらえるサービスに成
長させていきます!
ご成長(静聴)ありがとうございました! 76
77