【個人開発】消費カロリーを食べ物の個数に換算するアプリを開発しました🔥【React・Rails・Docker・Firebase Auth・AWS・Tailwind CSS・GitHub Actions】

# はじめに
はじめまして！ 
[ほーど](https://x.com/maaasaaayk)と申します。
この度、ダイエット支援アプリ「[なんこメシ](https://www.nankomeshi.com)」をリリースしました。
このアプリがダイエットをしている方々のお力添えになれることを願っております。
ぜひ、息抜きがてら気軽に触っていただけると嬉しいです！
### サービスURL
https://www.nankomeshi.com
### GitHub URL
https://github.com/masa5281/nanko-meshi
# 開発背景
ダイエットをしている方なら、一度はアプリ等で消費カロリーを確認したことがあるのではないでしょうか？
そこで疑問に思ったことはありませんか？

**「消費カロリーは分かったけど、いまいちピンとこない...」**
私自身こういう気持ちを抱えつつジョギングをしておりました。
カップ麺やお菓子のカロリー表記は目にするけどそこまで意識したことがない。
運動したからと、ついつい間食に手を伸ばす...

せっかく消費カロリーが分かるのだから普段の食事と照らし合わせ、
**「個数で直感的に可視化すれば、数値よりも分かりやすいのではないか」**
と考え開発に至りました。
# メイン機能（カロリー換算の流れ）
### 1. 自分がよく食べる食品を登録
![food-register.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/3633a2b7-eb6f-425f-8313-3d82be1b29fd.gif)
### 2-1. 運動で消費したカロリーと日付を入力（カロリー手動）
![food-conversion.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/e6ff33f6-8cb5-4845-a18f-42939f891a9d.gif)
### 2-2. 運動項目・運動時間・日付を入力（Metsによるカロリー推定値）
![food-conversion.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/368c2cb0-e6a0-4626-a91c-2ffb2cef9ae7.gif)
# サブ機能
|グラフ機能（月・週）|お気に入り機能|
|---|---|
|![graph.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/2d907aeb-9127-469d-b32b-f16bffc3c175.gif)|![favorite.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/1756bd12-99eb-41f3-afb3-b1219e15c4ff.gif)|
|週グラフは換算結果ボタンから再度カロリー換算ができます。|他のユーザーが登録した食品をお気に入り登録すると、換算の対象にできます。|
# 使用技術
|カテゴリー|使用技術|
|---|---|
|フロントエンド|React 18.3.1<br/>Tailwind CSS 3.4.17|
|バックエンド|Ruby 3.4.1<br/>Ruby on Rails 7.2.2.1（APIモード）|
|インフラ|AWS / Nginx|
|DB|PostgreSQL|
|認証|Firebase Authentication|
|環境構築|Docker|
|CI/CD|GitHub Actions|
|その他（フロントエンド）|ESLint / axios / recharts / motion / flowbite-react|
|その他（バックエンド）|RuboCop / CarrierWave / jwt / active_model_serializers|
# 技術の選定理由
### バックエンド：Ruby on Rails（APIモード）
学習期間中はフルスタックのRailsに取り組んでいたため、フロントエンドを分離した新しい開発スタイルに挑戦しました。
### フロントエンド：React （比較対象：Vue）
学習時に簡易アプリを作成した際、Turboを用いた部分的な非同期処理を実装した経験から、よりステップアップしたSPAを実装してみたいと考えたため。
Vueと違い学習コストは上がりますが、より深くJSの知見を磨けるReactを採用しました。
※個人的な理由ではアイコンのカッコよさが刺さりました。
### 環境構築：Docker
環境構築が容易になり、実務でも汎用的に用いられているため。
### インフラ：AWS （比較対象：Render）
- Renderと比べて簡易さは劣るが、インフラ周りの概念がしっかり学べる
- 企業のインフラで圧倒的なシェア率があり、実務でも応用が効く
### 認証：Firebase Authentication
- 機密情報の堅牢化
- ログインの簡易化

DB上でユーザー情報を管理するより、Googleセキュリティに一任する方がより情報漏洩のリスクを低減できる。
単独導入でソーシャルログインを実現できるため。
### CI / CDツール：GitHub Actions （比較対象：CircleCI）
GitHubリポジトリとの親和性が高く、ソースコードからデプロイパイプラインまで一元管理できるため採用しました。
# インフラ図（draw.io）
![インフラ図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/4738ab04-51c5-4009-9565-e55abb63dffc.jpeg)
AWS公式アイコンセットが豊富なdraw.ioで作成しました。
当初は可用性を考慮しマルチAZ構成でしたが、コストの関係でシングルAZ構成に変更しました。
# ER図（dbdiagram.io）
![ER図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/8a7d98e8-0e07-4a72-ab01-725331561a5b.png)
テーブル定義やリレーションをコードで記述でき、リアルタイムでER図が生成される利便性から採用しました。
# UIフレームワーク（Figma）
![UIフレームワーク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964455/566fbd5f-d4ff-4402-9854-caff83b0d839.png)
個人利用では無料でも十分な機能があり、クラウドベースで手軽な操作が可能なFigmaを使用しました。
# こだわり
### ①UI / UX
- **シンプルで温かみのあるUI**
ダイエットがテーマのため、全体的に温かみのある色合いで統一しました。
また、アイコン配置やグラフのタブ切り替えなどシンプルなUIで分かりやすさを重視しました。<br><br>
- **操作の把握**
画像アップロード時にローディングを表示して処理中であることを明確にしたり、
データ更新・削除後にはポップアップで処理完了の通知を表示しました。
モーダルウィンドウも適宜入れることで単調な画面とならないようにしています。<br><br>
- **レスポンシブ対応（PC・タブレット・スマホ）**
マルチデバイスで利用できるようにしました。
特に個数換算結果の画面は情報量の関係上レイアウト崩れが顕著に出たため、
スマホ画面でも違和感のないように調整しております。
### ②カロリーの入力方式（手動・Mets）
消費カロリーを計測しない方でも利用できるよう、手動入力とMetsによる自動算出の2通りの方式を採用しました。
運動項目も筋トレやストレッチの他、ジョギングやランニングも細かく分け、幅広いユーザーの状況にも対応できるようにしています。
### ③X（旧Twitter）シェア機能
換算結果をすぐにX上にてシェアできるボタンを配置しております。
「今日は運動をして〇〇（食品名） 〇個分のカロリーを消費！」というように食品名と個数に応じて変化するので、ユーザーが楽しみながら運動の成果をシェアできるようにしました。
# 苦労した点
- **RailsとFirebase Authとの連携**
トークンベースのJWTの検証とRailsAPIとの認証チェックが発生して、
DB上のUIDと紐づける処理が大変でした。
Firebase特有のエラー処理や、axiosで認証ヘッダー設定といったフロントとバックエンドを横断する力を求められて多くのエラーと向き合いました。
ただ、実装後のログインの手軽さとユーザー管理のしやすさで疲労が飛んでいきました。<br><br>
- **グラフでの日付オブジェクトの処理**
JSでの日曜情報は日曜が0から開始ですが、UIとしては月曜を起点としたかったため、整合性を意識してコードを記述することが難しかったです。
日付系はday.jsなどのライブラリがありますが、日付オブジェクトの理解を深める目的があったため、あえて使用しませんでした。
# 今後の展望
- **テスト**
今回はデプロイ時点でテストコードが未実装のため、
RSpecやJestなどを用いて実装してプロジェクトの品質向上を図っていきたい。<br><br>
- **運動項目の見直しや目標ゲージの追加**
運動項目がジョギングなど走る有酸素運動に特化してしまったので、
より多くの方が使用できるように項目の見直しをしていきたい。
月や週ごとの目標消費カロリーを決めて、プログレスバーで表示をしたい。<br><br>
- **ユーザー間のインタラクション**
お気に入り機能は実装したものの、他ユーザーとの交流やお気に入りされた数が把握できるなど、よりアプリを継続的に使用したくなるための工夫を施していきたい。
# おわりに
実はこれまでに2度プログラミングスクールで挫折しており、今回が3度目の挑戦でした。諦めきれない気持ちから退職後に独学を始め、約4ヶ月ほどでポートフォリオを完成いたしました。
学習中やポートフォリオ制作中には何度も挫けそうになったり、自堕落になり数日手つかずとなることも多々ありました。
そんな中でもMENTAやX（旧Twitter）でコードレビューやアイデアの相談に乗っていただいた方々には、本当に感謝の気持ちでいっぱいです。
この経験を活かし、今後も学習を続けていこうと思います！

以上です！
ご覧いただきありがとうございました。