こんにちは。エンジニアの籏野です。
フォルシアでは Tomcat(Java)上で動く Web アプリケーションフレームワークを自社で開発・運用してきており、2001 年の創業当初から長い間フォルシアの Web アプリ開発を支えてきました。
このフレームワークもまだまだ現役で活躍していけるものではありますが、2019 年頃からは TypeScript/Node.js を利用した新しいフレームワークを構築してアプリ開発が行われています。
Tomcat(Java)から TypeScript/Node.js という言語の仕様もまったく異なる技術セットへの移行をなぜ決断したのか、また実際の検討の様子や移行したことでのメリットについて、当時最新フレームワーク検討チームに所属していた技術統括部長の小海にインタビューしました。
籏野:
今日はフォルシアの Web アプリ開発に利用しているフレームワークについて伺いたいと思います。
よろしくお願いします!
小海:
よろしくお願いします!
小海 研太 | DXプラットフォーム部 技術統括部長
慶應義塾大学環境情報学部卒業後、フォルシア株式会社に新卒で入社。
フルスタックエンジニアとして多くのECサイトの構築・運用を主導する傍ら、社内の技術基盤や教育を整備。
2023年3月にDXプラットフォーム部 技術統括部長に就任。
フレームワークの内製から OSS 利用への変遷
籏野:
フォルシアが開発した Web アプリケーションフレームワークは TypeScript で作られた最新のフレームワークと、Tomcat で動くフレームワークが 2 世代ありますよね。
まずは過去に開発された 2 つのフレームワークについて概要を教えていただけますでしょうか。
小海:
まず初期フレームワークは 2003 年頃に出来上がったもので、Ajax 通信に関するクライアント/サーバーサイドの実装を楽にするものを基本として、クライアントサイドのパラメータ管理やイベント処理、サーバーサイドの DB 接続や DB からの返却値をパラメータやカラムごとにキャッシュしたりなど高速化の工夫もされていました。
Ajax 通信によってページ遷移なく検索結果が書き換わるのは当時では珍しく、簡単に使えるライブラリやモジュールもない中で簡単に API を作成し、jQuery が無い中でクライアントサイドでイベント・状態・Ajax の管理を簡単に行えるものでした。
また、Rhino を使用することでクライアントサイドもサーバーサイドも JavaScript で実装することができたため、ユーティリティの共通化やエンジニアの学習コスト低下させることができていました。
籏野:
私もこのフレームワークを使った開発は経験していますが作りこみがすごいですよね。
Tomcat アプリとして動くので JSP のような本来 JavaScript には存在しない機能も組み合わせて実現されているのも印象的でした。
小海:
そうですね。
20 年前というと動的な Web サイトも多くないような時代だったので、お客様からも驚きの声が上がっていたと聞いています。
僕の同期と「社内で一番勉強になる/出来がいいフレームワーク・ライブラリは何か」という話をした時には初期フレームワークの名前が上がりました。
それくらいよく考えられた仕組みになっていると思います。
籏野:
ベテラン社員のお墨付きのフレームワークですね!
第二世代のフレームワークについても Tomcat アプリ上で動くものになっていますが、こちらはどのような特徴があるのでしょうか。
小海:
第二世代のフレームワークは 2012 年頃に開発されたのですが、CommonJS モジュール仕様をサポートすることで開発効率・メンテナンス性・拡張性を上げ、DB リクエストの並列処理を簡単に行えるようになったりなど、よりブラッシュアップされたものでした。
さらに第一世代と異なった特徴としては「クライアント側のサポートがない」という点があげられます。
この頃にはブラウザ上の処理に jQuery を利用することが一般的になっており、初期のフレームワークが担っていたイベントの処理などは外部のライブラリに任せています。
このときに「エコシステムの恩恵を受ける」という思想が生まれ、最新のフレームワークにもこの思想が活かされています。
籏野:
たしかに最新のフレームワークはこれまでのものと異なって、複数の OSS を組み合わせたものですね。
OSS 利用に至った理由について、もう少し詳しく教えてください。
小海:
先ほど説明した 2 つのフレームワークもまだまだ現役で使えるようなフレームワークではあります。
ただ例えば React などエコシステムの恩恵を受けにくく、Rhino が Node.js に比べて実行速度が遅いという検証結果が出たりなどがありました。
Ajax の例なども今ではもうライブラリを使えば簡単に使用できますよね。
社内製だと脆弱性や最新ブラウザへの対応コストもかかります。
今後新しい技術を簡単迅速に取り入れていくためにはエコシステムの恩恵を受けられるフレームワークにしていこうという話になり、社内製で 0 から作るのではなく、エコシステムの恩恵を受け OSS を組み合わせていく方向性となりました。
籏野:
たしかに近年の Web アプリケーション関連の技術推移は目まぐるしく次々と新しい仕組みが生まれているように感じます。
その恩恵を受けることができるのは大きなメリットですね。
※ 初期に構築されたコードの一部例。
XML 内に JavaScript を書く等の独自仕様により、20 年近くも前からモジュール化した JavaScript ファイルの読み込みやフロント・バックエンド両方を JavaScript で書けるように工夫されていた。
技術選定 ~型に守られた開発へ~
籏野:
新しい仕組みを構築するための技術選定はどのように行われたのでしょうか。
小海:
詳細は以前に書いた記事もご覧いただきたいのですが、検討は 2018 年の 3 月頃に始まりました。
まず最初に好きな言語やフレームワークを持ち寄り同じアプリをそれぞれが作るハッカソンを実施しました。
実際に同じアプリを様々な言語やフレームワークを使用して作成された実装を皆で見ながら議論をすると、ある言語では詰まったポイントがある言語では簡単に実装できていたりなど違いがかなりあり、非常に面白かったです。
その議論の中で「やっぱり型が欲しい」などの意見が出てきたので静的型付け言語を中心に検討が進みました。
籏野:
当時の議事録やブログを見ていても、面白さが伝わってきます。
私が入社する前の時期だったので、ぜひ参加したかったです。
最終的に TypeScript に決まったのはなぜでしょうか。
小海:
同様の処理を様々な言語で実装した時の書きやすさ/処理速度等の実行環境ベースの比較検討を行いました。
最終的な有力候補は Node.js か Go でした。
将来性や拡張性は差がないと判断していましたが、実行速度は Go、学習コストや開発効率は Node.js だよねと。
最終的には、client-BFF-api という構成で Node.js で作成し、必要に応じて api 部分を実行速度の早い Go などを使用できるようにするという意見が出て、それを採用することになりました。
そして、Node.js なら型の恩恵が受けられる TypeScript、そしてアプリの構築は Express でやってみようという流れですね。
籏野:
フルスタックエンジニアとしてアプリの様々な領域に触れるフォルシアのエンジニアにとっては、クライアント/サーバーサイドで言語が統一されているのはより大きな恩恵を受けられますね。
フレームワークの構築と導入
籏野:
利用する技術が決まり、実際にフレームワークとして構築するステップはどのように進んだのでしょうか。
小海:
新フレームワーク検討チームが作られ、このチームのメンバーを中心に検討が進みました。
当時入社して 3 年目となる若手社員 3 名が中心となり、僕とキャリア入社のエンジニア 1 名がサポートをするような体制でした。
ハッカソンの開催もチームメンバーの一人が率先して進めてくれていましたし、手を挙げてくれたメンバーが集まってきたチームになります。
籏野:
かなり若いメンバーに任されたのですね。
若くてもやる気のある人に責任あるタスクを任せてもらえるのはフォルシアらしい部分ですね。
チームではどのようなことを検討したのでしょうか。
小海:
まずは旧フレームワークで作成されたアプリを 1 つ選び、それを TypeScript/Express 構成で作成することになりました。
その後、パラレルでの DB 接続やキャッシュ、ルーティングやプロセス管理など共通部分をモジュール化していくことで検索アプリのフレームワークを形作っていきました。
今後使われていく雛形となるため、BFF 設計などアーキテクチャの検討や、どこまでフレームワークで提供してどこからユーザーに育ててもらうのか、なども常に議論を繰り返しながら開発を進めました。
また、商用稼働を考慮した際に、負荷の高い検索サイトでも安定稼働できるのか、プロセス監視などの運用面、クライアントサイドの設計をどうするか、などが課題として上がりました。
籏野:
検討の中で難しかったのはどのような部分だったのでしょうか。
小海:
チームメンバーは専任ではなく、それぞれが案件に携わりながら業務の合間で開発を進めていました。
JavaScript/Tomcat 構成になっているものを TypeScript/Node.js 構成に作る変えるだけでもかなり規模が大きく、リソース面ではかなり苦労しました。
GitLab の issue を使って細かくタスクを切ることで隙間時間に作業できるようにしたり、分割できないようなタスクは 3 日間の開発集中期間を設させてもらうなど社内の協力も得ながら開発をしました。
社内のエンジニア全員が JS を書けるとはいえ TypeScript の型や React の学習コストも無視できない課題です。
Tomcat(Java)の知識がかなり蓄積されており、それらを一度捨てるというのは大きな決断でした。
籏野:
元々のフレームワークの作りこみがすごかった分、完全に刷新するというハードルは高いですよね。
それらの課題はどのように乗り越えましたか。
小海:
1 つずつ解消していくしかなかったですね。ただ、ここでも Node.js を核としたエコシステムの恩恵を受けた開発を進めることができました。
例えば安定稼働やプロセス監視などについては、pm2 を採用することで「プロセス監視」だけでなく「統一的な Node の開始と終了の手段の提供」「クラスタリングによるリソースの有効活用」「ログローテーション」などの恩恵を受けることができました。
Next.js を採用し、SSR や SPA に対応しつつ簡易な BFF の役割を担い、React を使うことで直感的でシンプルな実装ができるようになりました。
また学習コストを低下させるために勉強会を開いたり、学びたい人への教材をまとめておくなどを行いました。
そのとき心がけていたのは「やり方」だけじゃなく「なぜ嬉しいのか」を伝えることです。
TypeScript や React などは世間的にもかなり盛り上がっていて、少し調べれば教材には苦労しないので、使ってみたい/楽しそうと思ってもらえるのが大事だなと。
具体的には勉強会で実例を見せたり体験してもらうのはもちろんのこと、Slack の Reacji Channeler を活用して TypeScript の恩恵が集まってくるようにしたりなどですね。
勉強会のゴール設定も『参加者が TypeScript が書けるようになる』ではなく『参加者が TypeScript のメリットを理解して感動する』としていました。
またこのフレームワークを初めて商用利用する際に、フォルシアの中でもトップクラスに手の動くチームにお願いできたこともよかったです。
アプリ構築で出てきた課題感をフレームワーク検討チームにフィードバックしてくれたり、実際に改修を入れたりしてもらえました。
検討チーム以外を巻き込んで商用利用に繋げたという実績は大きく、これ以降に新規作成されるアプリについては新フレームワークを利用するという流れを作ることができました。
籏野:
勉強会には私も参加しましたが、瞬く間に画面が構築されたり、型を使った開発の恩恵を実際にデモで見させてもらったことは大変勉強になったのを覚えています。
今では新フレームワークの利用が主流になったとのことですが、移行してよかったと感じた瞬間はありますか。
小海:
繰り返しになりますが、エコシステムの恩恵を受けられるようになったことはやはり非常に大きかったですね。
何か課題を解決したいときの選択肢が非常に多くなるのと同時に、解決策の変更も簡単になりました。
あとはやっぱり型があると安心感が違いますね。
JavaScript では追加改修の影響範囲調査に時間を割くことも多かったのですが、トランスパイル時に指摘してくれるので凡ミスが減りました。
型推論が非常に優秀なので想定していたよりも開発コストは上がっていません。
また最近では Swagger/OpenAPI、Docker や k8s、テストや ci など様々な仕組みを導入しています。
社内製フレームワークだと導入検討時点で考えるべきことが沢山あったのですが、これらと組み合わせた実例の記事が沢山あがっているため、導入検討のコストが非常に低く、実際にやってみるハードルが下がったのも嬉しいポイントですね。
籏野:
「新しい仕組みを導入してみました!」という声が社内のいたるところで聞こえるようになった気がします。
これも検討チームの皆さんが議論を重ねてきたからこその結果であることが改めてわかりました。
本日はありがとうございました!
新しいフレームワークを使いこなす
本インタビューで紹介した通り、フォルシアでは 2018 年の新規フレームワーク検討開始時から TypeScript/Node.js を使った開発に向かい合ってきました。
その中で得てきたもの・学んだものについて、フレームワーク利用者である筆者の立場から紹介します。
TypeScript が導入されてまず何よりも感じることはインタビューの中でも触れられていましたが「型の恩恵」です。
社内でもよく言われているのが「型は最低限のテストである」ということであり、型があることで気付けた事象は数え切れません。
例えば以下のように意図せぬうちに string と number を足し合わせてしまい、全く違った答えが導き出されてしまっていても、Javascript だと見逃してしまうことが多々ありました。
function add(input) {
return input + 1;
}
const input = "1";
const answer1 = add(input); // 本来はnumberが入力されて「2」が返る想定だが、文字列であるために「11」が返る。
これが TypeScript で書かれていると、コンパイルの時点でエラーになるので問題にすぐ気づけます。
function add(input: number) {
return input + 1;
}
const input = "1";
const answer1 = add(input); // 型 'string' の引数を型 'number' のパラメーターに割り当てることはできません。
この恩恵は本当に大きく、過去 2 世代のフレームワークで開発されたアプリケーションの一部ソースコードも TypeScript で置き換える動きもありました。
※トランスパイル後のTypeScriptはJavaScriptなのでRhinoでも動かすことができます。
その際のポイントはログミーにて公開されていますので気になる方は合わせてご確認ください。
初めのうちは不要な型アサーションを付けてしまったり、any で型を破壊してしまう場面もありましたが、様々な開発・改修を経ることで型の利用はさらに洗練されてきています。
型定義を Swagger 定義から自動生成させることでクライアントサイドからサーバーサイドまで一貫してより強固に型で守られた開発を行えるようにしたり、ジェネリクスを用いた独自の型を定義することでより効率的な開発を実現したチームもあります。
さらにはインフラリソースの管理(IaC: Infrastructure as Code)にも TypeScript を利用する取り組みも始まろうとしており、単純なアプリ開発を超えてフォルシアの開発になくてはならない存在となっています。
これらの仕組みは週次で行われている TechMTG(全社エンジニアの集い)でも共有されており、全社の資産として日々蓄積されています。
関連したブログもいくつか執筆されているのでそちらもぜひチェックしてみてください。
OSS の利用者から貢献者へ
創業当初からフォルシアでは Apache/Tomcat/PostgreSQL など様々な OSS を利用させていただいてきました。
新しいフレームワークが構築されたことで、その恩恵を感じられる場面がさらに増えてきている中、恩恵を受け取るだけではなく何かしらの形で恩返しをしていきたいという想いもあります。
これまでも PostgreSQL へのコントリビューションを行ったり、技術的な Tips を発信する動きはありましたが、「OSS への貢献者になる」という意識をエンジニア一人一人がより強く持ちながら、さらなる発展・成長をしていきたいと考えています。
最後に
フォルシアでは TypeScript 好きのためのイベントである「Shinjuku.ts」を定期的に開催しています!
今回の記事で TypeScript に興味を持った方はぜひconnpass ページをご確認ください。
また直接もっと詳しい話を聞きたいという方は下部にある「話を聞きに行きたい」からもお気軽にご連絡ください!
この記事を書いた人
籏野 拓
2018年新卒入社
花粉症がつらいけど頑張ってます