アーキテクチャ物語 〜昔話から最近まで〜

この記事は [株式会社TRAILBLAZER Advent Calendar 2024](https://qiita.com/advent-calendar/2024/trail-blazer) の24日目（クリスマスイブ）の記事です。

---
こんにちは、株式会社TRAILBLAZER（トレイルブレイザー、以下トレブレ）ソリューション事業部で部長をやっている直井です。アドベントカレンダー4回目の登場になります。

トレブレとしてアドベントカレンダー初参加なので、まずは会社紹介や色んなメンバに記事を書いてもらったのですが、Qiitaなのにエンジニア成分が少ないかも？と思ったので、今回は自分が今まで関わってきたシステムアーキテクチャについて振り返っていこうと思います。

記憶を思い起こしながらの感想となるので、おっさんの昔語りポエムになりそうですが、そこはご容赦頂ければと思います。

## **前置きと言う名の経歴紹介**
2000年〜2007年6月：SIer
2007年7月〜2024年6月：某英語が公用語で有名なEC最大手のIT企業
2024年7月〜：弊社トレブレ

詳細をぼかすため、年代は明記しませんが、基本時系列に書いていくので、どの年代の話なのか想像しながら読んでもらえると幸いです。

## 本文
### クライアントサーバ型システム
#### 概要
いわゆるクラサバですね。
自分が就職した2000年からしばらくはまだ主流だったと思います。

雑なイメージ
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41577/46fcd347-3564-499a-6509-d88837fe7e55.png">

クライアントは様々ですが、自分が扱ったことあるものだと、
- POSレジ（組み込み開発）
- PC（インストールするパッケージソフトの開発）

の2つでした。

この時代は、とにかくネットワーク速度が遅いし、安定していなかったので、
クライアントとサーバの間のやり取りは、転送量と頻度のトレードオフでした。

どういう時代だったかと言うと、ダイヤルアップでテレホ時間にUOやっていて、PvPに勝つためにISDNへの切り替えを検討する、みたいな時代でした。日本語でおｋって感じですねｗ

そんなこんなで、夜間に日次バッチで前日分の情報を全部やり取りしてしまうか、プログレスバー見せて待ってもらって裏でせっせと情報をやり取りするか、みたいな設計が必要でした。

#### POSレジ（組み込み）パターン
まず、POSレジのパターンについて説明します。
と言いつつ、あまりおぼえていないのですが、言語は古のCOBOLでした。
いまだに「ENVIRONMENT DIVISION」って言葉だけ心に刻まれています。
当時はまだ英語に不慣れだったので、単語に馴染みがなく、TYPOしないように気を付けていたからかもですね。
各POSレジと店内のPCが繋がっていて、商品名、品目、金額みたいなシンプルなデータが集約され、締め処理でサーバに売上データなどが送信されるシステムだったと思います。

#### PC（インストールするパッケージソフトの開発）パターン
次に、PCクライアントパターンの説明です。
クライアント側はパッケージソフトの開発になります。
言語はC++で、VC++（Visual C++）やBCB（Borland C++ Builder）を使って、画面を開発していました。
画面設計はツールだけでは再現できない要件が多く、Win32APIも直接触ったりもしていました。
今だったら絶対断るんですが、当時の下っ端プログラマは首を縦に振ることしかできなかったので、無理矢理実装していました。まあ、いい勉強にはなりましたけどね。
パッケージソフトはテストがとにかく大変で、色んなメーカーのPCでテストしないといけないのがしんどかったです。

クライアントとサーバ、それぞれにDBを持っていて定期的にデータの同期を行っていました。その同期処理の実装を担当していたので、多数のクライアントからのリクエストをスレッドセーフに処理するため、マルチスレッドによる並列処理や、排他制御をどこでかけるか、など結構頑張って実装した記憶があります。

---
### Webアプリケーション
#### 初期（自分が関わりだした頃という意味での初期）
ADSLが出てきて、一般家庭のネット速度がちょっとずつ早くなってきた頃、今じゃ当たり前ないわゆるECサイトみたいなWebアプリケーションが増えてきたと思います。

ただ、ネット速度がユーザによって様々だったので、一番遅いところに合わせる感じで、1回のリクエストで軽量なHTMLを1ページ丸ごと返す作りでした。

雑なイメージ
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41577/74096f7e-838a-9874-ac27-7a7886652c2a.png">

アーキテクチャはオンプレでLAMP構成が主流でした。LAMPは、OSがLinux、WebサーバがApache、DBがMySQL、言語がP系（Perl/PHP）のことです。大きいサービスだと、DBがMySQLの代わりにOracleだったり、言語がJavaだったりって感じでした。

1回のリクエストでまるっとページを返すので、処理を高速化するためにDBから1回で必要な情報を全て取得してテンプレートエンジンにぶち込んでHTMLを出力する方法が取られがちでした。
Javaを例にすると、SQLで取得したデータをBeanにぶち込んで、JSPに渡して表示するんですが、~~魔改造~~ゴリゴリにチューニングされた長大なSQLが乱立して初見だと全く理解できず、触ると怖いのでBeanやJSPにロジックを書いて誤魔化してしまい、次に触る時の影響範囲が広がってしまって、なおさら分からないので適当にお茶を濁すという最悪のスパイラルが繰り返され、とんでもないスパゲッティが量産されていた時代でした。あ、自分のところだけかもしれませんが。

また、今よりHTMLだけでできることが少なかったのと、パッケージソフトみたいに自由な要件からHTMLだけでできることにフォーカスした設計に切り替わっていく途中だったので、サーブレットやFlashでカバーすることも多かったです。
特に、Flashの埋め込みは本当多くて、うっかり長生きしてしまったサービスがHTML5への切り替えで苦しむことになったのは、割と記憶に新しいんじゃないでしょうか。

#### おまけ（Oracle特化型）
上記のなるべく少ない回数でDBからデータ取ってこよう思想のある意味で究極系なのが、このOracle特化型アーキテクチャ（今、勝手に名付けた）でした。アプリケーション部分まで全部Oracleに依存し切ろう！という構想は潔さすら感じますね。

とんでもなく雑なイメージ
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41577/43e510a0-30df-bc17-48af-5e13b33376a9.png">

これは流石に嘘ですが、このくらいOracle依存しているという気持ちを表してみました。
正確には、Apacheにmod_plsqlを入れることで、PL/SQLでHTTP通信できるようにします。
PL/SQLにはHTPというパッケージがあり、HTMLを表示するための関数が色々用意されています。
例えば、
```
htp.print("hogehoge");
```
こんな書き方をすることで、HTMLを自由に出力することができます。
これを駆使してWebサイトを作り上げるという訳です。

自分がこの機能を最初に触ったのは、Oracle EBSというERPのアドオンとして実装した時だったので、そういうアドオン的にちょっとした画面が必要な時に使うものだと認識していました。
なので、普通のエンドユーザ向けサービスにがっつり使っているシステムがあることを知った時は、本当ビックリしましたし、早くリプレイスしなくては！と心に誓ったのを覚えています。まあ、全然すぐできなかったんですが。。。

#### jQuery登場したくらい
2000年代後半にjQueryが登場したことで、AJAXを比較的簡単に実装できるようになったのはエポックメイキングだったと思います。
今ではSPAやコンポーネントごとの表示なんて当たり前ですが、当時はページの一部分だけを動的に更新することができるのは画期的なことでした。
ただ、使いすぎるとクローラーが読み取れず、SEO対策に影響が出てしまうので、使い所は結構限られていた印象です。今のSPAでもクライアント側でレンダリングすると同じ問題が起きると思いますが、当時は今よりGoogleとYahooのSEO対策がとにかく絶対な時代だったので、あまりたくさん使えなかったですね。
ただ、AJAXの実装のためにJavascriptからコールバックするAPIを作る必要があったので、自然とAPIを作る流れが生まれていったのは良かったかなと思います。

#### フレームワーク乱立による覇権争いの戦国時代
MVCをベースに、様々なデザインパターンをサポートしているフレームワークが現れては廃れ現れては廃れしていた時代でしたが、個人的にはORMの登場が大きかったと思います。

JavaのStrutsでもORMをサポートできるよう拡張した大手SIer御用達の独自フレームワークは割と昔から存在していたのですが、ベンダーロックされてしまうのでメンテナンスを考えるとあまり使いたくはなかったので、ちゃんとサポートしているフレームワークが主流になっていったのは良かったなと思います。

ORMが主流になっていくことで何が変わったかと言うと、上の方で書いた複雑なSQLを書ける人こそ至上、みたいな考え方から、フレームワークをちゃんと理解して適切に設計・開発できる人が重宝されるようになったと思います。
当然、コードはシンプルになるので、テストも書きやすいですし、テストを先に書くこともやりやすかったと思います。
DB自体も表現しやすい設計に変わっていったと思います。

全体の設定を外出しできることとか、APIが作りやすいとか、DIとか、他にも色々ありますが、長くなるのでこの辺で。

#### イケてるフレームワークに集約されていった時代
自分がフレームワーク選定で気を付けていたのは、日本だけでなく世界中のコミュニティが活発かどうかでした。フレームワーク自体はOSSなので、コミュニティが活発 ＝ 継続的にアップデートされる、という安心感や、そもそも利用経験のあるエンジニアが多く、採用がしやすいという側面もありました。

多くの人がそういう風に考えた結果だと思いますが、いくつかのデファクトスタンダード的なもの、覇権フレームワークとでも言いましょうか、みたいなところに集約されていったと思います。
自分が関わっていたところの感覚ですが、JavaだとSpring・Spring boot、PHPだとLaravel・Symfony、Node.jsだとExpress・Nuxtらへんですかね。まあ、みなさんとも感覚のズレは無いのではと思います。

#### Oracle高くね？と今さら気付いちゃった時代
たくさんの大きなサービスがトランザクションの安定を求めてOracleを使っていたと思います。
が、特にWeb系ではサービスの成長に伴って増強を続けた結果、コア数が増えに増えてしまい、気付いたら莫大なランニングコストとなっているシステムも多かったのではないでしょうか？
脱Oracleの始まりですね。

DBの設計としては、複雑だったり絶対に保証しないといけないトランザクション部分だけをOracleに残します。RDBMSが強いテーブル群はMySQLなどに、検索に使えれば良いだけのものはMongoDBなどのNoSQLにしておきます。データもリアルタイム性が求められるもの以外は、Queuingを使って非同期にしてしまうのもアリですね。固定テキストみたいなデータはenumみたいに構造化されたコード化してしまっても良いですが、まあこの辺は管理とのトレードオフで。

プログラムの設計としては、DB切り替える前に、フロントとバックを疎結合、特にDBとのI/F部分を切り離しておくと、データソースの変更だけで済みます。API化しておくと、モノリシックなアーキテクチャからの脱却もできますね。

#### HTML5が出てきたらへん
この辺の時代になると、一般家庭の通信速度も光だったり高速化されていて、Webはどんどんリッチになっています。フロントエンドのフレームワークも充実して、コンポーネント単位での表示出力も簡単にできるようになったので、その単位にAPIを返す、マイクロサービスとまではいかなくても、ある程度の機能単位にAPI化していくのが当たり前になっていたと思います。

マイクロサービスなど機能を細分化していく場合は、ビルドとか依存関係とか監視とか、Kubernetesなどのツールを使って管理できるようにしないと、数が多くて管理しきれず死ぬので、運用もセットで考えるようにしてください。最初の頃に飛びついた人たちは、ツール回りが充実していなくて、かなり辛い思いしたと思います。コンテナ化しておくとエンジニアが開発環境作るのが楽なのも良い点ですね。

#### クラウドへのリフトとか割と最近
ここまでほぼほぼオンプレ環境の話をしていました。流石にVMにはなっていましたけど。

プライベートクラウドも扱ったことありますが、思想と責任を持って面倒見る人がいないと、機能開発が遅れるので、社内のユーザが増えない、ユーザが増えないと投資されず、機能開発が進まない、という良くない流れに陥りやすいと思います。

ということで、結局のところ、余程外部に出したくないもの以外は、パブリッククラウドに落ち着くのかなと思います。
クラウドへのリフトは、日本もちょっと前まではオンプレをまんま移行しただけが多かったですが、最近は結構クラウドネイティブが増えてきたのではないかなと思います。

パブリッククラウドとオンプレのアーキテクチャの考え方で一番違うなと個人的に思っているのは、やっぱスケールの考え方ではないでしょうか。

オンプレだと、5年で減価償却することを考えて、サービスの成長を見据えて最初から5年持つ構成を考えます。強めの物理サーバとかDBみたいな、特にお金のかかるものは5年の伸長率を計算して、始めから大きいものを買っておきます。比較的安価なWebサーバは最悪横に並べれば良いので、スケールアウトしやすい設計にだけしておけば良いかもです。

逆にパブリッククラウドは、極論、現状を満たす最低限の構成で良くて、必要に応じてスケールアウトやスケールアップできるようにしておけば良いです。スケールアウトしやすい設計はオンプレでも同じことかなと思います。
オートスケールが使えれば楽ですが、使えなくても、いつ増強すれば良いか把握するための監視は重要です。ただ、これはクラウドに標準で備わっている機能でも十分整備できると思います。

### スマホアプリ
書こうと思ったんですが、疲れたのでまた別の機会でｗ

## **締めの宣伝**
いかがでしたか？
今回は自分が関わったアーキテクチャについてのポエムでした。
20年以上仕事していると、まあ色々あるもんですね。
あと、割と良く覚えているなと、ちょっと驚きました。

締切の関係で、後半どんどん適当になっていったのはご容赦ください。
また別の機会にポエムを書けたら良いなと思います。

最後に、トレブレでは一緒に働くメンバーを募集中です。
こんな記事でも興味が出たそこのあなた、ちょっとクリックしてみませんか？

ということで、本日の記事はここまで。
自分のアドベントカレンダーの記事も今年はこれで終わりです。
読んでくれたみなさん、ありがとうございましたー

https://hrmos.co/pages/trail-blazer/jobs/2000002

https://hrmos.co/pages/trail-blazer/jobs/2000006

https://hrmos.co/pages/trail-blazer