個人開発でカタログ作成アプリを開発した件

## はじめに
私は「[アプレンティス](https://apprentice.jp/lp)」の2期生としてプログラミング学習をしております。

その中で「[CatalogEasy](https://github.com/setodeve/CatalogEasy)」という業務アプリをリリースしました。
開発期間は2ヶ月ほどです。

この記事はなぜこのアプリを作ったのか、何を工夫したかを解説をするといった内容になります。
興味ある技術を使ってみたかったところもあり、規模に対してオーバースペックである点はご了承ください。

## プロダクト概要
商品の画像付きのカタログを作りたいけどPC操作が苦手な両親へ向けたカタログ作成アプリです。
商品データと商品画像を登録することで簡単にカタログ作成ができます。
![top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365570/db127462-6ee0-ae01-ed43-74a7bd0d22aa.png)

### Github URL
https://github.com/setodeve/CatalogEasy

## 要件定義
まず何を作りたいかというところで、両親が営業している会社の業務を支援するアプリが作れないかと考えました。
何か困っていることがないかと確認したところ、
お客様に渡せる商品画像と、商品情報がまとまったリスト(以降 カタログ)を作りたいという要望がありました。

カタログのイメージは以下のような形です。商品画像と商品情報(値段やサイズ)が一覧になっている。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365570/cd711bf5-1212-e653-b632-7b08e10e46b5.png" width="30%">

ただし、そこには以下のような課題が見えてきました。
### 課題1:難しそうなツールを使うのはできない
カタログを作るとなれば、この世には多くのツールが存在します。有名どころだとWordやCanvas。
ただ、それらのツールを駆使するのはハードルが高いとのことでした。
特に、フォントや図形のサイズを自由にいじれることが逆に使うのを難しくしているようでした。

### 課題2:商品情報を一つずつ登録するのはあんまりやりたくない
カタログには商品情報を一つずつ入力する必要があります。
ただ、商品情報のマスターデータはすでに会社に存在しているため、それを活用する方法を探る必要がありました。

### 課題3:商品情報と画像が紐づいていない
現在、商品情報とそれに対応する画像が適切にリンクされていません。
この非効率性を解消するために、両者がスムーズに紐付けられる仕組みが必要でした。

上記の課題を解決するために以下の機能を盛り込もうと考えました。
- 機能はできるだけシンプルにする
- 商品のマスターデータはCSV形式で取得可能なため、CSVを読み込むことで商品情報が入力できるようにする
- 画像はドラッグ&ドロップで直感的に設置できるようにする

## ワイヤーフレーム
今回は、画像と商品が紐付けられ、カタログが作成可能という部分に焦点をあてており、ページ構成は非常にシンプルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365570/a213cc61-15c6-c7ce-9554-eead18e0f7a7.png)

## 使用技術
### フロントエンド
  - TypeScript
  - Next.js
#### 主要ライブラリ
  - Yamada UI
    - シンプルなUIを実現できるため
  - React Hook Form
    - 動的なフォームのバリデーションとフォームの状態管理を簡単に実装できるため
  - React-DnD
    - ドラッグ&ドロップ機能を簡単に実装できるため
  - Axios
    - リクエスト前の前処理が簡単にできるため
  - Prettier、ESLint
    - コード品質担保のため


### バックエンド(Ruby on Rails / Nginx)
#### 主要gem
  - devise_token_auth
    - 小規模アプリで、ユーザー認証が容易であるトークン認証を採用
  - rack-cors
    - APIの呼び出し時のCORS対応のため
  - rubocop
    - コード品質担保のため
    
### インフラ
AWSサービスを使用してインフラ構築をしました。
![arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365570/f2dd3cfe-0c35-1640-a2ff-dc66361045e3.png)

#### 主要AWSサービス
- ECS Fargate
  - Rails APIのデプロイのために使用。Docker開発におけるデプロイ負担の軽減のため
- ECR
  - Rails API、Nginxコンテナイメージ保存のため
- Amplify
  - Next.jsをデプロイするために使用。デプロイの容易さや、Vercelに比べ、AWS内のサービスとの連携が簡単にできるため
- S3
  - 画像アップロードのため。VPCのエンドポイントからアクセスできるように設定
- RDS(Mysql)
  - Rails APIのデータ保存のために使用。(マルチAZ)必要に応じてスケーリングが容易なため
- ALB
  - ECS Fargateへのトラフィック分散を行うため
- Route 53
  - Rails、Next.jsのアプリケーションの独自ドメイン設定のため
- ACM
  - SSL化のため

### その他ツール
- Docker、Docker Compose
- Lefthook: コミット前に自動で静的解析ツールを走らせるため
- Github Action
- Postman

## 機能一覧
### ユーザー利用機能
  - ログイン&ユーザー登録機能
  - 商品情報CSV読み込み機能
  - 商品画像/情報登録機能
  - カタログ作成機能
  - カタログ一覧機能
  - カタログPDF出力機能

### ユーザー非利用機能
  - UI
    - 親切な使用方法の解説
    - 機能を盛り込みすぎないことによる使いやすさ

  - セキュリティ
    - Route 53、ACMを使用した独自ドメイン、SSL化対応
    - トークンを利用した認証
    - プラウザ側でのURLの暗号化
    - XSS、CSRF対策

  - 開発
    - 静的解析ツールを用いたコード品質担保
    - GitHub Actionsによる自動デプロイ
    - Amplifyによる自動デプロイ
    - Dockerを用いたデプロイ効率化
    - UIコンポーネント(Yamada UI)を用いた開発の簡略化
    - Lefthookを用いたコミット前の静的解析ツール実行


## 苦労したところ
 ### A4サイズのページに商品情報を並べられるようにする
 商品情報を並べられるようにするため、配列情報の扱いに一手間加える必要がありました。
 
https://qiita.com/keiswe/items/13c3389b53525d6d5430
 
 ### S3から画像取得ができなかった
開発環境と本番環境で設定すべき値がわかっていなかったことで予期せぬエラーに遭いました。

 https://qiita.com/keiswe/items/78477e04422206a33e97

### URL上のIDを暗号化
セキュリティ向上のため平文のIDをURLに載せないように気をつけました。

 https://qiita.com/keiswe/items/3d7c9ef1b956a43ebd41
 
## 反省点
 ### 適切にSSRを使用すべきだった
 時間の限りがあり、開発のしやすさからCSRで開発を進めてしまった部分があります。
 今後のアップデートで適切にレンダリングするようにしていきたいです。

## 今後のアップデート
 * SSR化
 * デプロイ先の変更
     * 両親のみの使用を想定しているため、バックエンドをより安価な場所に移行予定
 * カタログ編集機能
 * テンプレート機能
 * 過去登録した商品情報からカタログ作成機能
 * カタログ名編集機能
 
## 最後に
2ヶ月くらいの個人開発を通して様々な技術的に挑戦ができたと同時に、反省すべき点も見えてきました。
引き続き技術の習得に取り組んでいきたいです。