はじめに
今回はAWSを一から学んで、Webアプリを作成してみました。
Laravelのアプリはローカルでしかアプリ開発をしたことがなく、デプロイ自体も初めてだったのでかなり苦労しました。
この記事ではアプリ開発の使用技術、設計や概要を説明していこうと思います。
アプリの概要
配達員が置き配許可をしている顧客を管理できるアプリです。
※現在はテスト環境は稼働しておりません。
ポートフォリオURL(https://test.sawascle.com/)※こちらはテスト環境のURLです。以下のユーザー情報でログインしてください。中身はダミーデータです。
メールアドレス
test@example.com
パスワード
password
ソースコードURL(https://github.com/akira9889/okitama)
特徴
検索機能
検索したらすぐに置き配かどうかわかるようにしております。また検索に該当する人数が複数の場合はテーブル表示、一人の場合は詳細が表示される仕組みになっております。
置き配履歴の登録と表示
顧客を検索し詳細ページが表示されたらそのまま置き配の写真が登録できるようなUI/UXにしております。登録する際に時間がかかっているためバックグラウンドで処理するように改善しようと思います。
顧客登録
ドライバーは入力する時間が惜しいほど忙しいので、その時間を短縮するために自動フリガナの実装とキーボドの右下の青いボタンを押すと次のフォームに移動、または閉じるようにしました。
メイン機能
- 顧客情報の作成・表示・編集・削除(CRUD処理)
- 顧客に紐づく置き配履歴の作成、表示(置き配した写真と日時、管理者権限がない場合は自分の履歴データのみ表示)
- 配達員同士で顧客の置き配情報を共有できる
- 顧客検索
- 配達エリアの作成・表示・削除
- 管理者機能(新規ユーザーの承認、削除、全てのドライバーの置き配履歴を閲覧できる権限)
認証機能
- ユーザー登録・ログイン・ログアウト
- パスワード再設定
使用技術
フロントエンド
- Vue.js 3.3.4(Composition API)
- Sass
- TailwindCSS
バックエンド
- Laravel 10.10
インフラ
- Mysql 8.0.33
- AWS(ECS on Fargate, S3, RDS, Route53, Certificate Manager, ELB, SES, Code シリーズ, Step Functions)
- Docker
- CopilotCLI
外部API
- 都道府県内市区町村一覧取得API(都道府県を選択した際に市区町村を取得するのに使用)
- gooラボ ひらがな化API(氏名の自動フリガナをする際に使用)
その他の使用技術
Git(GitHub) / Visual Studio Code /
Adobe XD(画面遷移図) / plantUML(ER図) / Drawio(AWS構成図)
なぜこの技術を選定したか
- PHP(Laravel):バックエンドエンジニアとして就職したく、MVCフレームワークに触れておきたかったからです。LaravelとRuby on Railsの候補がありましたが、もともとPHPでフルスクラッチ開発していたので理解しやすく、Ruby on Railsに比べて情報量の多いLaravelを選定しました。
- Vue:1つのページで種類の違うDOMを表示したかったので、実装しやすいVueかReactで悩みましたが、LaravelとVueは連携しやすいのと、Reactに比べて学習コストが低いと思ったのでVueを選定しました。
- AWS:バックエンドエンジニアを目指しているので、インフラ周りの知識も理解した方がいいと思いました。またコンテナオーケストレーションツールを使えば、Dockerの強みである開発環境と本番環境での差異が発生しないので、AWSのECSを使いたくて選定しました。
設計
インフラ、DBの設計図を解説していきます。
インフラ設計
- Webサーバー × 2、DBサーバー × 1、ファイルサーバー × 1 構成
- サーバーはECS on Fargate、RDS、S3を使用
- AWS codeシリーズ(Code Build, Code Deploy, Code Pipeline)を使ってCI • CDを導入
DB設計
テーブル数は9個で少ない方ですが、リレーションの関係を確認する際にER図があると確認しやすかったです。また途中から変更点などがある際も全体の関係が見れるのでよかったです。
ER図
各テーブルについて
テーブル名 | 説明 |
users | ドライバーの情報 |
customers | 顧客情報 |
prefectures | 47都道府県 |
cities | 登録した市区町村 |
towns | 登録した町域 |
dropoffs | 置き配場所の種類の情報 |
delivery_area | ユーザの担当する町域の情報 |
customer_dropoff | 顧客の置き配場所の情報 |
dropoff_histories | ユーザが顧客の荷物を置き配した履歴の情報(日時、写真) |
このアプリを作成した背景と目的
なぜ顧客管理アプリなのか?
作成した目的は?
上記2点について述べていきたいと思います。
なぜこの顧客管理アプリなのか?
私は元々配達員でした。コロナ禍もあったため、よくお客様から「荷物は玄関前に置いといて」という依頼が多々ありました。
しかし1日に数百人の荷物を運んでいるため、正直どのお客様が置き配していいのか覚えきれていませんでした。
そこで他の配達員は携帯のメモアプリや紙媒体で管理している人多かったですが、結局、何百人というお客様を箇条書きしていたので、特定のお客様を探すのに時間がかかったり、見落としたりしていました。
そのため、配達時間が伸びてしまったり、置き配できる顧客だったのに置き配しなかったりすることがある現状でした。
また1つのエリアを複数の配達員で回るのですが、配達員同士で置き配できる顧客の共有がうまくできていないため、電話で「このお客様は置き配OKですか?」という確認する手間が増えたり、そもそも共有すらできていませんでした。
そこでアプリで配達員同士がデータを共有できて、顧客の置き配情報を素早く確認できないかと考え、このアプリを作成いたしました。
このアプリを作った目的
私がWebエンジニアとして就職するために、自走力を鍛えるとともに、適正があるのか、実際に自分で課題解決をして、実際に使われるアプリを運用する必要があると思いました。
また企業様に採用していただく際に、自分の技術や熱意を証明するためにこのアプリを作ろうと思いました。
ポートフォリオ作成から完成までの振り返り
作成するにあたって意識したこと、苦労したことを述べていきます。
作成するにあたって意識したこと
下記5点の意識したことについて述べていきます。
- タスクばらしをしてから実装
- 最初から複雑な機能を実装しない
- エラー文をコピペしてすぐ調べるのではなく、きちんと理解して仮説をたててデバッグしてみる
- 実務を想定
- ページ表示速度が早くなるように工夫
タスクばらしをしてから実装
まず実装するのに大まかなタスク単位でばらしてから流れを理解して、当日にさらに細分化してタスクをこなしていくという方法で実装しました。タスクはGithubのissueにタスクをまとめて、下記のようにプロジェクトで管理しました。
最初から複雑な機能を実装しない
最初から複雑な機能を実装しようとせず、ページの表示だけや、データの取得だけなどのシンプルな機能を実装した後に、複雑な機能を追加する流れだとスムーズに実装できました。
エラー文をきちんと理解して仮説を立ててからデバッグしてみる
エラー文をコピペしてすぐ調べるのではなく、エラー文の意味を理解して、自分で仮説して検証するほうが実装力が鍛えられ、デバッグの仕方も上達すると思いました。
実務を想定
個人開発でしたがGitを使用する際はGithub Flowに則って、ブランチを切る→開発→プルリクエスト→レビュー→マージという流れで実装しました。また実務ではレビューをしたり、コンフリクトすることもあるので、GitHubのアカウントを2つ作り、レビューの流れを掴んだり、コンフリクトの解消をしたりしました。
また最初からローカルで開発し終えてからデプロイするとローカルと本番環境での違いでエラーが起きる可能性もあるので、最初にインフラを構築してから機能追加したらすぐ本番環境に反映という流れで開発しました。
あとはなるべく公式ドキュメントを読むようにしました。記事の内容もわかりやすいですが最新の情報ではなかったりするので、最初は慣れませんでしたが、どこに情報が載っているかがなんとなく分かるようになりました。
ページ表示速度が早くなるように工夫
フロント
複数の非同期処理を実行しているのならば、Promise.all
を使うなど。以下の記事を参考にしました。
https://qiita.com/nuko-suke/items/50ba4e35289e98d95753
バックエンド
- テーブルにインデックスを貼る
今回の場合は顧客の検索機能が一番速度が求められるので、customersテーブルに複合インデックスを貼りました。またsqlのexplainを使って実際にインデックスが使われているか、速度が速くなっているのを確認できました。 - N+1問題を避けるためにリレーションの情報を取得するときはwithメソッドなどを用いてEagerロードを使用
- sqlの発行回数が少なくなるようにバルクインサート、WhereInメソッドを使用
- OPcacheの導入
苦労したこと
インフラ
今回初めてLaravelのアプリをECSを使ってデプロイしたのですが、初期画面を表示するだけでもかなり苦労しました。ローカルと本番でnginx.confの設定が違うの全然気づけなかったり、環境変数がうまく設定できていなかったり、ssl化したらファイルが読み込まれなかったり、分からないことだらけでしたね。。。笑
LaravelをECSでデプロイする記事や動画も全然なく、あったとしてもインフラ設計(DockerやAWS)が違くてあまり参考にならなかったので、とても苦労しました。自力で表示できた時は嬉しさと同時に涙がでましたね。
フロント
このアプリはモバイルで動かす前提で作っていたのでios特有の挙動でデザインが崩れたり、UI/UXを調整するのに苦労しました。
バックエンド
コードを打っている途中で、DBの設計の変更が多々ありました。そのためDB変更に伴うコードの修正するのが大変でした。(そもそも設計が甘かったためこうなってしまったので、本当に大事だなと痛感しました。)
フィードバックと今後の課題
今後の課題について述べていきます。
フィードバック
ストレスがなく時間が短縮できた
- 顧客を探さずに検索ですぐに表示できるので注意深く探すストレスがなくなったのと、時間も短縮できた。
- 他のドライバーが追加した置き配できる顧客を共有できるので、ドライバーとの無駄なやりとりの時間もなくなった。
置き配写真登録にかかる時間の短縮
- 写真登録が完了するまで少し時間がかかっているので、今後バックグランドで処理するように改善します。
上記のフィードバックのように自分の手で課題解決できたのはとても嬉しく思いました。
今後の課題
テストコード
完成を優先したためテストコードを一部しか実装していないのと、どのようなテストコードを書けばいいかわからなかったのでこれから学んで実装していきたい。
コードのリファクタリング
なるべく重複するコードはまとめたり、変数名などは分かりやすくしましたが、まだ改善の余地はあるかもしれません。リーダブルコードを読んでメンテナンスしやすいコードにしたい。
質問力
実務では先輩や自分のためにも、どういう質問の仕方が良いのか知る必要があると思います。しかし、周りに先輩エンジニアの方に教えてもらえる環境ではなかったので、MENTAを利用しました。
質問の仕方については「新人エンジニアのための質問の仕方」の記事を参考にしながら実践しました。
チーム開発経験
ポートフォリオは個人開発でしたが、実務ではチームを組んで開発すると思います。
チーム開発の経験の流れも掴みたかったので、EXE(オリジナルサービスの開発メンバーの募集や参加ができるサービス)を利用し、そこではバックエンドとして参画いたしました。
チーム開発でGitも使用し、「ブランチを切る→開発→プルリク→レビュー→マージ」という流れで開発し、Gitの使い方がより深く理解できました。
メッセージのやり取りはSlack、タスク管理はGitのプロジェクトで管理し、実務を想定した開発経験ができました。
まだまだチーム開発経験が少ないものの、おおよそのチームでのコミュニケーションや開発の流れはサービスを通して掴めたかなと思います。