文化祭のWEBサイトとチケット発券システムを作った話

# はじめに
こんにちは、[Tomo](https://twitter.com/Tomo02721601)です。今回は、10/1(土), 2(日)に自分の高校で行われた文化祭の特設サイト、チケット発券システムを作成しました。

:::note inf
本記事の内容は、私が所属する学校にに非公式で公開しているものです。
本記事に関する問い合わせを学校へ行う行為は慎んでいただくようお願いいたします。
:::

# 自己紹介
現在高1で某進学校に所属する男子生徒です。中学2年生からWEBサイトの勉強を始めて今に至ります。今ではなんと自宅でサーバーを運用するほどになりました。
![IMG_4787.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/85c4391b-9b5f-e47b-6c8c-17151111347e.jpeg)
# 作ったもの
こういうの↓
![ezgif-1-f66467165a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/f07b005e-60ae-48de-ba66-fe87c15e4986.gif)




# 機能要件（自己満足を含む）
僕が自己満足するのに必要な要件と求められた要件があったので分けて書きます。
### 求められたもの
・文化祭に関するコンテンツを配信するWEBサイトが欲しい。
・著作権や肖像権的な理由から限定公開のコンテンツが欲しい。
・在校生招待客についてはオンラインでチケットを発行したい。

### 自己満足
・そこそこデザインが良いフロントエンド。
・GUI上から操作できる項目を増やして、当日や前日のエンジニアの負荷を減らす。
・Node.jsで書いてできれば自宅サーバーで動かしたい。

# フロントエンド
[I/O 3000 | Webデザインギャラリー](https://io3000.com/)にめちゃくちゃお世話になりながら作りました。デザインは最初紙にコンテンツを書き出したあとイラレでイメージを固めてコードにしていきました。ちなみに、夏休み前半のほうに作ったデザインは夏の終わりに気に入らなかったという理由でほぼほぼ捨ててしまっています。しかし、これも夏休み前半に格闘した甲斐あってのものだったったと思うので後悔はないはず....

### デザインコンセプト
カラフルで文化祭の彩が溢れるようなWEBサイトを目指しました。
また、昨年度の経験からいかにCSSを頑張っても一枚の写真の情報量には勝てないことを悟り夏の間は相棒のカメラと文化祭の関連団体の撮影に勤しみました。また、カメラが好きな友人からも画像の提供をたくさんいただきました。感謝!

### コンテンツの更新
昨年度の反省点として挙げられた、急な変更でエンジニアがサーバーのHTMLデータを直接編集しなければならない場面を減らしたかったのでトップ画面やメニュー画面の一部を管理画面から更新可能にして当日はコンテンツ担当のみで対処を行うことができました。

### 反省点
エンジニアのミスではないが、文章の募集や校閲に時間がかかってしまい、一部のコンテンツを公開することができませんでした。コンテンツをGUI上で更新できる部分が少なかったので、来年度はすべての文章を編集可能にしたいです。また、前述の問題もGUI上からWEBサイトの編集を可能にすることでエンジニアの負荷を少なくすることができる思います。

# バックエンド
Node.jsとMySQLで構築しました。

### アカウントの作成とログイン
生徒に与えられている学籍番号をIDとしてアカウントの管理を行いました。アカウントの登録方法についてアナウンス不足から一部混乱を招いてしまったので来年度はUIと合わせて工夫したいです。
![2022年度けやき祭-ログイン - Google Chrome 2022_11_16 10_06_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/147a6164-79a2-eacc-87c0-5e5077beeca2.png)

### チケットの発行
サーバー上でアカウントごとに3枚のチケットのQRコードを作成し、Base64文字列としてブラウザ側に転送させました。こちらは当日もトラブルなく運営できたので大満足です。
![2022年度けやき祭-ログイン - Google Chrome 2022_11_16 10_08_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/99e485de-dfef-904e-2111-9a02f72d6c14.png)
![2022年度けやき祭-ログイン - Google Chrome 2022_11_16 10_09_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/648e69cf-edef-73e5-3b7a-0444f8fc9ff2.png)

### チケットのスキャン
発行したチケットは入り口でスキャンされて入場が許可されます。


### 権限の割り当て・アカウントの管理
誰でもチケットの管理画面やスキャン画面を見れると不都合なので、権限を割り当てるシステムを作りました。他のコンテンツの更新や配信の管理などの画面の変更の権限もあります。
![2022年度けやき祭-マイページ - Google Chrome 2022_11_16 11_06_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/98d13ffa-4239-af20-b193-44dd5461195f.png)


# インフラ
今回は本体サーバーはオンプレで動かし、クラウド上にリバースプロキシサーバーを用意してオンプレが止まってしまった場合はクラウド上で最低限のシステムだけが動くような形にしました。

### オンプレ編
Proxmoxでclusterを構築し複数のVM（DB、Node.js、nginx_proxy）を用いて運用しました。また、毎日VMのスナップショットデータとDBとpm2のログとnginxのログをNASにバックアップして障害に備えました。また、学校の契約しているGoogle for educationでGoogle Driveを無制限に使うことができたのでNASからrcloneを使って自動的にアップロードして最悪家が燃えてもクラウド上で復旧が可能な状況を作りました。

:::note inf
Nginxのgzipの設定や細かなバックアップ方法などは気分次第で記事にします。
:::

### クラウド編
クラウドはセキュリティ上の都合であまり話せる事がありませんが、AWSの無料枠で監視を行い、別途契約したリバースプロキシサーバーを制御していました。自宅サーバーが動いているときは完全なリバースプロキシですが、自宅サーバーが停止すると自動的に静的なコンテンツページのみが表示されるだけの状態に切り替わります。

# 当日の様子
アリーナのライブ配信など様々なコンテンツを掲載していたため、予想以上にアクセス数が伸びました。クラウドリソースを挟んでいるとはいえ、自宅サーバーにかなりの負荷がかかったと思います。停止しないかはらはらしていた2日間ですが、無事に終えることができました。
![スクリーンショット 2022-11-16 110114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/15eae6b0-e762-69ef-5b54-111958ac515a.png)

# まとめ&感想
ほぼ一人で要件定義からインフラ、運用までを経験できて楽しかったです。今回、掲載した画面はテストの開発画面ですが、本番環境ではくらべものにならないくらい多くの情報がありました。本番環境が動作してる様子に興奮を覚え、この達成感を嚙みしめつつこれからも技術に対して向き合い邁進していきたいです！

PS 好評ならデザイン編、開発編、インフラ編、本番環境&SEO編を書きます。