【個人開発】赤ちゃんが眠りやすい時刻を計算するアプリSleepをリリース

こんにちは、二児の母(小1・1歳)です！
前回の記事で、私が育休中に個人開発をするためにやったことをまとめていますが、この記事ではそのアプリの概要と開発への想いをご紹介させていただきます！

https://qiita.com/akane2726/private/428110ea8825130f1fcb

私は育休中にReact特化型のプログラミングスクール[ShiftB](https://www.instagram.com/shiftb_web/ "ShiftB Instagram")で学び、Next.jsでアプリを開発しました。

https://sleep-iota.vercel.app/

## 個人開発の題材について
私はプログラミングを学ぶためにスクールへ入会し、カリキュラムにポートフォリオ作成があるから題材を考えたパターンではなく、睡眠のアプリ作りたいけど技術力ないからスクールに入ったという流れでした！

第一子で寝ない、泣く、抱っこ時間長すぎ等の過酷が過ぎる育児を経験して、もうこんなの御免だと思ったのですが、赤ちゃんはタイミングよく整った環境で寝かせたらスムーズに寝ると知ったことや、第一子が年中になりだいぶ楽になってきたこともあり寝る子なら産めると思い、絶対に1人でたくさん寝かせると心に決めて5歳半差の第二子を出産しました。

実際に産み育てると、寝かせる方法を知った私の知識の量と質の違いによって育児の大変さに天と地ほどの違いがあり、最初から布団で寝かせることができる→自分の時間が確保できる→我が子かわいいの好循環。
産後うつ、育児ノイローゼとは程遠い、楽しい育児が出来ました。
これは何人産んだとかではなく、単純に知っているか知らないかの違いによる差だと思っています。

「赤ちゃん育児中の全家庭が赤ちゃんを自分で寝かす術を知れば世界が変わるのでは？」
「寝ないから自由な時間がないなんてもったいない！」
「夜泣きなんて親子共にいいこと一つもない！させたくない！」

そんな風に考えました。
もちろん知識があって抱っこで寝かせたい人はそうしたらいいと思いますが、知らないならこんなにもったいないことないです。

置けば寝る赤ちゃんが出来上がると誰でも寝かしつけできるのでほんとーーーに楽です！
預けやすくて母親が楽なのはもちろんですが、代わりに寝かせることになる人も、赤ちゃん自身も楽になるんです。

実際、次回のねんね時刻を通知してくれるようなアプリもありますが、恐らく月齢で一律の活動時間で計算されているもので、月齢のわりに活動時間が短めだった第二子には使えませんでした。
人によって活動時間って全然違うので、個別に対応させたい、運動面の発達が著しい時期は活動時間が短くなるのもありますし、直近の睡眠時間が短いと活動時間が短めになることもわかっているので、そのあたりも反映させたい、、、となり、個人開発の題材は育児しながら決まりました！
これ全部叶えたらめっちゃいいアプリ出来るんやない？とかなり自信がありました！！

## アプリで解決したかった課題
先述の内容と重複する点もありますが、列挙します。

・寝かしつけ開始から入眠までの登録をしたい
→睡眠時間の記録はできても、入眠までの所要時間の計算ができるアプリは知る限りないので、欲しかったです。毎回その他のカスタム項目のようなものを使って「寝かしつけ　活動時間2時間」みたいにメモしていたので、ここは自動化したかったです。

・活動時間がある程度わかっているなら次何時に寝かせるのか自動で算出したい
→計算自体は簡単ですが、いちいち計算するのが面倒臭かったんです。

・発達の記録をつけたい
→いつ何ができるようになったか、データで残したいという思いがありました。
かつ、活動時間に影響を与える項目なので重要です。

・今どれくらい起きているのか、もしくは寝ているのか一目でわかるようにしたい
→現在の睡眠時間もしくは活動時間が分単位で更新されてわかりやすくなるようにしたかったです。

・夫に子を任せて外出した時に次いつ寝かす？といちいち聞かれるのがすごく嫌で、自分で確認して欲しい
→これは結構ストレスで、アプリを開けば私に聞かずともわかるようにしたかったです。なので赤ちゃん情報の共有機能は絶対必要でした！

・体重の日当りの増加量を自動計算したい
→機能自体は超シンプルで簡単なものですが、特に低月齢の赤ちゃんを育てている方には地味に役に立つ機能だと思っています！
どれくらい増えてるかな？母乳出てるかな？ミルク足りているかな？の判断になる重要な項目なのに、小児科でも保健センターでもカレンダーみて電卓叩いているんですよね。自動で計算したかったです。

体重に関してはおまけです。
睡眠には直接関係ないですが、体重軽めの赤ちゃんは活動時間短めの傾向はあるように思います。

## 機能
* 活動時間の登録を元に次回のお勧めねんね時刻計算(活動時間・睡眠時間・発達・月齢等を元に算出)
* サブアカウントの発行(赤ちゃん情報の共有)
* 睡眠記録の登録(寝かしつけ・寝た・起きた)
* 睡眠時間、活動時間、入眠所要時間の計算と表示
* 睡眠ログ棒グラフで描画(単日、1週間単位)
* 合計睡眠時間の表示
* 体重の登録と表示
* 体重の前計測日からの日割り増加量の計算
* 体重と月齢の折れ線グラフ描画
* 発達記録(練習開始日・習得日)
* 現在の睡眠時間と活動時間を表示

## 専門家監修
安心して使えるアプリにするため、IPHI乳幼児睡眠コンサルタントの坪根理恵さんに監修していただきました。
私自身の経験である程度は作れると思いますが、やはり専門家に監修していただいた方がより良いアプリを作れると考えました。
数多くの赤ちゃんの睡眠改善(夜泣き改善・セルフねんね習得等)をされてきたご経験から具体的な計算式についてや、活動時間の月齢別目安や見極め方のアドバイスについて監修していただき、アプリ内で確認できるようにしました。
おかげ様で価値あるアプリが開発できました。
監修の依頼を快諾してくださり、色んな細かい質問にもいつも丁寧に回答して下さり、理恵さんには心から感謝しています。

今現在、赤ちゃんの寝かしつけや夜泣きに悩んでいる方がいらっしゃれば、理恵さんに相談されるといいと思います。
活動時間も正しく把握できるので、睡眠を整えてからアプリ使う方がお勧めではあります。

https://www.instagram.com/imaneru_rie/

https://www.imaneru.com/

## アプリを使う上で注意したいこと
このアプリを利用する上で大切なのが「活動時間の登録」です。
登録を元に計算しますので、ある程度我が子の活動時間を知っていないとただの記録アプリになります。
監修の理恵さん曰く、活動時間を長く見てしまっている保育者は多いとのことでしたので、本当はどれくらいなのかしっかり観察して眠たいサインが出るタイミングを知るのが重要なことです。
活動時間オーバー　→　疲れすぎ　→　ストレスホルモン分泌　→　寝つき悪くなる(ギャン泣き)
この流れで寝かしつけに苦戦するパターン少なくないので、最初はアプリ内の活動時間の目安を元に寝かしつけてみた方がいいと思います。

:::note info
活動時間とは、赤ちゃんが無理なくご機嫌に起きていられる時間のことです。
活動時間を超えてしまうと夜泣き、寝つきが悪い、寝られてもすぐ起きてしまう等、睡眠のトラブルを引き起こすことが少なからずあります。
:::

## 今後追加していきたい機能
* チャット機能
赤ちゃんの情報を共有しているメイン・サブアカウントでグループチャットをアプリ内でできたらいいなぁと思っています。

ここから少し技術的な内容行きます！！

## github
https://github.com/yoshimoto-a/sleep

## 技術スタック
* React
* Next.js
* TypeScript
* supabase
* prisma
* vercel
* Tailwind CSS

## 使用したライブラリ
* @supabase/supabase-js: Supabaseと連携するため
* @prisma/client: Prismaクライアントライブラリ
* dayjs: 日付と時刻を操作するため
* react-hot-toast: 通知トーストの表示
* react-modal: モーダルダイアログを実装するため
* recharts: グラフを描画するため
* swr: データフェッチ
* jest: テスティングフレームワーク

## データベース設計
まだ実装していない内容も少し含まれています。
ER図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816029/6ee08cbc-8dc7-4410-e29c-6de9125ab572.png)

## 苦労したところ
### サブアカウント作成
簡単なログイン機能はスクールのカリキュラムで作っていましたが、私はサブアカウントを作りたかったのでここが一番最初の山だったかなと思います。
SupabaseにinviteUserByEmailメソッドが用意されていたのでそれを使うことにしました。
Supabaseの公式サイトはサンプルコードも充実していてとてもわかりやすかったです。
赤ちゃんのIDをオプションにして、ユーザー登録する際に赤ちゃんIDの有無で登録しようとしているユーザーがMAINなのかSUBなのかを判断してユーザー登録をするようにしました。
苦労したこととして挙げましたが、調べたら割と普通に実装できたような気もします。
割と最初の方に実装したのとサーバー側でしか使えないメソッドだったので、結構手探りでしたがどこに苦労したかは意外とあまり語れないです！

https://supabase.com/docs/reference/javascript/auth-admin-inviteuserbyemail

https://zenn.dev/matken/articles/invite-user-with-supabase#%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E5%81%B4%E3%81%8B%E3%82%89%E6%8B%9B%E5%BE%85-api-%E3%82%92%E5%8F%A9%E3%81%8F

### 睡眠の登録で不整合データができることを阻止する必要がある
今回は一つのテーブルのレコードに寝かしつけ(bedTime)、寝た(sleep)、起きた(wakeup)の時刻をそれぞれカラムとして持たせることで、差分の計算や紐づけが簡単になるかなと思ってデータベース設計をしました。
「寝かしつけ」は登録する人もいれば不要だという人もいると思うので任意の登録にしようと思いましたが、「寝た」の登録がないのに「起きた」の登録をしようとされては困ります。
また、「寝た」後に「起きた」の登録をしていないのに、また「寝た」を押されても困ります。
「起きた」時にどの「寝た」から「起きた」のかわからないためです。
不整合データができないように登録をブロックすることを考えないといけないことに実装段階で気づきました。

これに関してはスクールで聞いて、フロントではなくサーバー側でブロックすることを教わりました。
具体的には「wakeup」がnullのデータが存在している状態(起きたまで揃っていないデータが存在する状態)で「起きた」以外の登録リクエストが来たらエラーを返すようにしました。
しかし！現役赤ちゃん育児中の私が実際にこの仕様だと困るシーンは容易に想像がつきました。
夜落ち着いてから夕寝の登録することって普通にあると思ったんです。
就寝したときは「寝た」の登録が最後になるので、起きてないからと言って夕寝の登録がブロックされては困ります。
いつでもリアルタイムで登録できるわけがないので、過去の登録等は一括で登録できるようにしようと思い「寝た」と「起きた」がセットであれば登録が可能になるようにエンドポイントを一つ追加しました。

### 睡眠の日別一覧表示(ログイン後のtopページ)
同じテーブルでも普通に日付が変わるので日付跨ぎを考慮するのが難しく感じました。
最初に発生し得るデータパターンを考えて、それに対応出来るように記述しましたが、順番を考えたらそこまで個別のデータパターンに対応しなくても良いことに気付き、さらにクエリを変更したらもっと短く書けることに気付き、リファクタリングを重ねて1000行近くあったコードを100行程度まで減らすことができました。
結構バックエンドでの処理を書くのに時間がかかることが多かったような印象ですが、クエリ次第で成型したいデータをつくりやすくも、作りにくくもなるなと思いました。



他にも沢山苦労しましたが、長くなるので一旦ここまでで今回は終わります！

## おわりに
想いがあって開発したアプリなので、一人でも多くの保育者に認知され使っていただき、寝かしつけが楽になり、親子でぐっすり眠れることを祈って開発を続けたいと思います。
まだまだ未熟な開発者なので、これからも学び続けてより便利になるよう改良改善を続けていきます。