React Server Componentsに感じたフロントエンドの消失

7 min read読了の目安(約6400字 8

はじめに

新年早々に面白そうな記事を見つけました。ReactでのAPI呼出しを最適化するために「部分的にサーバサイドで実行するコンポーネントを作る」というもののようです。

https://zenn.dev/erukiti/articles/react-server-components

あるいは去年の記事ですが気になってたものとしてBlitz.jsでReactベースのFWであるnext.jsに永続化層を持たせてRailsのようなFWにしようというアプローチもあります。

https://zenn.dev/mizchi/articles/cbe81299e145491676f8

どちらの記事も書かれてる内容自体は分かる気がするものの 「それをフロントエンドでやる意味あるの?」 というのが拭えずイマイチ腑に落ちなかったんですが、単純に 「私と最前線でやられてる方々で期待してるものがたぶん違う」 という気がしてきたので、その辺を整理のために書いてみます。

注意書き

  • Vue.js/Nuxt.jsは少し触ったことがありますが、React Server ComponentsやBlitz.jsを触ったことは無いです
  • 「なんでそういう方向に進化しようとしてるんだろう?」という疑問への自分の今時点の感想でしかないので何かを否定したり矮小化する意図も無いです
  • 普通に間違ってたり異なる見解もあると思うので、気になることがあればコメント等によろしくお願いします。

TL;DR

  • React界隈はフロントエンドという言葉に捕らわれない進化を目指している
  • ただし、バックエンドが主体となるような大規模システムはそもそもユースケース外
  • XaaSの進化でバックエンドが単なるGWのような構成ならフロントエンド由来の技術でフルスタックFWを作るのは自然

フロントエンドエンジニアなんて居ない

まず最初に少なくとも私の思っていた 「フロントエンドエンジニア」 というロールは無いあるいは最前線には居ない、という事。

元々、フロントエンドエンジニアをJQueryに長けた人たちから始まった 「Webアプリのクライアントサイドを書くロール」 と考えていましたが、たぶんそれはもう間違っています。実際のところは 「React/Vue.js由来の技術を使ってWebアプリケーションを書く人々」 くらいなのかな、と。

であれば、そもそもとしてクライアントサイドに完結する意図が無いから、SSRの利用にも躊躇がないし、なんだったらビジネスロジックも書く。フロントエンド開発がしたい分けではなくWebアプリ開発がしたい ので、フロントエンドとバックエンドの境界なんてどうでも良いのです。UIの記述性が高くロジックも問題なく書けるReact/Vue.jsを使って 「ビジネスロジックも書いてしまった方が効率的」 。このくらいの感覚なんじゃないかなぁ、という気がしています。

このあたりが私のようにReactやVue.jsを 「フロントエンドの技術」 というバイアスで見てるから最近の流れがしっくりこない点かな、と。それらはあくまで 「フロントエンド 発祥 の技術」 というとこまで来てるのに 古い感覚 が抜けてないという話だと思う。

フロントエンド、バックエンドとは?

「フロントエンドエンジニアなんて居ない」 と考えると、そもそも 「フロントエンドとバックエンドって何?」 という疑問が出てきます。
これに関して定義めいたものを見たことは無いのですが、私の元々の感覚としては「フロントエンド==クライアントバックエンド==サーバサイド」でした。ただ、最近のFFBやSSRの流れを見てインフラを境界にするのは合ってないなと思い 「フロントエンドはプレゼンテーションバックエンドはビジネスロジック」 と認識を改めてたところ。

バックエンドにバッチを含めるか否かはさておきとして、この定義だとプレゼンテーション層以外は全部バックエンドだからバックエンドのが広大なんですよね。なので私なんかは 「フロントエンド」 と言われるとカスタマーチャネルだからめちゃくちゃ重要だけどシステム全体としては部分の印象がどうしても強い。

ただ、これは私が仕事では比較的規模の大きなシステムを取り扱うし、フロントエンド/バックエンドとして言葉をわざわざ分けるから感じる事で、たいていのWebアプリやスマホアプリのように プレゼンテーション層が主体 でなんならテーブル設計のような永続化層すらUIに従う 設計ならそっちがメインですよね。

そういったシステムを組む時にはわざわざフロントエンドとバックエンドを分けて考える必要は無いですし、RailsやSpring/JSFで書いて良いならば同様にBlitz.jsなどReact由来のFWで書いても良いのはそうだろうな、と。あとは好みと個別要件の向き不向きですね。少なくともプレゼンテーション層主体のアプリケーションでそこから始まったFWを使おうと考えるのはとても自然です。

フロントエンドとバックエンドはなんで分かれてるんだっけ?

次に思うのは「なにか理由が合って分かれていたはずのフロントエンドとバックエンドを分けずに考えても良いのか?」「それは時代への逆行ではないのか?」 です。では、これについて考えます。

理由はいくつかあるでしょうが主だったところは以下じゃないかな、と。

  • サーバ負荷をクライアントへオフロード
  • DBアクセスなどサーバサイドでしか安全に出来ない処理の分離
  • UIとビジネスロジックを分離して疎結合にする事で

まず、サーバ負荷の軽減というものがあります。これはサーバはステートレスなAPIとして実装し状態管理やHTMLの生成をブラウザ側で実施する事で負荷を下げるという事です。この点に関してはReact Server ComponentsやNext.jsなどSSRのFWであればSPAなどに比べてサーバ負荷が増えますが、状態管理は基本的にクライアント側に移譲出来てますしレンダリングもクライアントとサーバで必要に応じて分散して実行するのでサーバサイドのみで完結するアプローチよりは大きく改善しています。加えてサーバサイドロジックが比較的小さかったりステートレスな事も多いと思うので、FaaSなどのサーバレスなインフラに流し込みやすいのでスケーラビリティを確保しやすい点もポイントではないでしょうか。

次にDBアクセスなどサーバサイドではないと安全に出来なさそうな処理をバックエンドでやる、という考え方。
これに関してはバックエンドの役割が本当に単なるゲートウェイなのであれば従来的なバックエンドは確かに必要無くなるケースが多そうです。何故ならば 直接クライアントからDBにアクセスすれば良い ので。インターネットに公開されているという点はTLSで暗号化してしまえば良いだけです。認証もWebアプリのログインと同程度もに保ててれば問題ないでしょう。権限周りは無論注意が必要ですがそこは選ぶツールと設計しだい。GoogleのFireStoreなんかはまさにそのためのDBだし、GraphQLも レガシーなインフラに対しての汎用的なラッパーという側面もあるんじゃないかと思っています。GraphQLもイマイチ使いどころが見えてなかったのでこの考え方にそうと結構しっくりくる。クライアントサイドJOINを多発するとレイテンシの問題が気になりますが、だからこそReact Server Componentsみたいな発想が生まれるのでしょう。FaaSにDB周りはやらせる方法もあるし。なんか Web以前のクラサバ時代 に戻った気もしますが、歴史は繰り返しますしね。現代のユースケースにマッチするなら戻って何ら問題ない。

最後は責務の分離ですね。
プレゼンテーションとビジネスロジックを分離することでそれぞれ独自にスケールアウトできますし、新しい技術を採用してもインタフェースが守ってれば影響はありません。まあ疎結合にせよというのはシステム設計の基本ですね。
ただこれはある程度システム規模がでかい、または極端なパフォーマンスが要求されるときのことです。
マイクロサービス化と同じですが初期段階での過度な分割はデメリットの方が大きく、プレゼンテーションとビジネスロジックの分離も同様です。

人類は密結合を求めている

「密結合は悪だ! 疎結合のためにAPIの境界を守れ」 と思いますか?
大規模開発を正しくやるためには分割統治が基本で、そのためには明確な境界とI/Fが必要です。古事記にもそう書いてある。最初から正しくやるのが一番! そう思いたくもなります。

なのですが、常に正しくやりたいなら人々はEJB2に満足していた でしょう。悪名高き?EJB2ですがこと疎結合という点では良くできていたと思います。全てをインターフェースで包み単なるメソッド呼出しリモートサーバとのNW通信といった異なる実装を同一の操作でアクセス出来るという非常に美しいアーキテクチャです。

なんですがこのアーキテクチャは大不評と共に無くなりました。それは 全てにインターフェースを書くのがあまりにめんどくさい からです。
たしかにSOAやMSAのような分散システムを組む上ではEJB2のようなデザインは便利なのですが、マシンスペックの向上とともに分散システムでは無く単独のアプリケーションとDBだけでシステムを組むことが増えました。そうなるとインタフェースを書く意味はないですし、分散システム向けのオーバーヘッドが足かせになります。

というわけでアンチテーゼとしてのSpring/Hibernateが流行りましたし、シンプルなMVCとしてのStrutsやRails, PHP系各種FW (SynfonyとかCakeとか)が流行ったという側面もあります。これらはすべて 「単独のアプリケーションで完結する」 ことを基本としたFWです。

疎結合の方が拡張性や保守性は高いのですが基本的にめんどくさいので 分業不要な規模でかつ性能問題が無い ならば常に密結合を選んできたのが人類です。

良く言われる話ですが、この手の疎結合/密結合システムあるいは分散/集約システムはだいたい数年から十数年でトレンドが入れ替わります。おそらくですが最初はスタートアップで密結合なシステムを作り、その会社が業界のリーダーポジション程に大きくなったころに性能問題か分業体制強化のために疎結合システムに移行して成功。他の会社も近いステージの会社が増えてるから同調してトレンド化、そして疎結合システムは面倒なのでスタートアップ界隈を中心に今のニーズにあったシングル性能と生産性の高い密結合なFWが生まれ、彼らが大きくなるまで利用されるという流れかと思います。つまり「今のイケてる会社」のステージに影響してるんだろうなー、と。

ちょうど今がその時期なんでしょうね。たぶん。バックエンドのマイクロサービス界隈もモジュラモノリスがどうのと言い始めたし。この辺はマシンスペックとかインフラの進化とも連動しますし。

私がフロントエンドに求めていたもの

この章はほぼ余談ですが、逆に私が「フロントエンド」という領域に何を期待していたかを書いてギャップをクリアにしたいと思います。

フロントエンドに期待していたものはサーバ負荷の削減非同期処理によるNW速度や描画速度の隠蔽です。
正直に言えば仮に多少クライアントの方がレスポンスが悪いとしても 「フロントエンドに処理を寄せてサーバの負荷が減ったりステートレスになるならその方が良い」 と考えています。これはクライアントでの200msの遅延よりサーバサイドでの50msの遅延の方がチリ積で サーバダウンを招き最終的にユーザ体験を損ねる可能性が高いから です。実際どっちがUXに大きな影響かはケースバイケースだと思いますけど。

また、サーバ側をステートレスにするということはクラウドネイティブ化の容易さにも繋がりますし、クライアント側が厚くなるという意味でもあるので分業もしやすくなります。そのためインフラ面を含めて「フロントエンドとバックエンドの境界」が大事です。

なので、SPAやSSG/JAMStackのようにCDNに静的コンテンツとして配布できるのが最も理想的な形です。CDNはマネージドなHTTPDとして考えると最強レベルの性能とコスパの良さを誇りますからね。クライアントとCDNに負荷を寄せれることの意味はとても大きいです。

次点でBFF (Backend for Frontend)を使ったSSR。これもビジネスロジックを持つ APIサーバとはインフラレベルで分離されているのでフロントエンドとバックエンドの境界は維持されています。フロントエンド側のロジックはFaaSにデプロイしやすいものも多そうですし。

こういう視点だから「React Server ComponentsでAPI統合はもちろんDB直アクセスもできる」とか「Blitz.jsで永続化層を持たせれる」と言われてもピンとこないどころか「筋が悪いのでは?」とすら感じてしまってた要因。
目指してるゴールが違うから当然ですね。

JAMStack向けのFWもありますし、この視点が異端とまでは思ってないですがReact/Vueの進化の方向性として少なくとも異なるゴールが存在しているということは意識しないとなと思います。

まとめ

私自身がフロントエンド主体の人ではないので、実際の認識と合ってるかは分かりませんがなんとなく最近の流れで感じてた違和感がすっきりした気がします。

それ 「RailsやSpring/JSFで良いじゃん。Reactでやる意味あるの?」 って感じるのは当然で解決しようとしてる問題領域が同じだからですね。その上でプレゼンテーション主体のアプリケーションをReactなどそれに向いたFWで書いた方が楽ってのは自然な話。フルスタックFWの範疇にクライアント領域が改めて含まれた だけなので、RubyやJavaでユニバーサルなFWが出ないと同じ土俵では勝負にならないのかな、と。いろんな観点があるから最終的にどれが流行るかは別だけど。

こういう話になる時点で、もはやフロントエンドやバックエンドという区切りはされていないので、React Server ComponentsやBlitz.jsが普及すればフロント領域とかフロントエンドエンジニア という言葉も無くなるのかなぁ、と思ってのこのタイトルとなりました。

それではHappy Hacking!

追記:

Blitz.jsのようなアプローチを採用したときのスマホアプリは気になりますね。PWAやハイブリッドアプリにする感じかな? アーリーステージではそれも良い気がする。