🌀

基礎から深堀りするWebアプリケーションアーキテクチャ

2023/04/22に公開

はじめに

Next.jsを触る機会があり、SPAやSSR、SSG等の周辺知識を分かっておきたいということでWebアプリケーションのアーキテクチャについて調べたことをまとめます。
本記事で説明する内容

  • MPA
  • SPA
  • CSR
  • SSR
  • SSG
  • ISR

これらはそもそも何なのか

上記に挙げた用語は、Webアプリケーションの構築と運用のための技術(=アーキテクチャ)です。私達は普段からあらゆるWebサイトを利用していますが、ページ遷移が快適にできたりできなかったりすることがあります。また、ページの情報が古い!といったことも稀にあります。これらはWebサイト(Webアプリケーション)がどのようにサーバーからページ情報を持ってきているのか、という設計に大きく影響されています。この設計がCSRやSSRといった技術の正体です。これらの技術は、ユーザー体験の向上はもちろんのこと、開発効率やパフォーマンス、セキュリティなどの視点も考慮されるものです。それぞれにメリット、デメリットがあり、 Webの発展と共に進化してきました。

本記事の方向性

調べていく中で、私は理解が曖昧な前提知識がいくつかあることに気づきました。ここで取り上げるWebアーキテクチャは、クライアントとサーバー間のデータのやり取りやページ描画の流れ・タイミングを設計するものです。
「流れ」はなんとなく分かるものの、何がどんな役割をしているのかという点があやふやだったので実装のイメージがあまりできていませんでした。
本記事では、Webページのアーキテクチャを構成する要素を役割と具体例を提示して一つ一つ紐解きながら、Webアーキテクチャを理解することを目的とします。

Webアーキテクチャの構成要素

Webページが表示されるということを最大限にざっくり説明すると、クライアントがサーバーにHTTPリクエストを送って必要なデータをレスポンスとして受け取るという流れになります。
さらに細かい粒度で見ると、サーバーにはAPIサーバーやフロントエンドサーバーがあったり、CDNという仕組みがあったりします。これらは各Webアプリケーションの設計によって必ずあるもの、ないものとあります。アーキテクチャについて説明する前に、前提知識としてこれらの構成要素について整理します。

①クライアント(ブラウザ)

役割:UIの提供。つまり、HTML、CSS、JavaScriptなどのコンテンツを描画(レンダリング)して表示する。サーバーに対してHTTPリクエストを送信して必要なデータを要求する。
(例)Google Chrome / Safari / Firefox

②Webサーバー(フロントエンドサーバー)

役割:HTML、CSS、JavaScriptや画像データなどの静的コンテンツを提供する。
いわゆるホスティングサーバーとはWebサーバーを指す。
※AWS S3の静的ホスティングを利用することでもWebサーバーの役割を果たすことができる。
(例)Nginx / Apache HTTP Server

③アプリケーションサーバー(APIサーバー)

役割:クライアントまたはWebサーバーからの要求に応じて処理を実行し、データのCRUDを行う。
バックエンドサーバーとも呼ばれます。
(例)RESTfulAPIやGraphQLの規格を用いたAPIサーバー

④DBサーバー

役割:アプリケーションのデータを保存、管理する。
(例)MySQL / RDS / DynamoDB / Redis

※ここでは詳しい説明を省きますがWeb三層アーキテクチャは②〜④の三層で構成する設計を指します。

⑤CDN

役割:大容量のコンテンツデータを配信するために最適化されたネットワークで、画像や動画、HTML等を効率的かつ高速に配信する。
(例)Akamai / Amazon CloudFront / Cloudflare

⑥レンダリング

HTMLやCSS、JavaScriptを解析・実行することによってコンテンツをブラウザの画面に表示すること。ブラウザに搭載されているレンダリングエンジン(Webkitなど)によって行われる。

⑦Ajax

Asynchronous JavaScript and XMLの略。クライアント・サーバー間でデータを非同期通信でやり取りする技術のこと。非同期通信ではない場合(同期的な場合)、ページ遷移・更新時にページ全体を再読み込みするため一瞬ページが白くなります。Ajaxでは必要なデータをサーバーから非同期に取得するため、表示しているページはそのままに必要な部分だけ動的に内容を更新することができます。
Ajaxにより取得するデータはかつてXML(データのやり取りのためのマークアップ言語)形式でしたが、現在はJSON形式が主流です。
(例)XMLHttpRequest / FetchAPI / Axios

Webアプリケーションの構造とレンダリング技術

いくつもの略語がある中で区別があやふやになりそうだったのが、MPA/SPAとCSR/SSR等は異なるという点です。MPAやSPAは各ページのコンテンツをどのように配信するかというWebアプリケーションの構造を指します。一方でCSRやSSRはその名称の通り、ページのレンダリング技術です。
ブラウザ側でページ内容を変化させるSPAとブラウザ側でレンダリングするCSRはどう違うのかという点でもやもやしていましたが、そもそも並列で語るものではありませんでした。SPAを実現するレンダリング技術の一つとしてCSRがあるということです。
SPAを実現する、と言いましたが、MPAとこれらのレンダリング技術の組み合わせもあります。またレンダリング技術も一つのみを使用するのではなく用途に応じて組み合わせて使用することもあります。

Webアプリケーションの構造

MPA

Multiple-Page Applicationの略。Webが登場した初期からある従来のアーキテクチャです。各コンテンツ毎にページが独立して存在。ページ遷移の度にクライアントはサーバーにリクエストを送信、新しいHTMLを取得します。シンプルな構造で開発コストが低いです。しかしページ遷移の度にリクエスト送信、データ取得が行われるためパフォーマンス面でデメリットがあります。(Ajaxを部分的に使用するという解決策もあります)

SPA

Single-Page Appllicationの略。ページは一つのみ、JavaScriptによってページの内容を動的に更新。
Webの発展と共に、ユーザーとサーバー側のやり取りが増えたことでコンテンツ更新の効率化・高速化が求められるようになりました。ユーザーのリクエスト(または状態)に応じて表示されるコンテンツが動的に変わる(インタラクティブである)ことが多くなり、その都度サーバーからHTMLを取得しているとユーザー体験が損なわれるという問題が出てきます。そこで登場したのがSPAです。SPAを実現している技術の一つがAjaxです。データを非同期に取得できるからこそ、一枚のページの中で動的にコンテンツを表示させることができます。またページ表示に関して、SPAを支えるレンダリング技術がこれから説明するCSRやSSRなどです。

レンダリング技術

レンダリングの流れ(初回アクセス時、二回目以降の挙動)とそれぞれを実現する技術、メリットとデメリットについて説明します。

CSR

Client-Side Renderingの略。ブラウザ側でレンダリングを行います。初回アクセス時にHTML、CSS、JavaScriptなどWebページを構築する全てのリソースをWebサーバー(またはCDN)から受け取ります。そしてこれらのリソースを用いてブラウザ側でページをレンダリングします。
その後必要なデータはその都度APIサーバーに対してAjaxを使用してHTTPリクエストを送信して受け取ってコンテンツを更新、ブラウザ側でレンダリングを行います。

  • 実現する技術
    • React、Vue.js、Angular等のJavaScriptライブラリ・フレームワーク
  • メリット
    • ページ遷移をせずにコンテンツ内容を動的に変えられるので高速な閲覧が可能。
  • デメリット
    • ブラウザ側でレンダリングするため初回表示が遅くなる可能性。ブラウザ環境への依存
    • レンダリング・リクエストをクライアントサイドで行うためセキュリティ上のリスクがある。
    • 初期データが空なのでSEO的には微妙。

SSR

Server-Side Renderingの略。サーバー側でレンダリングを行います。リクエスト毎にデータ取得からHTML生成まで全てサーバー側で行い、ブラウザに返します。ブラウザは生成済みのHTMLを受け取るため、レンダリングの時間が短縮されます。
動的に必要なデータはAPIサーバーに対してAjaxを用いてリクエストを送信・取得してブラウザ側でレンダリングが行われます。SPAにおいてSSRは初回アクセス時にほとんどのコンテンツがHTML生成されており、その後のデータ更新のみブラウザ側で行われることが多いです。
※サーバー側で行うのはあくまでJavaScript実行によるHTML生成であり厳密には直接レンダリングを行うわけではなく、ブラウザ側でのレンダリング時間を極限まで短縮できるということだそうです。ChatGPTの回答から知りました。

  • 実現する技術
    • Next.js:getServerSideProps、getServerSidePaths
  • メリット
    • ブラウザ側でのレンダリング時間がほぼないためページ表示が高速。
    • ユーザーのブラウザ環境に依存しないHTML生成。
    • リクエスト処理やHTML生成をサーバー側で行うためクライアント側でのセキュリティリスクが低減。(Ajax通信によるリクエストは例外)
    • データを保持した状態で初回表示が可能なため、SEOに有効。
  • デメリット
    • レンダリング可能なサーバーが必要。サーバーの負荷はもちろん増加。(CDNなどによる解決策がある)
    • 開発が複雑になる可能性がある。

SSG

Static Site Generatorの略。「静的サイト生成」の意。ビルド時にサーバー側でAPIからのデータ取得とHTML生成を行い、Webサーバーが生成済みのページを保持しています。ユーザーのリクエスト毎にWebサーバーは生成済みのページを返します。SSRの課題であった、リクエスト時にサーバーでHTMLを生成するため負荷が増加するという点を解決しています。
HTML生成がビルド時に行われるため、ユーザーによるデータの更新が生じても再ビルドを行わなければ反映されません。そのためリアルタイム性が求められない静的なコンテンツでSSGは使用されます。どうしてもデータを更新・取得したい時はAjaxを用いて限定的にCSRを使用します。

  • 実現する技術
    • Next.js:getStaticProps、getStaticPaths
  • メリット
    • ユーザーからのリクエスト時には生成済みのHTMLを返すだけなので非常に高速。
    • 静的HTMLを生成済み+リクエスト処理がほぼないためセキュリティリスクがかなり低い。
    • データを保持しているのでSEOに有効。
  • デメリット
    • リアルタイムなデータの更新・反映が難しい。
    • ビルド時間の増加やサーバーのリソース消費量の問題。コンテンツの更新頻度によってはビルド回数の増加も。

ISR

Incremental Static Regenerationの略。「インクリメンタル静的再生成」の意。簡単に言うとSSRとSSGの間、いいところ取りです。ビルド時にHTML生成が行われることはSSGと変わりませんが、ISRでは生成済みのHTMLをCDNにキャッシュします。そしてユーザーのリクエストに対してキャッシュ(生成済みのHTML)を返却。キャッシュには有効期限があるので、一定時間毎にサーバー側でHTMLを再生成→キャッシュするという流れを繰り返すのがISRです。
SSRのサーバー側の負荷とそれに伴うパフォーマンス性の懸念、およびSSGのリアルタイム性の低さをカバーして双方のメリットを活かすことを目指した構成です(もちろんCSRやSSRには劣る部分もあります)。

  • 実現する技術
    • Next.js:getStaticProps+revalidate
    • Nuxt.js:useStatic+reactiveRef
  • メリット
    • 生成済みのHTMLをキャッシュから配信するため高速。
    • 一定期間毎または特定のトリガーによりHTML再生成を行うため柔軟なコンテンツの更新が可能。
  • デメリット
    • 再生成時のサーバー負荷(オーバーヘッドが発生することがある)。
    • 再生成のタイミングの設定など、実装が複雑。

実装について

SSGやISRでは静的ページを配信しつつ動的なコンテンツ更新等の必要に応じてCSRやSSRと組み合わせたり、SSRも同様にデータの取得・更新時にAjaxを利用してブラウザ側でレンダリングを行ったりします。
考慮すべき点は多く、ユーザー体験からサーバー側の負荷、SEO対策、セキュリティ面までアプリケーションの要件を整理する必要があります。それぞれの構造・技術の利点と課題を理解してバランスの良い設計が求められます。
例えばJAMstackは、SSGを基盤としてコンテンツの高速な表示のためCSRやSSGを組み合わせながらAPIやヘッドレスCMS(バックエンドのみのCMS)等も利用したWebアーキテクチャの一つでパフォーマンスとセキュリティにおいて優れています。

余談

学習中にuseEffectとgetServerSidePropsを同一ページに記述した時の挙動を見て、なるほど、と思いました。正直に言うとコードの削除ミスでしたが、SSRは初回表示(リロード時)の描画が速いことを確かめることができたのは思わぬ収穫でした。

最後に

フロントエンドを触ること自体が初めてで、SSRって何?SSGって何?というところから始まりました。多くの既存記事を参考にしながら、理解の穴埋めのため細かい疑問点をchatGPTに聞いては深堀りして、さらにチェックもお願いして、本記事は完成しました。(このテーマについての会話を繰り返していたからか、使えば使うほどGPT-4のすごさを実感しました。)
今回は主にレンダリング技術一つ一つの理解を目的としましたが、先に述べたように実際に設計する際は考慮点が多々あります。ベストプラクティスや要件に応じた適切な設計についてはまだまだ学ぶべきことがたくさんありそうです。

※誤った記載があればご指摘ください。

参考記事

https://zenn.dev/rinda_1994/articles/e6d8e3150b312d
https://zenn.dev/akino/articles/78479998efef55
https://zenn.dev/mt877/articles/6dc3afe99ee794

Discussion