🔩

スコラボを支える技術 (2023/01版)

2023/12/20に公開

スコラボ という配信者・VTuberがもっと気軽に、もっと楽しく配信ができるように、配信をサポートするサービスを作っています。
実際どんなサービスかについては、利用が基本無料ですので触っていただけると嬉しいです。

今回は、2023年1月時点でのスコラボを支えている技術やサービスを紹介します。(すでに公開時点で年末で、もうすでにめちゃめちゃ変わってはいるのですが...最近の話は別記事で...)
今後もどんどん改善していきますし記事公開日にもすでに変わってしまっている部分もありますが、この記事ではサービス公開当初〜2023年1月に利用していた技術・サービスをご紹介します。
私自身はフロントエンドとインフラばかり触っているので、フロントエンドとインフラの話だけを書きますが、バックエンドについても別日に出るカモしれません!

フロントエンド

Next.js

フロントエンドではNext.js(React)を使っています。
TypeScriptとの相性やSSRを今後使う可能性がかなり高かったことも理由としてはありますが、開発の初めから2022年12月中旬までフロントエンドエンジニアが私一人だったこともあり、開発スピードを考えた上で慣れているNext.jsを採用しています。

appDirについては後述するUIライブラリの都合や、バックエンドとの繋ぎこみの関係から使用していません。

Chakra UI

UIフレームワークとしてChakra UIを採用しました。
必要なコンポーネントがしっかりと揃っており、カスタマイズ性もかなり高い素晴らしいUIライブラリです。

依存関係としてFramer Motion / Emotionがある関係もあり、appDirでそのまま利用することができなかったり、Bundleサイズが肥大化する問題も存在しますが、開発速度を犠牲にするほどではないと考えています。

ただ、サービスの規模も大きくなってきていますので大幅な変更を行う際に段階的にTailwind CSSなどのバンドルサイズが小さく、小回りの効くフレームワークへの変更も検討していく必要があるかなと考えています。

SWR & Aspida

データ取得系はSWRとAspidaを組み合わせて利用しています。

SWR

今だとReactQuery(現TanStackQuery)がいいよと推してくれる方もいるかと思いますが、開発初期の段階で触ったことが合ったのがSWRだったため、SWRを採用しています。
~Vercelが開発していることもあり、開発については安定感があるため、強い理由がない限りはReactQueryへの移行をすることはないでしょう。(この辺りは好みだと思っています)~
と書きましたが、今は少し迷いがあります

Aspida

実際のAPIリクエストにはAspida (@aspida/fetch) を利用しています。
リクエストが簡潔に表現・記載できるというメリットやAPIサーバへのリクエスト・レスポンスにTypeScriptの型を効かせられるため導入しました。
現在はOpenAPIで記述したAPI仕様を元に openapi2aspida を使ってAPIクライアントを別パッケージに切り出して利用しています。
このことでバックエンドとの仕様のズレも少なくなり、開発体験がかなりよくなっています。(Solufaさんをはじめとするaspidaを開発いただいてる皆様ありがとうございます)

Moveable

スコラボの一番重要かもしれない編集画面の素材・時計の配置操作(↓の画像の赤枠内の操作部)にはMoveableを利用しています。
編集画面 配置部分に赤枠

当時の画面

旧UI編集画面 配置部分に赤枠

Canvasで頑張るという選択肢もありはしたんですが、時計の存在や自分自身あまりCanvasに詳しい・実装経験が豊富とは言えない状態だったため、Moveableをある程度無理なやり方をしながらも使うという選択肢を取りました。

dnd kit

シーンの並び順の操作やアイテムのレイヤー順の操作(↓の画像の赤枠内の操作部)のためにdnd kitを利用しています。
編集画面 dnd kit利用部分に赤枠

当時の画面

旧UI編集画面 dnd kit利用部分に赤枠

ReactでDrag & Drop的な動作を実現しようとするとreact-draggableかdnd kitをえらぶことになると思いますが、今回は並べ替えという操作に利用するためdnd kitのSortableとの相性がとても良く、実装コストが低かったためdnd kitを採用しています。

ESLint / Prettier / TypeScript

社内として厳格なコーディングルールを決めない代わりに、ESLintPrettierを導入してそれらのルールに従うという形を取っています。
また原則、JavaScriptは使わずにTypeScriptで記述し、開発体験とコードの安全性・保守性の両者を確保するようにしています。(ライブラリの都合で一部JSを利用する場合もあります)

テストは?Storybookは?

テストやStorybookは初めの余裕のあった頃はかなり頑張って作っていたのですが、途中から整備が追いつかなくなり人力QAを行うことになっています...
今はすこし落ち着いていることもあり追っかけで整備を進めています...

インフラ・外部サービス

Google Cloud Platform

Cloud Run

フロントエンド・バックエンド共にCloud Run上にデプロイしています。
リリース前に負荷テストを行って正常にスケールアウトしてくれるようなCPU・メモリ上限を設定するようにしています。
実行環境の第2世代についてはメリットがあまり感じられず、コンテナ起動時間が2~4倍に伸びてしまうというデメリットが出たため利用していません。

フロントエンド1サービス・バックエンド2サービスの計3サービスのCloud Runが存在します。

なぜバックエンドは2サービス存在するの?

バックエンドのサービスが2つ存在するのは、OBSから表示情報を取得するGETリクエストがかなり多くなるため、そのリクエストだけメインのCloud Runサービスとは別のサービスで受けるようにするためです。

OBSの表示情報を取得するリクエストがエラーになると、配信を行っている利用者さんが表示することすらもできなくなってしまうため、そこのリスクをなるべく下げるためという意図もあります。

Load Balancer

計3サービスのCloud Runに対してCloud Load Balancerでパスルーティングを行っています。
そのため、Cloud Runを直接露出させずに内部かロードバランサからのトラフィックのみを許可するようにネットワーキングルールを設定しています。

Cloud SQL

DBはPostgreSQL on Cloud SQLを利用しています。
Cloud Spannerや(現在では)AlloyDBも検討しましたが、現状ではコストが見合わないことからメインで1台とリードレプリカ1台の構成にしています。
リードレプリカが存在する理由はバックエンドのCloud Runが複数台存在するのと同じ理由です。

Memorystore

セッション管理等にMemorystore for Redisを利用しています。
Redis Enterprise Cloudも開発環境では利用していますが、様々な問題から本番環境での導入には至りませんでした。(Memorystore for Redisくんお高いんですよね...)

Serverless VPC Access Connector

Cloud RunとCloud SQL・Memorystore・Cloud RunはVPCを通じて通信させていますが、Cloud RunはCloud Run for Anthosを除いてネイティブにはVPCに接続できない仕様です。
そのためServerless VPC Access ConnectorをCloud Runに対して接続することでVPCに接続できるようにします。

Cloud RunからCloud SQLに対してはServerless VPC Access Connectorを利用しなくても接続することが可能ではありますが、実際のCloud Runの挙動としてはCloud SQL Proxyを使ってCloud SQLにアクセスを行うことからAPI Quota等の制約をもろに受けるため利用していません。

Cloud Storage

様々なサービス内で提供している素材の保存・Cloud Buildの一部Artifactの保存用に利用しています。

Cloud CDN

Cloud Storage内にある素材の配信時にCloud CDNを利用しています。

Cloud Armor

Cloud Load Balancerの前にArmorを設置することで、ある程度の攻撃を弾けるようにしています。

Cloud Build

Cloud Runへの自動デプロイに利用しています。
共有プールを初めは利用していましたが、デプロイにあまりにも時間がかかるようになってしまったため、プライベートプールを利用しています。
短期的にはプライベートプールを利用してデプロイ時間を短縮しつつ、長期的にはデプロイのキャッシュ戦略等を考えて根本的な解決に向かっていくようにしています。

Identity-Aware Proxy

社内ツールやGrafana、開発サーバなどに社外の方からアクセスされないようにする防壁として使用しています。
これのお陰でVPNの整備&接続というとても辛いことをする必要がなくとても助かっています。

GitHub

みんな大好きGitHub!ソースコード管理だけでなく、利用規約やプライバシーポリシーなどのバージョン管理にも利用しています。

Grafana on GCE

GrafanaをGCE上で立ち上げて、監視基盤・データ収集基盤として利用しています。
監視のAlertはGrafana Alerting経由でSlackに飛ばしていますが、今後Grafana OnCallを利用する予定です。

Cloudflare

Cloudflare Pages

公式サイト( https://www.sucolab.jp/ )やバックエンドのところでも書いたOpenAPIから生成したReDocをCloudflare Pagesにデプロイしています。

Cloudflare Workers

社内ツールやSlackのボットなどが一部Cloudflare Workers上で動いています。

Cloudflare Zero Trust

APIドキュメントなどを社外から閲覧されないようにするため、Cloudflare Zero Trustを使ってアクセス制御をしています。

imgix

すべての画像の配信はimgixを通してある程度最適化されています。
リクエストするURLの生成はnext/imageにお任せしていましたが、Next.js v13から自分でloaderを作らなくてはいけなくなったので、react-imgixを使って生成する方法に変更中です。(この部分はまた別な記事で書くかも...?)

Algoria

現在存在する素材を検索する機能にはAlgoriaを採用しています。
synonymsをある程度設定していたり日本語向けに設定を変更していたりはしますが、なかなか思うような検索精度が出せておらず、さまざまな方法を検討している最中です。



今後(すでに今も)、サービスを展開していく中で様々な技術・サービスの変更があると思いますので、定期的(不定期)にこんな記事を投稿していこうと思います。

なにか気になることなどあればぜひコメントでお教えください!
また、この記事から弊社に興味を持っていただいた副業や転職先を探している方は私までご連絡ください!

スコテック

Discussion