【フロントエンド】自社開発で技術選定を任せていただいたので選定理由と考えたこと

# はじめに
つい先日、私が所属している会社で自社開発を始めてみよう！ということで
フロントエンドの技術選定を任せていただいたので、その時に考えたことや選定理由などを自分なりの振り返りも込めてまとめてみました。
まだまだ駆け出しエンジニアの域を脱せないいちエンジニアの**一つの意見**として、暖かく見守ってくださると嬉しいです。

では早速、見ていきまっしょう！


# 前提
バックエンドとかインフラとかサービスについての前提情報は下記のような感じです。

**・C向けのサービス
・新規システムとして過去の負債がないまっさらな状態から開発をスタートできる
・バックエンドはNest.jsを使用する。
・インフラはAWSを使用。
・開発するアプリケーションは SPA＋一部ページでSSRを実装する予定。**


# 言語
まずは大前提となる言語については**TypeScript**を選定しました。
最近ではもはやデファクトスタンダードになりつつあるありますね。
導入理由は言うまでもないかなとは思いますが

* **型チェックによって早期にバグを検知できる。それによって修正コストも抑えることができる。**
* **型があることで、プログラムの可読性の向上。エディターの補完機能を活かすことができ、コーディングの効率も向上が見込める。**
* **導入する上でのデメリットが見当たらないこと(強いて言えば学習コスト)。**

と言ったところでしょうか。




# フレームワーク
続いてフレームワークについてです。
結論から先に言うと、**React（Next.js**）を選定しました。
理由としては下記が挙げられます。


* **TypeScriptとの親和性**
* **ライブラリが豊富(選択肢が豊富**)
* **単方向データバインディングによるシンプルな実装が可能**
* **Vueに比べて後方互換性が高いため、長期での運用保守に向いている。Vue2~Vue3のような大きなBreaking Changeが少ない。**
* **コミュニティの活発度**



比較対象として**Vue.js（Nuxt.js**）も候補に上がりましたが、上記にも記した
**TypeScriptとの親和性、ライブラリが豊富さ、コミュニティの活発度**などの主に３点で最終的にReactを選定する結果となりました。
よく引き合いに出される学習コストについても、チームメンバーが全員**React経験者**だったというのもあってほぼ考えておりません。



### Next.jsについて少し深掘り

また、Next.jsについてももう少し深掘りをしてみました。

**メリット**
1. **SEOの向上**: SSRを使用することで、検索エンジンがJavaScriptアプリケーションを正しくインデックスできるようになりる。
2. **クライアントサイドのパフォーマンス向上**: SSRを使用することで、クライアント側のJavaScriptの読み込みや実行が不要になり、ページの読み込みが高速になる。
3. **ルーティングのシンプル化**: Next.jsは、ファイルシステムベースのルーティングを提供しています。これにより、ルーティングの設定が簡単になる。
4. **SSRやSSGを簡単に導入可能**: Next.jsは、開発者が簡単にSSRを実現できるようになっています。

**デメリット**
1. **サーバーへの負荷**: Next.jsはサーバサイドレンダリング（SSR）を使用するため、レンダリングの度にサーバーリソースを必要とします。
2. **スキルの要件**: Next.jsを導入するためには、サーバサイドレンダリングに関するスキルが必要になります。これは、開発者にとって学習コストがかかることがあります。
3. **対応していないライブラリがある**。クライアント側でのみ実行するように設計しているものが多いため。


上記はNuxtとの比較というよりは、「**React前提でNext.jsを導入するべきか今一度考えてみよう**」と言った視点で考えています。
最終的に**SSRを導入したい**という意見が多かったので、Next.jsを導入する結論に至りました。


# 状態管理（Redux VS Recoil VS ContextAPI）
多くの現場で一番使われているのは**Redux**かなと思います。非常に柔軟性が高く、Reduxが定めるベストプラクティスのRedux ToolKitがあり使いやすくなったのも大きいですね。

### ①Recoilの検討
とはいえ、最近徐々に頭角を表してきている**Recoil**も検討しました。
とゆうか個人的に私は**Recoil推し**でした。
まだベータ版とはいえ、既に大きなプロジェクトで採用され始めていると言うのをよく聞きます。
それに何と言ってもあのシンプルさ故の「**学習コストが低い割に、機能的には十分**」な点が非常に導入しやすい要因かと思っております。
「**Atomという単位で一意なキーをもったグローバルStateを保持するので、理解しやすい**」のも大きいですね。

### ②ContextAPIの検討
こちらも中規模程度の開発くらいまではアリですね。
ですが、個人的に「祖先コンポーネントまで辿ってツリーを更新する為、**頻繁にレンダリングが発生してしまう**」のが使いにくいので嫌いです。
「 **管理するStateが増えてくるとProviderのネストが深くなり、視認性が悪くなる**」のもデメリットかなと思います。

### ③結論Reduxを選定
結局、**Redux**を選定しました。
ContextAPIに関しては上記記載の通り、**デメリットの方が大きい**と考えた為です。

私の推しであるRecoilを選定しなかった理由としては、「**まだメジャーバージョンリリースしていない**」のが大きいネックとなりました。

大きいプロジェクトでも使われ始めてはいるけど、**サポートされていない状態で今選定するのはリスクになり得るかもしれない**と思った為の苦渋の決断です。。
(ぶっちゃけチームメンバーがかなりRedux推しだったのもあります。笑)



# CSS
意外と意見が分かれがちな**CSSどうするのか問題**ですね。

我々のチームでは、当初**Tailwind**を使用する方向性でしたが、前提にもある通りに今回開発するサービスがゴリゴリに**C向けのサービス**になります。

なので、TailwindなどのCSSフレームワークは「**デザインの自由度**」の観点から適さないのではないか、と考えました。
その為UIコンポーネントでもある**Mui**や**ChakraUI**なども当然選択肢から外れます。


そこで最適なものとして挙がったのが**Emotion**でした。

「Emotion」はJavaScriptでCSSを記述するために作られたライブラリで、いわゆる**CSS-in-JSのひとつ**です。
同じCSS-in-JSの中で、「styled-components」というものもあります。

Emotionの大きな選定理由は下記のとおりです。
* **TypeScriptとの相性◎**
　→**コンパイル前に間違ったら叱ってくれる。かぶってるやつ教えてくれる**
* **render内（html)が見やすくなる**
* **styled-componentsではタグなのかスタイルなのか混同してしまいがちだが、それがない。**
* **メディアクエリが簡単**
* **自由度の高いデザインを実現可能**

何より書き方がすごく**直感的で書きやすく、読みやすい**のも大きかったですね。


# storybook
次にstorybookについてですが、
コンポーネントを素早く確認でき、開発メンバーと非開発者の橋渡しになることがメリットとして挙げられるが
* **今回は全員エンジニアであること**
* **最初の段階では開発に時間が掛かる**
* **ストーリーの管理コストが掛かる**

以上３点の理由から、今回は**storybookの導入はしない**結論になりました。

導入メリットよりもコストの方が大きくなってしまうと考えたからですね。



# テスト
はい。次は**テストどうするのか問題**です。
そもそもフロントエンドにおいて**テストを書く意味はあるのか**、というところから意見が分かれがちです。ベストプラクティスも定まっていない印象を受けます。

とはいえ、下記記事にもありますように、
テストを書くにあたって、テストを書くメリットについてチームが同じ理解を持つことが大切で、もしテストを書く **ROI （投資対効果/投資収益率**）が低いと感じる場合は、テストを書かないのも一つのテスト戦略とも言えます。

https://zenn.dev/koki_tech/articles/a96e58695540a7

この２つのコストとメリットを天秤にかけ、コストの方が上回るようであれば上記でも記したように「**テストを書かない」という戦略も有用**と言えます。
あくまで論理的に考えるべきであって、**めんどくさいから書かないというのは論外**です。


そもそものテスト導入メリットとしては
- **開発中に早い段階でエラーを発見しやすくすることで、開発効率と開発体験を上げる**
- **機能が増えた時に、既存の機能を壊さない可能性を上げる**
- **画面に不具合が発生し、ユーザーの期待通りの挙動にならないことを防ぐ**
- **自動テストにすることで、安全で高速にリリースできる**
が挙げられます。


前置きが長くなりましたが、我々のチーム内での結論は上記運用コストを考えた上で
・**単体テストのみ導入する（JestとTesting Library**）
に決定しました。

なぜ単体テストのみかというと
**・規模感的に結合テストやE2Eまでコストをかけられない
・最低限のコンポーネント単位で動作を保証することができる**

以上の２点の理由から、**単体テストのみ導入する**結論に至りました。


# その他ライブラリ

### ESLint/Prettier
言わずもがな。チーム内で書き方がバラバラにならないので導入しない理由がないですね。

### API呼び出し
https://axios-http.com/


# おわり
いかがだったでしょうか？
技術選定はプロジェクトの内容や規模感、目的など様々な要因が絡み合う為「**絶対にこれ！！**」って言うのがないので掘れば掘るほど興味深かったです。
いい経験をさせていただきました。
また技術選定させていただく機会があればもっともっと深掘りして最適解を探していきたいですね。



# 余談
余談ですが、**npm trends**を見ていたら数ヶ月前くらいに唐突にVueが発作を起こしてて、瞬間的に通常時の１０倍くらいの利用率に跳ね上がってて面白かったです。
おそらくNuxtの影響かなとは思いますが、npm trendsは見ていて楽しいので定期的に見ると新しい発見があったりなかったりします。笑

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819187/819d7f18-7710-bfd0-1138-ea190068a3e9.png)