主にスキル向上を目的に、ポートフォリオとしてタスク管理アプリ (Miwataru) を作成しました。
これはシングルページアプリケーション (SPA) になっており、フロントエンドには、TypeScript / React、バックエンドには、PHP / Laravel、インフラには、Vercel (静的サイト) / AWS Lambda (API) を使用しています。詳細は後述の開発環境 (フロントエンド)、開発環境 (バックエンド)、本番環境をご覧ください。
アプリケーションや作成したコード、実装過程の説明については、以下のリンクからアクセスできます。
- アプリケーション:
https://www.miwataru.com/ - GitHub: https://github.com/zuka-e/laravel-react-task-spa
- フロントエンド実装過程: https://qiita.com/zuka-e/items/60afcc09464e10162338
- バックエンド実装過程: https://qiita.com/zuka-e/items/3faf100cbcdf7ec40ee6
目次
機能
- 認証
- ログイン / ログアウト
- Cookie / セッション
- ユーザー登録 / 表示 (マイページ) / 更新 / 削除
- メールアドレス認証
- 未認証ユーザー削除 (定期処理)
- ユーザーパスワード更新
- パスワードリセット
- ゲストユーザーログイン (認証済み)
- ゲストユーザー登録 (未認証、ランダムメールアドレス)
- ログイン / ログアウト
- タスク (カード) 管理
- 作成 / 表示 / 更新 / 削除
- リスト (カードグループ) 作成 / 表示 / 更新 / 削除
- ボード (リストグループ) 作成 / 表示 / 更新 / 削除
- 絞り込み
- 並び替え
- 選択型 (日付、昇順 / 降順)
- ドラッグ&ドロップ型
- 状態保持
- 検索
- ページネーション
開発環境 (フロントエンド)
フロントエンドの開発言語としてTypeScriptを使用し、ライブラリとして使用したのはReactです。またこれらを基本とした開発環境の構築にはCreate React App (CRA)を用いており、これによって、Reactを実行し結果を確認できるサーバーなどのReactの利用に必要な環境が簡単に用意できます。その他実行環境は以下のようになっています。(括弧内の数字はバージョン)
-
Create React App (4.0.3)
- Yarn (1.22.10)
- Node.js (16.6.1)
- TypeScript (4.2.4)
- React (17.0.2)
動作確認のブラウザには、Chrome (Mac、Android) を使用しています。
開発環境 (バックエンド)
バックエンドの開発言語にはPHP、WebアプリケーションフレームワークにはLaravelを利用しました。開発環境の構築には、Laravelから公式に提供されているLaravel Sailを用いており、これを実行することで開発用のサーバーが起動し、データベースやセッションストアの他、メール送信まで行うことができる環境が整います。
Laravel Sailにデフォルトで用意されている環境はカスタマイズすることも可能ですが、今回は特に変更を行っておらず、構築した環境は以下のようなものです。
- Docker for Mac (3.6.0)
- Laravel Sail (1.4.7)
本番環境
フロントエンド側で生成された静的ファイルのホスティングサービスとして、Vercelを選択しました。一方、バックエンドで作成したAPIは、AWS Lambdaで実行しています。そこで使用したサービスと用途については以下に列挙した通りです。
- Vercel - 静的ファイルホスティング
- CloudFormation - AWSリソース構成
- Certificate Manager - SSL/TLS 証明書発行 (API用カスタムドメイン)
- API Gateway - API (Lamdba) アクセス
- Lamdba - サーバレスコンピューティング (Laravelアプリ実行)
- VPC - 仮想ネットワーク構成
- VPC Endpoint - VPC内外プライベート接続
- RDS (MariaDB 10.4.13) - RDB
- DynamoDB - キャッシュ、セッションストア
- S3 - アセットストア
- Amazon SES (SMTPインターフェイス) - カスタムドメインメール送信
- IAM (ユーザー、ロール、ポリシー) - アクセス管理
- Systems Manager (パラメータストア) - 機密情報保管
- CloudWatch (ログ, イベント) - ログ管理、Lamdba関数トリガー (Cron)
インフラ構成図
アプリケーションの基本的な処理の流れとしては以下のようになっています。
- ユーザーは、VercelにデプロイされたURLからアプリケーションにアクセス
- APIの機能が必要な場合は、API Gatewayに向かってリクエストを送信
- API Gatewayによって呼ばれたLambdaが以下のような処理を実行
- Cookieの付与、DynamoDBによるセッション管理
- データベースからデータの取得や更新
- 必要に応じてユーザーにメールを送信
- ログをCloudWatchに保存
これを表しているのが以下の図です。
上記で触れていないポイントについて簡潔に説明していきます。
まず図の上部のCloudFormationについて、これは設定ファイルに基づいてAWSリソースの構成が役割です。このとき例えばパスワードなどの秘匿情報が必要となるので、Systems Managerのパラメータストアという機能を用いてその値を安全に扱っています。
次に、Certificate Managerについて、これはカスタムドメインに対するSSL/TLS 証明書の発行を行っています。ここで設定するドメインはブラウザのURL欄に表示されるものではなくそのサブドメインです。ユーザーが直接アクセスするメインのドメインはVercelによって設定を行います。
次に、Lamdbaについて、まず前提として通常LambdaをVPC内に設置しませんが、ここではVPCと共に構成しています。これはRDSとの接続を行うためです。RDSはVPC内に設置されているので、アクセスするためにはパブリックアクセスを有効にするかまたはVPCから行う必要があります。後者の方がセキュリティの観点で優れているため、VPC内でLamdbaを利用しています。
一方、LambdaはDynamoDB及びSESにも接続していますが、これらはRDSとは異なりVPC外のリソースです。通常アクセスするためには、Lambdaのロールに適切なポリシーをアタッチするのですが、VPC Lambdaはインターネットに接続不可能という問題があり、これだけではまだVPCの外に存在するリソースにアクセスできません。そこで、間にEndpointを挟むことでその問題の解決を実現しています。
最後に図の下部に位置しているLambdaについて、これは先述のものとは異なり、APIリクエストによって実行されるのではなくイベントをトリガーとして起動します。ここではスケジュールをイベントとし、指定した時間になると事前に設定した関数を実行する仕組みになっています。
以上が今回構成したインフラの概要です。
参考:
Environment variables - Bref # Secrets
Custom domain names - Bref
Using a database - Bref # Accessing the internet
Cron functions on AWS Lambda - Bref
ER図
Laravelでは初めから様々なマイグレーションファイルが用意されています。それらを含めて生成されたER図は以下のようになりました。
上記の図の内、今回のAPIのために作成したのはusers
と繋がっている部分です。タスクをtask_cards
(カード) という最小単位で扱い、それらの集合がtask_lists
(リスト) となり、task_board
(ボード) は複数のリストを持つという関係になっており、またそれぞれがusers
に所属しています。
ER図の作成には、MySQL Workbenchというツールを用いました。
MySQL Workbench
MySQL Workbenchとは、GUIでデータベースの作成や操作などを行うことができるツールです。機能の一つとして、既存のデータベースの情報を用いてER図を出力することができます。
ER図を作成するにあたって問題に思ったのは、データベースとの不整合が発生する恐れがあることです。先述の通りLaravelにはデフォルトで用意されているデータベースが存在しており、自身で作成していないことから、それらは特に見落としが発生してしまうと考えました。
そこでデータベースの情報からER図を作成する手段を探していた所で、MySQL Workbenchを利用する方法に辿り着き、これによって作成の手間を省きER図とデータベースの整合性を保つことが可能となりました。
使用技術 (フロントエンド)
- TypeScript (4.2.4) - 開発言語、静的型付け
- React (17.0.2) - SPA構築ライブラリ
- React Router Dom (5.2.0) - ルーティング
- React Helmet Async (1.0.9) - HTMLタグ更新
- Redux (4.1.0) - 状態管理
- React Redux (7.2.4) - 状態管理 (Reactバインディング)
- Redux Toolkit (1.5.1) - 状態管理 (Redux簡便化ツール)
- Marerial-UI (4.11.4) - UIデザインツール
- Axios (0.21.1) - HTTPクライアント
- React Hook Form (7.6.5) - フォーム
- Yup (0.32.9) - スキーマ構築 (バリデーション)
- React DnD (14.0.2) - ドラッグ&ドロップ
- Jest (27.0.4) - テスト
- React Testing Library (27.0.4) - UIテスト
- Mock Service Worker (0.28.2) - APIモック
- markdown-to-jsx (7.1.3) - Markdown
使用技術 (バックエンド)
- PHP (8.0.5) - 開発言語
- Laravel (8.32.1) - Webアプリケーションフレームワーク
- MySQL (8.0.23) - RDB (開発環境)
- Redis (6.0.10) - キャッシュ、セッションストア (開発環境)
- MailHog - メール送受信 (開発環境)
- PHPUnit (9.5.2) - テスト
- Telescope (4.4.6) - デバッガー
- Sanctum (2.9.3) - SPA認証 (セッション、CSRF & XSS 防衛)
- Fortify (1.7.8) - 認証用バックエンド (ルーティング、コントローラー etc)
- Bref (1.2.10) - PHP用Lambdaデプロイツール
- Serverless (2.53.1) - サーバレスアプリケーション構成管理
- AWS SDK for PHP (3.188.0) - AWS連携
使用技術 (その他)
- Docker - コンテナ管理
- GitHub Actions - CI/CD
画面
ホーム
ログイン
入力時バリデーション | 送信時バリデーション |
---|---|
ユーザー登録
入力時バリデーション | 送信時バリデーション |
---|---|
マイページ
メールアドレス認証
認証確認通知
認証用メール
未認証警告+再送信ボタン (マイページ)
パスワードリセット
再設定リクエスト
入力時バリデーション | 送信時バリデーション |
---|---|
再設定用メール
ボードCRUD
リストCRUD
カードCRUD
絞り込み
並び替え
検索
所感
Reactは以前に学習したことがありましたが、フロントエンドの実装には苦労しました。特にデザインやレイアウトについては、他のサイトを参考にしても思い通りのものにならず多くの時間を費やしています。それでもまだ上手くいかないことも多々ありますが、その過程でHTMLやCSSについて未知の部分も学ぶことができたのは良かったと考えています。
バックエンド側については、Laravelやその関連パッケージが様々なテンプレートを用意しているので、それに沿った利用ができれば記述するコードとしては少なくなります。一方で何かカスタマイズをすることになったときには、コードやドキュメントを読んで理解する必要があり、その部分にやや苦心しました。特に、フロントエンド側のTypeScriptを利用したパッケージと異なり、補完機能が利用できずまたコードへのジャンプができないこともあり、フロントエンドと比較してコードの記述量としては少ない代わりに何度もコードやドキュメントを読むことになりました。
インフラの構築について、AWSには何度か触れたことがある程度でネットワーク設定やアクセス権限などは少々把握していましたが、Lambdaを利用したデプロイは初めてで、手が止まることもしばしばありました。LambdaはEC2やFargateなどと比較して管理の手間が省ける一方、中身の処理が見えず現状の把握が困難です。これに対してはCloudWatchのログを確認しながら試行錯誤の連続でした。それでも今までサーバレスアプリケーションの構築を試したいと考えていたので今回の試みは良い機会だったように思います。
ただ、インフラ構成にはAWS マネジメントコンソールを利用することも多かったので、インフラ構成の把握や再利用には課題があります。これをコード化することで利便性を高めていくことが直近の目標です。
アプリケーションを実装しつつ学びを深めようとする程に、今まで気付かなかった問題が表面化し、中々思うように進みませんでした。それでもできるようになったことは少しずつ増えており問題解決までの時間も次第に短縮はされているので、これからも勉強を継続し技術の向上を図っていきます。
各種リンク
- アプリケーション:
https://www.miwataru.com/ - GitHub: https://github.com/zuka-e/laravel-react-task-spa
- フロントエンド実装過程: https://qiita.com/zuka-e/items/60afcc09464e10162338
- バックエンド実装過程: https://qiita.com/zuka-e/items/3faf100cbcdf7ec40ee6