初めて自分でモノを作った [Node.js MongoDB AWS Terrafrom GitHubActions]

## 背景
・新卒SIerで3年半ほどインフラエンジニアとして働いていました
・インフラだけでなくアプリ側も経験したく、アプリ側の勉強のアウトプットとして今回のアプリを作りました
・「Reactまで導入しよう」「UI/UXももっと快適にしたい」「こんな機能もいいな」などありますが、初めに考えていた構想が実装できたので一つの区切りとしました


## どういうアプリ
好きな漫画の言葉を閲覧投稿するアプリです。
漫画のタイトルごとでグルーピングされ他の人が投稿した言葉を見たり、ユーザ登録すれば「スキ！」してお気に入りとして自分がスキ！した投稿を見ることができたりします。
投稿された言葉にはスキ！された数が⭐️のカウント数で見ることができます。

「漫画 名言」等検索したときに漫画ごとでグルーピングされてるモノがなかったのと、既に作成側で上げた言葉が紹介されていて自分で上げられるモノがなかったので作ろうと思いました。

アプリ名：**ふぁぼワード**

アプリURL
※停止しました

GitHubリポジトリ
https://github.com/hiroXXI/hiro-app


### 機能
・言葉(画像)の投稿・編集・削除
・スキ！(お気に入り)機能
・検索機能
・ソート機能
・ページネーション機能

・ユーザ登録
・ログインログアウト
・アカウント削除

### イメージ
#### 投稿機能
漫画タイトル、人物、巻数、言葉、画像を入れて投稿。
![投稿.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/a7b0607c-a75d-90aa-3308-979b36099e77.gif)

#### スキ！機能
その場で「スキ！/スキ済」が切り替わり合わせて⭐️のカウントも変わる。マイページの設定画面からスキ！した投稿を見ることができる。
![スキ！.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/3c206e4f-5cc6-ba3d-34f9-8d290325136f.gif)

#### 検索機能
入力した文字を含む漫画で絞り込む。
![検索.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/a0021dd7-ccc5-a9c6-a149-8364a4b37c56.gif)

#### ソート機能
スキ！数順、新着順、古い順で投稿された言葉を並び替える。
![ソート.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/0ee85b79-c20e-cc62-8558-abf8a5adf98b.gif)

#### ホーム画面
投稿された最新の5件が表示される。
![ホーム.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/8adadcf3-e551-252f-78b8-6d2494922188.gif)


## 期間
・2023年12月〜2024年1月: Udemyの講座でアプリ側の勉強
・2024年2月〜3月: アプリ作成


## 技術スタック
#### フロントエンド
JavaScript(EJS)

#### バックエンド
Node.js(Express)
MongoDB(Mongoose)

#### インフラ
AWS(ECS ECR DocumentDB ElastiCache ALB S3 パラメータストア Route53 ACM CloudWach)
Terraform
GitHubActions


## 構成図
![構成図.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/e8cca754-f838-ab5c-9373-236be60a4c0a.png)

### ER図
![ER図.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683048/bb533235-2462-ce5f-4bc3-cf993e41ad25.png)


## 技術の選定理由
#### 言語まわり
・漠然とNode.jsに興味があったのでバックエンドはNode.jsにしました
・調べるとReactなどを使ったSPA型のアプリが今は主流だと感じましたが流れ的にはMPA->SPAと来ているようだったのでまずはMPA型で作ることにしました
・同じような理由で静的型付けのTypeScriptではなく動的型付けのJavaScriptで作ることにしました
・フレームワークは取り組んだUdemyの講座がExpressだったのと調べてみてメジャーだったのでExpressにしました

#### DBまわり
・RDBMSも考えましたが取り組んだUdemyの講座がMongoDBだったのとExpressとの組み合わせによく使われてそうだったのでMongoDBにしました
・ORM/ODMについても同じような理由でMongooseを使うことにしました

#### インフラまわり
・AWSは前職で使っていたので使用しました
・MongoDB互換のDocumentDB、セッションの保存先にElastiCache、画像の保存先にS3、環境変数の保管先にパラメータストア、等々を利用しました
・前職ではマネコンでポチポチがメインだったのでIaCを使ってみたく、よく使われてそうだったTerraFormを使うことにしました
・前職ではGitHubを使ったことがなかったのでGitHubを利用し始めるのと一緒に、付いているGitHubActionsを使うことにしました


## 意識したこと
#### バリデーション
作成者以外の何も知らないユーザが使っていくアプリなので、フロント側/サーバサイド側で必須チェックや形式チェック、トリムなどをかけて変なデータで入るのを防ぐようにしました。

#### 認可
投稿した言葉の編集・削除などそのユーザ本人しかできてはいけない機能があるので、ログインしてるのかやその言葉を投稿したユーザ本人なのかを確認して、そういった適切な状態・権限がないとアクションできないようにしました。

#### UI/UXとAI活用
フロントのデザインにあまり時間の比重を置きたくなかったのでAIを活用しました。
1. ChatGPT等にBootstrapを使ったデザインを伝えコード案を出してもらう
2. 出してもらったコード案で使われている機能をドキュメントで確認する
3. 微調整する

このように進めていきフロントのデザインにかける時間をなるべく減らしてページを作ることができました。


## 苦労したこと
#### 認証まわり
Passportというライブラリを利用しましたが都合よく自分の環境に合う参考記事はなかったので、ドキュメントを見て各コード箇所でどういう処理をしているのか推察して試行錯誤を繰り返して実装することができました。

#### データの受け渡し面
初めて自分でアプリ側の開発をしたのもあって、期待していたデータが送れていなかったり受け取ったデータの形が期待と違かったりなどありましたが、
言語の基本知識を再確認したりドキュメントでどういうデータが扱えるのか、console.log()で中身がどういう形のデータになっているのかを確認しながら解決していきました。


## 終えてみて感じたこと
#### テストの仕方、自動化について
ブラウザ上からやPostmanを使ったり、データベースの記録を確認しながら自分で書いたコードが期待している動作になっているかを進めていきましたが、
その都度手動でやっていくのはアプリが大きくなればなるほど厳しくなるのでそもそもの良いテストの仕方やテストの自動化について身につける必要があると感じました。

#### 分かりやすいファイル構造、コードの書き方について
今は自分だけなので「どういうファイル構造になっているか」「ここのコードはどういう処理をしてるのか」が分かりますが、仕事であればチームで開発していくことになるので自分以上にチームのために分かりやすいファイル構造やコードの書き方について身に付けていかないといけないと感じました。

#### IaCの便利さについて
今までマネコンでポチポチがメインだったのでIaCの便利さを強く感じました。環境を複製する時の楽さは桁違いでした。
IaCで運用していく場合のノウハウも身につけたいです。


## 最後に
今までインフラ側としてやってきましたが、アプリ側の勉強・アウトプットをしていく中で領域外のことを知らずに/気にせずに過ごして来ていたことを実感したのでそれだけでもまずは価値があったと思いました。
目先はアプリ側(バックエンド)目指して転職して、その先でどういう領域で進んでいくかまた考えたいです。