LaravelとReactでモダンなwebアプリケーションを開発してみた【Laravel / React / Vercel / Supabase】

# はじめに
このアプリは部活で実際に使うことを想定して作ったアプリで、部員でないと機能が分かりにくいかもしれません。事前知識を下に書いてあるのでそちらを一読してください🙇‍♂️
# 自己紹介
現在大学３年生で専攻は電子&機械工学でCSとは異なる勉強をしています。
独学でreactを3ヶ月ほど勉強した後に2024年3月から現在まで長期インターンでlaravelとreactを使って受託開発をしています。

# サービスの紹介

https://windap.jp

### サービス概要
Windapは自分が所属しているウィンドサーフィン部の活動を便利にするようなアプリです。カレンダーや練習ノートの共有や海に出るときの連絡、匿名質問ができるようなアプリです。

### Windapを開発しようと思った経緯
今まではLINEで欠席連絡をしてTimeTreeでカレンダーに記入しマネージャーが部員の練習回数を管理し、週末に今週練習に来なかった人をLINEで報告していました。
複数のアプリを使うことによって連絡のし忘れが増えてしまいマネージャーの仕事が増えてしまうといった問題があったので、1つのアプリで完結させるために開発を決めました。また、匿名で質問や回答をでき日々の練習の気づきをノートにまとめ部員同士共有できる機能をつけることで部のボトムアップをできると考えました。

### このアプリを知ってもらうための事前知識
#### 出艇とは
* 意味：海に出て練習を行うこと
* 規則：週3回以上の出艇が必須
    * 1年生の場合：上級生(2年生以上)との同伴が必要
    * 1年生が上級生に出艇を依頼することを**イントラを頼む**という
* 出艇を登録するタイミング：出艇をする前日か当日

# 工夫した点
1つ目はPCではなくスマホで使うことを想定しているのでネイティブアプリライクなUI構築をし、極力モーダルを使うことでページの遷移をできる限り減らすことでユーザ体験を向上させました。

2つ目は出艇の時間が視覚的にわかるよう表とガントチャートの2種類で確認できるようにしている点です。ガントチャートの良いところは自分と他人の出艇時間の重なりを視覚的にわかるため導入を決めました。

3つ目は出艇を登録する画面で日付を今日と明日で選ぶことができ、時間と日付を別々に選ぶ点です。DateTimePickerのようなライブラリで一度に入力する方がバックエンドの型がdateTimeであるため楽でした。しかしDateTimePickerでカレンダーから日付を選ぶのではなく2択で選んだ方がユーザの手間が減ると考えました。

# GitHubのレポジトリ
バックエンド

https://github.com/shutaLab/windap-api

フロントエンド

https://github.com/shutaLab/wind-app-front

## 使用技術
**バックエンド**: PHP 8.3.4 / Laravel 10.48.9
* 認証: Laravel Sanctum (SPA認証)
* DB: PostgreSQL

**フロントエンド**: TypeScript 4.9.5 / React 18.2.0
* 主要なライブラリ、パッケージ: Axios / TanStack Query /  FullCalendar / ReactHookForm / Zod / dayjs / mui-icons /  
* CSSフレームワーク: Tailwind CSS 
* UIコンポーネント: shadcn/ui

**インフラ**: Vercel / SupaBase(DBだけ使用) / SupaBaseStorage / MailTrap
**ドメイン**: お名前.com

### 機能一覧
* **認証 Authentication**: メールアドレスとパスワードを利用したユーザー登録 / ログイン機能
* **ユーザ User**: ユーザプロフィール登録機能 / プロフィール画像登録機能
* **出艇 Departure**: 出艇者一覧 / 登録 / 更新 / 削除 / 今週出艇していない人、連絡をした上で出艇していない人を割り出す / 出艇回数ランキング / イントラ受理 / イントラ拒否
* **カレンダー Calendar**: 予定一覧 / 登録 / 更新 / 削除 
* **ノート Note**: ノート一覧 / 登録 / 更新 / 削除 / お気に入り機能
* **質問 Question**: 質問一覧 / 登録 / 更新 / 削除
* **回答 Answer**: 登録 / 更新 / 削除

### 主要機能の紹介
#### 
**出艇 Departure登録**

| 1年生が出艇を登録しイントラを依頼する | 上級生がメールを確認する  | 上級生がイントラを承諾する  |
|---|---|---|
| ![departureCreate1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/f4f99294-654c-6a1f-689a-36336a03e946.gif) | ![スクリーンショット 2024-11-29 15.41.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/e0e5dfc3-864e-2fb1-3bae-bb12074d7fae.png) | ![departureCreate2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/c4be17cf-625e-04f0-2945-3647568f51ab.gif) |

* **カレンダー Calendar登録**
日曜日にだけ下記のような表が表示されます。月曜から土曜までに出艇していない人だけ表示されるので出艇が登録されているtestUserは表に表示されていません

| 欠席連絡を入れることで未連絡の欠席から連絡済みの欠席になる |
|---|
| ![calendarCreate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/fa0ffdba-bcb1-06e9-60d3-3c85eddacd8d.gif) |

### ER図
 * #### 出艇、イントラ申請、カレンダー、通知
![スクリーンショット 2024-11-26 7.06.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/c0e0f39d-b2ae-dbcb-98f0-025d4df948d0.png)
 * #### ノート、質問、回答
[![answer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/21493e99-4afa-9850-b399-ff600174c99f.png)

* #### ユーザ
![スクリーンショット 2024-11-26 7.07.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459340/ee2102c7-6781-6f29-cbdb-a12484e946df.png)

## 選定技術の採用理由

### バックエンド : PHP / Laravel
**検討技術**: Ruby / Ruby on Rails
**選定理由**: 
* ProgateでRailsを少し勉強していたのでRailsにしようと思ったがインターン先がLaravelを使っていたためインターンで学んだことを個人開発にそのまま活かせると思ったため
### フロントエンド : TypeScript / React
**検討技術**:  Next.js
**選定理由**: 
* ReactもProgateで勉強していたので土台があったが、Next.jsを新しくキャッチアップするのに時間がかかると判断したため。

### DB : Supabase
**検討技術**:  heroku cleardb(mysql)
**選定理由**: 
* supabaseに興味があって使ってみたかったため。制限はあるものの無料で使え、pgsqlを基盤にしているリレーショナルデータベースであるため。
* ストレージも無料で使えるため
### ポートフォリオ作成に使ったサービス
色々なサービスを使った中で主なサービスを紹介します。

#### ChatGPT
エラー調査、変数名の命名に使いました。claudeも使っていましたが、課金さえすれば制限なく使えるchatGPTの方が使いやすいと思いました。

#### Mailtrap
開発環境でのメール送信テスト、本番環境でメールサーバとして使用しました。月に1000配信までは無料で使用できるのでかなり優秀だと思います。ただ、コンプライアンスチェックを受けるため多少英語でのメールのやり取りが必要です。

https://mailtrap.io/ja/

#### Canva
ブランドロゴ、メインビジュアルの作成に使用しました。
ブランドロゴはCanva内のAI画像生成で作ったのですが、なかなか自分のイメージした画像が生成されないので何回も生成し直しました。一ヶ月は無料で使えます。

https://www.canva.com/

## 苦労した点
cookie認証を行っているのですが、ミドルウェアの設定やconfigの設定の間違いでcookieが保存されないことで認証できず改善するのに多くの時間を使ってしまいました。

本番環境特有のエラーがいくつも起きてしまった点です。例えばフロントエンドとバックエンドのドメインが違うことで認証ができなかったことです。また、vercelへのlaravelのデプロイする情報があまりネットに出ておらずvercel.jsonの作成に苦労しました。

## 実際に使ってもらって
一旦、2週間だけのお試しですが実際に使ってもらいました。
### 改善点
* **匿名にするかどうかは選択制にする**
「誰が回答したのかわからないと不安。」「聞きにくい質問だけ匿名でいい。」とのことでした。
質問をするのが怖い、といった人を質問をすれば答えてくれるんだと気づいて欲しいと言う願いでこの機能をつけたのですが、質問や回答の質を担保しづらいという欠点がありそうです。ですので匿名にするかどうかは、ユーザに選んでもらうという形が一番いいかもしれません。
* **メール通知ではなくプッシュ通知にする**
「メールの通知をオンにしたくない。」「メール通知が鬱陶しい。」これに関してはリリース前から自分でも気づいていましたが、そのままリリースしてしまいました。一番工数が少ないのはPWA化することですが、laravel,reactのPWA化の情報がなかなか見つからずかなり難しいかもしれません。勉強します、、
    
## 次のステップ

次に学習すべき・もしくは学習したいこと

* SQL (絶対)
* Docker (絶対)
* AWS (絶対)
* Next.js (絶対)
* PWA (したい)
* Go (したい)

2台のPCで開発を行っていることもあり環境構築やデプロイの際、Dockerで環境構築していれば、、、と何度も思いました。UdemyやChatGPT先生との壁打ちなど、プログラミング学習がしやすい時代なので今後も学習していきます。

# 最後に
反省点として、ちゃんと設計をしてから実装を始めなかったことが挙げられます。自分は設計を殆どせずに見切り発車で開発を始めてしまいました。そうすると開発しながら作りたい機能を決めていったことによってDB設計を何度も変えてしまい無駄な時間を費やしてしまいました。
最初に設計をする良い点として、必要な機能を絞ってスピーディーに開発を行えます。実装を進めている中でこの機能欲しいかも、と思うことがたくさんありました。しかし、必要な機能に絞ってシンプルなアプリにする方が結果的に使いやすいアプリになると思います。