🔥

文化祭で始めるトレンド技術スタックWebアプリケーション開発【紹介編】

2022/10/26に公開約5,100字

やぁ。

こんにちは、dino a.k.a. shioです👋
とある茨城高専で学生をしています。

10月に開催した茨香祭にてWebアプリケーション「OZ」を作成したので、その †限界開発譚† を徒然なるままに書いていこうと思います。
まさか炎上プロジェクト🔥なわけないよなぁ...

https://3i.shikosai.net

https://github.com/3I-shikosai32/shikosai32-front

https://github.com/3I-shikosai32/shikosai32-server

どんなの作ったん?話聞こか?

以下は、弊学級が作った出し物「OZ」の簡易シーケンス図です。

ここから見て分かるように、Webアプリケーション「OZ」はユーザーとそのポイントの管理を主な機能とします。

基本機能

以下に、「OZ」の基本機能をまとめてみました。

ランキング

茨香祭は2日間に渡って開催されるため、1日目と2日目の二つのランキングを作成します。
また、現地のスクリーンで表示するため、自動的に表示するランキングの種類が切り替わるようになっています。

ゲーム

ユーザー側

ゲーム一覧画面では、「OZ」が提供する全6種類のゲームの参加状況をリアルタイムで見ることができます。

また、各ゲームの詳細ページでは、現在そのゲームに参加しているユーザーの情報(ユーザーネーム、アバター)がリアルタイムで表示されます。
難易度やルールも併記されているため、参加する際にそういった情報を参照できるようにした所もこだわりです。

スタッフ側

管理者用画面では、各ユーザーへのポイント付与と強制退出をさせることができます。
例によってここもリアルタイムでユーザーの入退出が反映されるので、一々リロードする必要はありません。

景品交換

ユーザー側

ゲームをしてポイントを獲得したユーザーは、自分のポイントと景品とを交換することができます。
この際、「ランキングに反映する用のポイント」と「景品と交換する用のポイント」は別々のフィールドとして用意してあるため、景品と交換することでランキングが下がることはありません。

スタッフ側

現地の景品交換所で待機しているスタッフは、景品交換履歴を見ることでどのユーザーがどの景品を購入したかが見れるようになっています。
このとき、「受け渡し済みかどうか」というフィールドを持たせることで、景品を渡し忘れるという状態を未然に防ぎます。

技術スタック

冒頭で述べたとおり、FE/BEの詳細は別記事でまとめるため、ここでは簡易的な紹介に留めさせていただきます。

フロントエンド

Framework

  • Next.js
    • 言わずもがな、様々なレンダリング方法を提供するFEのフレームワーク。なお「OZ」では結局ISRとかは使わなかったため、実はViteとかでもよかったんj(ry

UI

  • React.js
    • 宣言的にDOMを構築できるUIライブラリ。今回メンバーにVue.js経験者がいなかったため、「OZ」内でのReact.js/Vue.js戦争は一瞬で幕を閉じた。
  • Tailwind.CSS
    • 既にいくつかのクラスが用意されており、それらを組み合わせることでスタイリングができるCSSフレームワーク。導入後、Tailwind.CSSのクラスは詳細度が全て同じなために、コンポーネントの外部からclassNameを受け取ったときの挙動が安定しないことが問題となったが、tailwind-mergeを導入したことで解決。
  • Radix UI
    • スタイリングはなく、コンポーネントのa11yに焦点があてられたheadless uiコンポーネント。tailwindと併用すると脳汁ドバドバでバチクソ楽しい(個人の感想

State

  • Recoil
    • React Context APIだけだと無駄な再レンダリングが発生してしまうので、代わりのstate管理として導入。外部からatomを参照できないようにするために、ちょい設計に気を遣う必要がある。

Fetch

  • URQL
    • Apollo Clinetよりも軽量なGraphQL Fetch及び状態管理ライブラリ。必要なexchange(プラグイン的な)を取捨選択できるのが好き(個人の感想

Develop

  • StoryBook
    • UIコンポーネントのカタログを作成できる。これをChromaticにCDすると、レビュアーはとても幸せになれる(経験談
  • react-magnetic-di
    • StoryBookにコンポーネントを載せる際に、fetch系のカスタムフックや時間依存系のカスタムフックを注入できる。これがないとStoryBook書けないくらい便利。

バックエンド

Framework

  • NestJS
    • くっそ堅牢なサーバーフレームワーク。REST APIもGraphQL APIも作成できる。標準でDIコンテナを提供しており、これを使うと一瞬でクリーンアーキやオニオンアーキが構築できる。

ORM

  • Prisma
    • 比較的型安全なORM。同梱のPrisma Studioが便利だったり、schema.prismaの書き心地が良かったりするので採用。NestJSとの相性も悪くない。

Store

  • dataloader
    • GraphQL APIを作るとき必ずと言っていいほど遭遇するN+1問題の解決者。当初はPrisma Fluent APIだけでこの機能が満たせるものと思っていたが、全然そんなことはなく結局お世話になった。

限界開発譚

7月あたま

弊学級の委員長の発案により、「OZ」の概略が説明されます。
ちなみにこのときのみんなの頭にある「OZ」は十人十色でした(えぇ...

8月あたま

弊学級のプログラマ、デザイナ、イラストレータ、ミュージシャンが集まりそれぞれのタスクとロードマップを決めます。

8月おわり

デザインの締切二日前にして、Figmaのプロジェクトが空っぽであることに気が付きます。
急いでデザイナに問い合わせたところ、「茨香祭の他の準備が忙しくてこっちまで手が回っていない」とのこと。
あっ終わった──。
そう思う暇もなく、私ともう一人のフロントエンドエンジニアの二人でチキチキ☆深夜のデザイン☆耐久レースが幕を開けました。
そしてこの翌日、無事デザインは完成を迎えることとなります(当社比

https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Ffile%2FsfwYU5BKtdxAPxaE9ciAi7%2FOZ%3Fnode-id%3D0%253A1

9月あたま

デザインが完成したので、プログラマが本格的に動き出します。

9月おわり

サーバーが大規模なリアーキテクトに迫られます。
というのも、当初はNestJSのチュートリアルのようなディレクトリ構成だったため、各クラスの責任が曖昧になり、どこにどんなコードがあるのか分からず、またテスタビリティも悪かったためです。
慎重な下調べの結果、リアーキテクト後のアーキテクチャにはオニオンアーキテクチャを採用しました。

10月あたま

茨香祭当日を目の前にして、フロントも大規模なリアーキテクトに迫られます。
理由は、サーバーでのGraphQL Schemaの変更に対して、フロントでの変更点が多すぎたためです。
そのため、変更容易性に焦点を当て、ModelUseCaseStorePresenterContainerInfraなど、いくつかの層に分割しました。

茨香祭当日

さて、やんややんやとコーディングをした2ヶ月でしたが、茨香祭当日を迎えた我々の進捗は...。

わい「進捗5割にも満たないじゃあないか!!」

ということで、当たり前のように当日もコーディングを行います。
当日において認証機能が動作していなかったり、一部機能に致命的なバグが生じて半分にも満たない機能のままリリースしたりしたのはまた別のお話...。

茨香祭が終わって

茨香祭が終わり、私は今Zenn記事を書いています。
振り返れば、プログラマとしてかなりの成長を遂げた2ヶ月だったなぁと感じています。
それも、共に開発をしてくれた友人やそのバックアップをしてくれた弊学級のみんな、茨香祭を運営してくれた色んな人たちのおかげだと思います。
この場を借りて、お礼をさせてください。
ありがとうございました。

おわりに

ここまでクソナガ文章を読んでくださり、ありがとうございました。

次は(気が向いたら)OZのサーバーについてのお話を書こうかなと思っています。
(どっちかというとそっちが本命だったり...)

またね。

Discussion

ログインするとコメントできます