🎃

とりあえずWebサービス作る時の私の技術選定ポイント@2022/02

2022/02/11に公開
7

はじめに

inspired

https://zenn.dev/moga/articles/my-technology-selection

mogaさんのブラウザで動くサービスを作るときの技術選定が素晴らしい記事だったので、自分も書いてみる事にしました。

幸いにも技術選定からのお仕事をする機会が多くて、自分の中でパターンが大体決まってきているので言語化してみます。前提が同じサービスは無いので絶対的な正解は無いですが、なんかしらの参考になれば幸いです。

※2022/02時点

私/よくあるお仕事について

Web系のサービスなんかいい感じにするマンとして、フリーランスとして働いています。

準委任という形でスタートアップ企業をお手伝いする事が多いです。
MVPを作りたい、もしくはMVPは行けたのでちゃんと作り直したい、という要望があって参画して、まるっと作ってそのまま運用をします。作って終わりではなくて、運用や拡張性を考えてやってます(サービスに必要なのはもちろん、運用する自分が楽だから)。

前提

  • エンジニア少ないけどなんとかしたい
    • 自分含めて1人〜数人程度
    • なので、フロントエンドもバックエンドもインフラもできる人が全部やる
    • メンテコスト(エンジニアの工数)あまりかけられない
  • スピード感は欲しい
  • でも拡張性も欲しい
    • 負荷対策
    • 機能拡充
    • エンジニアの採用する時にボトルネックにならない
  • ブラウザで動くWebサービス
    • アプリは一旦考えない
    • スマホ、PC両方
  • 各種SaaS、サーバの費用はお客さんが出すけど、べらぼうに高いのはNG

基本構成

基本的にはこれを基準として考えます。

  • ある程度枯れていて学習コストがかかりすぎない
    • 開発者のテンションが下がらない範囲で
  • 汎用的にしばらく使い続けられる
  • あまりお金はかけすぎず
  • フルマネージド系のサービスをできるだけ使って、サービス本体の開発にできるだけ注力できるように

という観点での選択になっています。

サービスの特性で尖っているものがあれば、それに適したものに変える必要がありますが、まだまだこれからというフェーズであればシステム構成的にも、人員的にも戦いやすくなっていると思います。

構成の説明

  • 大枠
    • フロントはSPAで。SSR/SSGはしない
    • backendとはRestAPIでやりとり
    • 全部TypeScrpt
    • GCP/Firebase
  • フロント
    • Nuxt
    • vue2
    • TypeScript
    • compositionApi使いまくる
    • SSRしないのでfirebase hostingにおくだけ
  • バックエンド
    • TypeScript
    • メインのFWはNestJS
      • NextJSじゃないよ
    • ORMはTypeORM
    • コンテナ化してCloudRunにのっける
    • DBはMySQLをCloudSQLで
    • CloudSchedule + CloudRun(NestJSがのってる)でバッチ実行
  • その他
    • 認証はFirebaesAuthentication
    • 画像はCloudStorage
    • データ分析はBigQuery使ってもらう
      • CloudSQLのデータそのまま参照できる
      • googleアカウントでの参照設定をbiz系のメンバーに付与して、よろしくやってもらう
    • システム監視系
      • GCPのサービスで使えるやつは使う
        • CloudLogging
        • CloudMonitoring
      • Sentry
      • NewRelic
    • CI/CD
      • CloudBuild

この構成の推しポイント

  • Dockerコンテナ
    • インフラ構成的に、コンテナを採用するかどうかが最初の分かれ目
    • 学習コストがかかる場合があるが、十分payすると思う
      • コンテナベースのサービスを使える事によるお手軽さと拡張性の両立
      • ローカル環境
      • メンテ性
  • TypeScript
    • 新規サービスのフロントの言語としてはTypeScript一択
      • バックエンドも統一するとめちゃめちゃ効率が良い
      • 開発人数が少なくチームも分かれていない時、フロントとバックエンドを同じ人が開発する事が多い
        • 単純に頭のスイッチコストがかからない
      • 開発環境の共通化
        • lint等も共通化できる
      • webAPIのIFになるObjectの定義をコピペできる
        • 本当はIFのコードを自動生成した方がかっこいいが、、、
  • Nuxt(vue)
    • Reactの方が良いかも、、、と思う事が多いが(後述)、好みでvueを選んでも良いと思う
      • 私が慣れてるので、vueの方が開発が早い
    • vue使うなら、Nuxtを使わない理由はあんまり無い
    • vue3に対応したNuxt3はまだβなので、productionでは使えない
      • Nuxt2はTypeScript対応が微妙な時があるが、compositionAPIを使えば十分戦える
    • UIFrameworkはVuetify
      • これもvue3対応が、、、、
  • NestJS
    • TypeScriptのWebフレームワークなら一番良さそう
      • NestJS本体は薄いExpressのwrapper(Fastlyも使える)で、他のライブラリ(ORM等)と組み合わせる前提
        • 今までのNodeJSの資産が使えるのでできない事はほとんど無い
    • DI機能があって、テストが書きやすい
    • Web系のフレームワーク使った事ある人ならすぐ使えるようになる
  • TypeORM
    • TypeScript製のORMで、一通りなんでもできる
      • ただしbugが多め、、、
    • Entityクラスからのmigrationファイル自動生成が便利
    • ORM使ったことある人ならすぐ使えるようになる
  • GCP
    • 全体的にAWSよりシンプルで使いやすい
    • コンテナを使う場合、CloudRun、GKEともにAWSより洗練されている
    • 無設定でもそこそこ使えるものが多いので、構築にかける時間が節約できる
  • CloudRun
    • フルマネージドなのでインフラに工数かけたくない時にめっちゃ楽
    • 無料枠が結構あるのでしばらくは無料で戦える
    • バッチもこれでいける
  • Firebase
    • GCPと密結合で実質GCP
    • 無料で色々できるすごい
    • FirebaesAuthenticationは各種SNSでの認証が簡単にできて便利
    • firebae hostingはデフォルト設定で十分戦えるのが賢い
  • REST API
    • 安定。学習コストがかからない。
    • OpenAPIを使えばIFのコードを自動生成したりもできるので十分戦える
  • CloudSQL
    • 安定のRDB
      • いつかRDBだけだと対応できなくなる可能性はあるけど、しばらくはこれでほとんどの事ができる。困ったら考える
    • フルマネージドなので楽ちん。
    • MySQLかPostgreSQLかは好み
  • BigQuery
    • ちょっと設定すればCloudSQLと連携したデータ基盤ができあがる。すごい
    • 無料枠でも十分働いてくれる
  • Sentry
    • フロンドエンドのerror検知
    • 無料枠でも十分働いてくれる
  • NewRelic
    • バックエンドのパフォーマンス監視
    • 無料枠でも十分働いてくれる
      • DBのパフォーマンスも見てくれる
  • CloudBuild
    • GCPのCI/CDサービスなので、GCPの各種サービスと親和性が高い
    • 無料枠があるのでしばらく無料でできる

基本構成じゃないけど検討するもの/採用しない理由

サービス特性、好み、要はバランスになってしまうのですが、、、

  • シンプルにVPSなりでVM立ててLAMPな構成
    • めちゃめちゃシンプルなWebサービスであれば全然あり
      • 拡張性はイマイチ
    • 今この構成なのをどうにかしたい案件が自分の場合は多い
  • Rails
    • 色々と密結合になりがち
    • サービスをSPAにして、APIサーバとして使うにはFatすぎると思う
    • SPAにしない or Rails慣れてる人がいるならあり
      • 使いこなしてる人なら開発早い
  • Go
    • パフォーマンスを重視するサービスなら良い選択肢
  • Rust
    • パフォーマンスを重視 & ドメインが複雑なサービスならGoよりもハマりそう
      • 実務で使ったことはないので印象
  • AWS
    • GCPと比べると、設定できる項目が多く重厚
      • 逆に言うと設定が大変
    • インフラ周りで特別な要件がある時はAWSの方がやりやすい事が多い
    • Fargateあるけど、CloudRunと比べると設定が大変
    • 最終的にはお好みで
  • React
    • エコシステムが充実している
    • NextJSは機能がもりもりですごい
    • TypeScript対応はvueよりイケてる
    • 進化が早い
      • キャッチアップが大変
    • 最終的にはお好みだけど、vueに強い人がいるとかでなければReactの方が良いかも
  • PostgreSQL
    • 複雑なSQLを書いてもわりと頭良くIndex使ってくれる
      • ので、複雑なテーブル構成で、joinしまくるようなサービス特性の場合はPostgreSQLの方が良いと思う
    • 最終的にはお好み
  • NoSQL
    • Firestore等
    • RDBに比べると汎用性に劣り、使い所の見極めが必要
      • ハマれば強い
  • Spanner
    • 費用が高い
    • 意外と癖がある
      • ただのRDBと同じ感覚で使うと罠にはまる事があるので注意
    • DBへの書き込みがボトルネックになる事が見えている & お金かけて良いなら選ぶ
  • GraphQL
    • 使いこなせてる人が少なく、立ち上がり(学習コスト等)に時間がかかりがち
    • サービスの特性によってRESTと使い分け
      • RESTとの比較はこちらが参考になる
  • GKE(kubernetes)
    • 学習コストがかかる
    • プロダクト初期ではオーバースペックな事が多いと思う
    • 拡張性を優先するならチャレンジするのもあり。
      • とりあえずCloudRunなりでコンテナ化さえしておけば、後でどうにでもなる
  • CloudFunctions
    • 制限が許容できるか
      • 本格的にやろうとすると冪等性の担保が面倒
      • コールドスタンバイ
    • フルマネージドなサーバレスなので管理は楽
    • Node動くので実質TypeScriptでも書ける
    • ローカル環境等の設定を真面目にやりだすと、コンテナでCloudRunの方が楽じゃん?という気になりがち
    • 本当にちょっとしかバックエンドが無いなら十分
  • Netlify
    • firebase hostingできつい場合の選択肢
      • 権限周りがGCPとセットになっているのはfirebase hostingにメリットがある
    • 静的hostingに特化しているので、使いこなせば便利
  • Vercel
    • SSRしたくなった時のファーストチョイス
    • Vercel以外は、Nodeと静的ファイルを別に配置しないといけなかったり、cache戦略を考えたりと結構やる事がある
  • Prisma
    • TypeScriptのORM
    • 使った事無い
    • 2年前に検討した時はまだ未実装機能が多くて見送ったのだけど、今なら良さそう
    • 後発なので色々洗練されてるイメージ
  • Auth0
    • ちょっとしか触ったことない
    • 高い
    • お金があるならこっちの方が良さそう

その他SaaS/ツール等

  • SendGrid
    • GCPにはメールサービスが無いので使う
    • AWSの場合でも、SESよりSendGridの方が良いと思う
      • 海外サービスの場合、キャリアのメールアドレスに送れない事が多かったような、、、
  • Stripe
    • 決済ならこれ
    • なんでもできる。すごい
  • Terraform
    • 最初に頑張ると、以降楽できるのでおすすめ
    • 複数環境すぐに作れる
      • 途中からdev環境増やすとかありがち
  • Slack
    • チャットツールとしての使い心地は好みがあるだろうけど、システム的にはほとんどのSaaS系が連携に対応してるので楽

おわりに

以上、色々と知ってる事/考えてる事を言語化してみました。参考になれば幸いです。

「これはどうなの?」とかあればコメントいただければ知ってる範囲でお答えします!

まとめてみると、本当はこっちの方が良いけど経験が無いから避けてる系があるので(GraphQL、React、Prisma)、ここは勉強しないとな〜と思いました!

技術選定に役立ちそうなリンク

https://zenn.dev/marokanatani/articles/compare_vue_and_react
https://zenn.dev/moya_dev/articles/9ed3aa4290d6c4

Discussion

村長村長

LGTMです!

自分もNestJSをCloud Runに乗せて使ってます。
ただ、コールドスタート時のレスポンスの遅さが気になってまして
何かその辺りの対策をしていたらご教授願いたいです!

daisuke-fukudadaisuke-fukuda

ありがとうございます!

コールドスタート対策としては

のどちらか(あるいは両方)を採用しています。

負荷が集中してスケールするタイミングについては地道にやるしかないですね、、、(そもそもかなり早いとは思いますが

村長村長

なるほどです。

最小インスタンス数などの見積もりをする上での指標(レスポンス平均時間とか?)を
注視する必要がありそうですね

とても参考になりました!
ありがとうございます。

渡邊 陽平@フォカッチャ渡邊 陽平@フォカッチャ

とても参考になりました!

基本的にSSRしないということですが、動的ページに対して、SEO対策や各SNS等でのOGP表示といった要件がある場合、どのような対応をされることが多いでしょうか??
(自分はいつもSSRしてしまうので、何か他の方法があればと思い...)

daisuke-fukudadaisuke-fukuda

ありがとうございます!

その場合はNuxtのSPAモードでは対応できないので、SSRするしかないですね、、、
(私の場合はtoB向け、もしくはtoCだけどログイン前提のものが多かったので、SSRしない場合を基本とした記事にしています)

SSRする場合は、記事にもある通り自分の中ではVercelをファーストチョイスにしています。

渡邊 陽平@フォカッチャ渡邊 陽平@フォカッチャ

早速の返信ありがとうございます!

なるほど、管理画面系の想定ということであれば、確かにSSRは不要ですね。
SEO/OGP対策系は、Vercel等でSSRするのがベストそうですね。

Prerender.io などでプリレンダリングしてキャッシュするというのも手ではあるのですが、毎回、なんとなく手を出せずに(面倒そうなので)Next.jsでSSRしています😅

参考になりました!

daisuke-fukudadaisuke-fukuda

Prerender.ioは知らなかったので勉強になりました。ありがとうございます。

Prerender.ioは情報があまり多くないので、SSRしてる人の方が多いんですかね〜。