【個人開発】実務経験約6ヶ月の僕が実務で使ってない技術だらけでWebアプリを0から開発してみた話

#0.はじめに
<font color='blue'>***実務経験だいたい6ヶ月の僕がスキルアップのために現時点では実務で使っていない技術を使ってWebアプリを0から開発してみた話。***</font>

<font color="red">**未経験からエンジニア転職を目指す方々のWebアプリ（いわゆるポートフォリオ）作成**</font>にも結構参考になることはあると思いますのでぜひ。

作成したのは**面接情報共有アプリ**です。


#1.使用技術

- **フロント：HTML／MDBootstrap4／<font color="red">Vue.js（2.6.11）</font>**
- **バックエンド：<font color="red">Laravel（6.8）**</font>
- **DB：開発環境はDockerのMySQLコンテナ、本番環境は<font color="red">RDS（MySQL）**</font>
- **開発環境：Docker（LEMP環境）**
- **インフラ：<font color="red">AWS（EC2／S3／Route53／ELB／RDS）**</font>
- **CI/CD：<font color="red">CircleCI**</font>
- **ソース管理：Git／GitHub**

<font color="red">**赤太字が2020/9/19時点で実務で使ってない技術**</font>


#2.簡単に自己紹介

- 関西のWeb系企業でPHPを使ったWebアプリ開発を行う新米パパ
- 2019年10月からプログラミング学習を開始→2020年4月からエンジニアのキャリアスタート
- 好きな食べ物は**ホットケーキ**


#3.開発背景
面接情報共有アプリを開発した理由は大きく分けて**2**つ。

- **Laravel、Docker、AWS、CircleCIの勉強のため（アウトプットしながらが効率的）**
- **エンジニアへの転職活動中の方の面接の内容（特に質問）がTwitterで伸びやすいく、需要のある情報だと思ったため**
- ~~**1つのサービスの開発、運用を経験してみたかったら（特に運用）**~~<br>
**↑開発前はリリース→機能追加→リリースをしてサービスをグロースできたらいいなと思っていました、他にやりたいこと・やるべきことがたくさんあり、今はそこまで考えてない**

#4.（ひとまず）完成したWebアプリをご紹介
**トップページ↓**
![スクリーンショット 2020-09-13 23.59.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/37321c12-a811-e4a2-3ffb-8b135c33ae53.png)

**URL↓**
~~https://mensetsu-app.work/~~
https://mensetsu-app.herokuapp.com/

<font color="red">※AWSのEC2にデプロイしておりましたが、コスト面の考慮＆Herokuを触ったことがなかったので**Herokuにデプロイ**し直しました。
（AWSのサービスついてはS3以外は消してます）</font>

**GitHub↓**
https://github.com/shimotaroo/laravel-app

`README.md`はこちらの記事を見ながら書きました。
[【GitHub】シンプルなREADME.mdの書き方 -コピペで使えるテンプレート付き-](https://cpp-learning.com/readme/)

トップページに画像だったりとアプリの説明をいれるケースもありますが、Twitter、note、Instagramをイメージしてこんな感じのトップページのUIアプリの説明とか画像が入ってない）にしました。

自分がテスト投稿したデータが本番環境に残ってますが悪しからずww

#5.完成までにかかった日数
![スクリーンショット 2020-09-14 0.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/27740df0-54ce-12d5-3325-82ff7a86c870.png)

毎日このアプリ開発に時間を費やしていたわけではないので明確にわかりませんが草は上の画像の感じです。
（育児と本業、その他諸々の傍らコツコツやってました）

まあフルコミットすれば**1ヶ月くらい**でできたのかな、って感じです。（多分）

#6.実装した機能

- **CRUD機能**
- **ユーザー登録**
- **ログイン／ログアウト**
- **Googleアカウントでユーザー登録／ログイン**
- **Twitterアカウントでユーザー登録／ログイン**
- **プロフィール編集**
- **パスワード変更（現在のパスワードをチェックする仕様）**
- **プロフィール画像のデフォルト設定／変更**
- **いいね（お気に入り）**
- **ページネーション**
- **並び替え＋ページネーション保持**
- **絞り込み検索＋ページネーション保持**
- **N+1問題解消**（機能ではないけど一応）

特別難しい機能はないかと思います。レベルの高い初学者の方ならポートフォリオとして盛り込んでいたりするかもです。
（と言っても僕はいくつかは手こずりました）

#7.その他にやったこと

- **ER図書いてDB設計**
- **開発環境DockerでLEMP環境構築（もちろんLaradockじゃないです）**
- **PHPUnitで単体テスト**
- **AWSにデプロイ**
- **Circle CIで自動テスト／自動デプロイ**

1つ前に書いた機能実装よりこっちの方が未知の分野だったので大変でした。そして頑張った。
（上手くいかず何度PCをぶん投げようと思ったか...）

#8.DB設計
DB設計というかER図作成は**Draw.io**というツールを使いました。
VSCode用のプラグインがありエディター上ででER図を作成できるスグレもの。

作成したER図はこちら↓
![スクリーンショット 2020-09-14 0.49.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/ce722d39-5202-e96f-f6a8-29225b597e6f.png)

作成したテーブルはこちら↓

|テーブル名|説明|
|:--|:--|
|users|登録ユーザーの管理|
|articles|投稿された面接情報の管理|
|prefectures|articlesに紐づける都道府県|
|company_types|articlesに紐づける企業の事業形態|
|phases|articlesに紐づける選考フェーズ|
|likes|いいねの管理|

ポイントとしてはarticlesテーブルにprefecturesやcompany_types、phaseの情報をベタでINSERTせずにそれぞれのテーブルで値を保持しておき、articlesテーブルではそのidを参照するように外部キー制約を設定しました。（正規化っていうらしい）

詳しいことは上のER図をみていただければわかるかなと思います。

僕はこれまでER図を書いたことがなかったので1から勉強しました。
初めはリレーションあたりが「？」でしたが、めっちゃググって理解できました。ググった中でも特にわかりやすかった記事を下にピックアップします↓

- [VSCodeでDraw.ioが使えるようになったらしい！](https://qiita.com/riku-shiru/items/5ab7c5aecdfea323ec4e)
- [エンティティとリレーションシップ](https://qiita.com/Taku94/items/bb662223ff1f36ec1d68)
- [やさしい図解で学ぶ　ER図　表記法一覧](https://qiita.com/ramuneru/items/32fbf3032b625f71b69d)

#9.ソース管理
ソース管理は皆さんお馴染みの**Git/GitHub**です。

個人開発なので**GitHub Flow**でソース管理しました。（masterとfeatureブランチ）

GitHub Flowがよくわからない人はこちらから↓
[GitHub Flow 図解](https://qiita.com/tbpgr/items/4ff76ef35c4ff0ec8314)

<font color="blue">***※Gitに関して、僕の記事にもまとめていますので特に初学者の方はこちらも併せて読んでいただくとお役に立てると思います↓***</font>

**[Gitでやりたいこと、ここで見つかる](https://qiita.com/shimotaroo/items/b73d896ace10894fd290)**

※僕のQiitaの記事は**約800LGTM**なので結構オススメです（笑）


#10.環境構築
環境構築は**DockerでLEMP環境を構築**しました。

LEMP環境は以下の通りです。

- L：Linux（OS）
- E：Nginx（Webサーバー）
- M：MySQL（DBサーバー）
- P：PHP（アプリケーション）

**Dockerを使ったLaravel+Vue.jsの実行環境の構築方法**については以下にまとめております。今回作成したアプリもこの記事通りに環境構築しました。

- [絶対に失敗しないDockerでLaravel+Vueの実行環境（LEMP環境）を構築する方法〜前編〜](https://qiita.com/shimotaroo/items/29f7878b01ee4b99b951)
- [絶対に失敗しないDockerでLaravel6.8+Vueの実行環境（LEMP環境）を構築する方法〜後編〜](https://qiita.com/shimotaroo/items/679104b7e00dd9f89907)

<font color="Red">**絶対失敗しない**</font>のでDockerでLaravelの実行環境を構築をしたい方はぜひ併せて読んでいただければと思います。

#11.インフラ
インフラは**AWS**を使いました。
僕は**独学期間にAWSはノータッチ＆実務でもまだAWSを使ったことがない**ので、この開発を通して初めて触りました。最初は意味不明ながらもUdemyの動画教材（後ほどご紹介します）を見ながら必死でインフラ構築しました。

構築したインフラはこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/1542ff5e-13a6-e7ba-f9c4-860c9d9d0ab4.png)


上図の通りですが簡単に。

- Webサーバー：EC2
- DB：RDS
- DNS：Route53
- 画像用ストレージ：S3
- ロードバランサー：ALB

せっかくローカルの環境をDockerで構築したので**ECS**を使ってデプロイできればよかったのですが、いかんせんAWSを初めて触ったレベルだったので諦めました...（一応チャレンジはしました）
なお、***"EC2内でDockerコンテナを立ち上げる"***方法も検討しましたが、こちらも全然上手くいかず諦めました...
良い勉強になりましたが、今後は↑このあたりも勉強＆挑戦していきたい。

あと、先ほど掲載したインフラの図を見て、「あれ...」って思われた方がいらっしゃると思うのでここで簡単に<font color="red">**反省点**</font>をあげます（笑）

- **ロードバランサー使っているのにアクセスを振り分けるEC2が1つしかない**
- **てかそもそもEC2もRDSも1つしかなくて全然冗長化できてない**
- **画像を扱うのにCloudFront使ってない**

わかっています。わかってるんです...
お、お金の面を考慮してリーズナブルにしました...（お許しを...）

#12.使った教材
僕がこのWebアプリを作成するために活用した教材をご紹介します。

**Laravel、Vue.js：[【Techpit】Laravel(+Vue.js)でSNS風Webサービスを作ろう！](https://www.techpit.jp/courses/11)**

**PHPUnit、Circle CI、AWS：[【 Techpit】Laravel × CircleCI × AWSで学ぶCI/CD](https://www.techpit.jp/courses/78)**

**AWS：[【Udemy】AWS：ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得](https://www.udemy.com/course/aws-and-infra/)**

**Docker：[【Udemy】米国AI開発者がゼロから教えるDocker講座](https://www.udemy.com/course/aidocker/)**

ここで紹介している教材は本当にわかりやすかったです。もちろん上記プラスで**公式ドキュメント**や**Qiita**を見ながらしました。

当たり前と思いますがLaravelならこちらは必ず見た方が良いですね。
[ReadDouble](https://readouble.com/)

#13.大変だったこと
大変だったこと、苦労したことはやはり**初めて触る技術・実務で使っていない**ですね。
具体的にはこちら↓

- **Laravel**
- **PHPUnit**
- **Circle CI**
- **AWS**

##Laravelで大変だったこと
Laravelに関しては現職に入社する前に基礎は学習していたのでそこまで躓かなかったのですが、

- 並び替え・絞り込み検索時のページネーション保持
- プロフィール画像のデフォルト設定／変更

は結構手こずりました。

画像の取り扱いに関しては

- **開発環境ではローカルに保存**
- **本番環境ではS3に保存**

にするように変更したので、初めからS3に保存していてもよかったですね。

##PHPUnitで大変だったこと

- テストコードの書き方全般
- DBを使ったユニットテスト（単体テスト）

**結合テスト**だったり**統合テスト**は今後勉強していきたいです。

##Circle CIで大変だったこと

- **config.yml（設定ファイル）の書き方全般**

だいぶ苦労しました。4日くらいひたすら自動テストの段階で格闘してましたw
めっちゃググって実際に書いて大まかな書き方は理解できたのでこれは今後別の記事にできたら良いなと。

<font color="red">**※ちなみに、自動テストと自動デプロイが無事に通った瞬間は最高の気分で昇天するかと思いました。**</font>

##AWSで大変だったこと

- **AWSの概念の理解**
- **ALB（ELB）を使ってクライアントとの通信をHTTPS化**

HTTPS化に関しては結局Laravel側にも設定が必要ということに気づいて解決したんですが、ここも結構時間を使いました。

#14.実装したかったけどできなかったこと・まだしていないこと

思いつくだけでもこちらです↓

- 要件定義
- 基本設計
- 詳細設計
- ユーザー登録時のバリデーション強化
- セキュリティ面の確認
- コメント機能
- DM機能
- フォロー機能
- Vue.jsの活用
- ファビコン設定
- Twitterへのシェア機能
- Webサーバー、DBサーバーの冗長化
- ECS(Elastic Container Service）でデプロイ
- Cloud Frontでの画像のキャッシュ配信
- Docker環境の最適化
- 結合テスト／統合テスト

見てもらうとわかると思いますが、できてないこと・してないことはたっぷりです（笑）
少しずつできたらいいなと思います。


#15.開発してみた感想
プライベートでWebアプリを開発したのは転職活動前ぶりでしたが、当時は

- フレームワークなしでネイティブPHPのみ
- ローカルはMAMP
- Xserverに手動デプロイ
- テストコード0

というなかなか笑えない感じだったので、今回色々な技術を使って開発した感想としては

- <font color="red">**アウトプットしながらのインプットがまじで最強**</font>
- **FW超便利**
- **Docker超便利**
- **AWSはむずい**
- **CI/CDパイプラインは構築はむずいけどできたら超便利**
- **公式ドキュメントをちゃんと読むようになった**
- **ググればある程度の問題は解決できた**

とかですかね。

赤字で強調しましたが、**アウトプットありきのインプットはまじで効率がオバケ**です。
どういうことかと言うと、**勉強（インプット）してから「どんな機能を実装しようかな」（アウトプット）**じゃなくて、**まず実装する機能をまず決めて（アウトプット）それに必要な知識を勉強（インプット）する**ということです。

<font color="red">**アウトプット駆動開発**</font>とでも言いいますか。</font>

超オススメです。

（あとは実務未経験でポートフォリオにDocker、Circle CI、AWSを盛り込んでいる方がいますがマジですげえなと思いましたね）

#16.さいごに
かなり長くなってしまいましたが、最後までご覧いただき本当にありがとうございますm(__)m

今後はもっと上流工程（要件定義、基本設計、詳細設計）にチャレンジしたいなと思っています。

初学者の方々も僕と同じくエンジニア1年生の方も<font color="red">**アウトプット駆動開発**</font>でゴリゴリスキルアップしていきましょう(^^)