爆発的アクセスを想定した海外4言語メディアをWordPressで作った話

ニュース・ブログ

爆発的アクセスを想定した海外4言語メディアをWordPressで作った話

blog

爆発的アクセスを想定した海外4言語メディアをWordPressで作った話

韓国・台湾・タイのファンに向けて、ある大手エンタメ企業の公式ニュースを多言語で配信するメディアサイトを作りました。記事は社内の編集者が毎日書く。読者の8割以上がモバイル。4言語(将来的に英語を足して5言語)同時運用。そして、アーティストの新譜・ライブ・メディア出演などの瞬間に、世界中のファンが一斉にアクセスする──という性質のサービスです。

最終的な構成は、WordPress(従来型、ヘッドレスではない)+ Polylang + AWS という、ある意味「ありきたり」な組み合わせ。今日は、なぜそう選んだのか、内側をどう作っているのか、瞬間風速にどう備えているか、という話です。

なぜWordPressなのか

新規メディアの技術選定で最初に問われるのは、たいてい「ヘッドレスCMSにするか、フロントをNext.jsで組むか」あたりです。今回はそこを一段引いて、「日々、編集者が記事を投入し続ける運用が、5年回り続けるか」を最優先軸に置きました。

編集者の作業UX、メディアライブラリ、リビジョン、予約公開、複数言語ぶんの翻訳ペアリング──このあたりはWordPressとPolylang(多言語プラグイン)の組み合わせが、現時点で市場で圧倒的に枯れています。ブロックエディタ(Gutenberg)で動画・SNS埋め込みを差し込む体験も、編集者にとっては慣れた道具です。流行りに合わせてヘッドレス + フロント別構築にすると、ここの "毎日触る道具" の体験が落ちて、運用フェーズで効いてきます。

一方で、企業の本番運用に耐える要件(独自データ構造、認証、外部連携、負荷)をWordPressのテーマだけで雑に書くと一瞬で破綻します。なので "WordPressに乗ったまま、内側はちゃんと作る" 方針で、コードは責務ごとに層分けし、コアの業務ロジックはWordPressに依存しない形に切り出して、テストを書きながら開発する、というルールを敷きました。「WordPressを選んだ = 雑に作っていい」ではない。ここを徹底することが選定とセットでした。

技術スタックの全体像

使った道具は、WordPress + Polylang + PHP、それを AWS(CloudFront・EC2・Aurora MySQL Serverless v2)の上で動かす、という標準的な組み合わせです。デプロイは GitHub Actions で自動化していて、本番反映は確認文字列を入れないと発火しないようにしてある、という程度の「真面目に組んだ普通の構成」です。

「特殊な技術スタックは何ひとつない」──これが意図です。新規メンバーがキャッチアップしやすいこと、ローンチ後に長く運用が続くこと、を優先しました。

多言語をどう実装したか

多言語メディアサイトでいちばん事故るのは、「翻訳キーの管理」「URLの言語プレフィックス落ち」。両方とも運用が始まってから一発で表面化して、ユーザーに直接影響が出るタイプの事故です。

翻訳データは1つのファイルで集中管理

翻訳データはすべて1つのファイルにまとめてgit管理し、デプロイ時に自動で翻訳DBに同期する仕組みにしました。デザイナー・翻訳者・エンジニアが触る場所が1箇所に集約されるので、「誰かが管理画面で直接編集 → 次のデプロイで上書きされて消える」というよくある事故を防げます。

運用ルールとしては、文言を変える時は他言語側だけ編集する、日本語の原文ごと変える時は新エントリとして追加する、という形を徹底しています。多言語プラグインの内部仕様上、日本語原文をうかつに書き換えると他言語訳が一斉に外れるトラブルが起きやすいため、ここはガバナンスで守っています。

「途中で英語に飛ばされる」事故を仕組みで防ぐ

多言語サイトでありがちなのが、「韓国語で登録を始めたユーザーが、フローの途中でなぜか英語ページに飛ばされる」みたいなURLまわりの事故です。油断していると本番運用が始まってから一発で表に出ます。

対策として、URLを生成する場所を「正しい入口」1つに統一して、それ以外の書き方を禁止するルールにしました。プラグイン任せでは塞げない穴を、仕組みとコードレビューでちゃんと守る、という発想です。

瞬間風速に耐える設計

このサイトの性格上、平常時のアクセスは緩やかでも、特定の瞬間に世界中のファンが一斉にアクセスする──という典型的なバースト系トラフィックを想定する必要がありました。基本方針は、「リクエストが届く層をできるだけ手前で止める」「平常時はミニマム、瞬間風速で持ち上げる」です。

3層キャッシュ──ログイン必須でもキャッシュは効かせる

このサイトは「全コンテンツがログイン必須」という仕様なので、普通に作ると「人ごとに違うページ」になってしまい、キャッシュが効きません。そこで、ページ本体はみんなに同じものを返して、その人だけに見せる情報(フォロー状態、未読バッジなど)はあとから個別に取りに行く方式に切り替えました。これで「全員に同じページを配ってもいい」状態をつくれます。

あとはユーザーに近い順に、3層でキャッシュを重ねる構成にしました。瞬間風速対策の起点はここで、「実際にサーバー側のプログラムを動かす確率」を構造的に下げています。

ユーザーからCloudFront + AWS WAF、Nginx FastCGI Cache、PHP-FPM + OPcacheを経てAurora MySQL Serverless v2に至る3層キャッシュ構成図

事前バーストは手順書、突発バーストはアラームとWAF

プレスリリースや新譜解禁など「事前に分かっているバースト」には、当日の事前増強で対応します。手順は社内の運用手順書(ランブック)に整理し、サービスを止めずに切り替えられるよう検証済み。通常運用は最小構成で回し、必要な日だけサーバーを持ち上げて、終わったら戻す。月々の運用コストを抑える設計です。

突発的なバースト(意図しない拡散、想定外のメディア露出、攻撃)に対しては、AWSの監視機能でアプリ・DB・防御の各層をまとめて見ていて、異常があれば素早く気づける体制を組んでいます。WAF(ウェブ防御サービス)側にもアクセス元ごとのレート制限を入れていて、攻撃性のあるバーストはここで止まります。

まとめ: 選定 = ありきたり、中身 = ちゃんと作る

外から見ると「WordPress + Polylang + AWS」というありきたりな構成ですが、内側はコードの層分けと自動テスト、翻訳ルールの整備、URL生成の入口統一、3層キャッシュ、増強の運用手順書まで含めて「ローンチ後5年、瞬間風速にも耐えながら、運用が回り続けること」を前提に組んでいます。流行りの技術スタックを並べるより、こちらの方が結果的にお客様の運用コストと事故リスクを抑えられる、という判断です。

弊社では、こうしたグローバル展開を見据えた多言語メディアサイトや、アクセス変動の激しいプロダクトのアーキテクチャ設計・運用設計を、PoC(小さく試す検証フェーズ)からローンチ後の監視整備までお手伝いしています。導入のご相談やデモ体験については、お気軽にお問い合わせください。