はじめに
27卒でエンジニア就職を目指している大学生です!
大学では物理を専攻しており、これまで本格的なプログラミング経験はほとんどありませんでした。
社会人になる前にある程度開発経験を積みたいと思い、現在Web開発を中心に勉強しています。
課題
旅行のとき、こんなことありませんか?
- 何を持っていけばいいかわからない
- 毎回ChatGPTに聞いている
- ただ、一般的な持ち物しか提案されない
- 結局自分で調整する
- 次の旅行ではまた一から考え直している
特に、自分の場合は毎回
「前回も同じこと考えた気がする…」
となっていました。
そこで、「旅行経験を蓄積して、自分専用の持ち物リストを育てるアプリ」 を作ろうと思いました。
PackTuneとは
PackTune は、旅行の経験を蓄積しながら、自分専用の持ち物リストを育てていくアプリです。
ユーザーは旅行ごとに持ち物を記録し、旅行後に
- 不要だったもの
- 持っていけばよかったもの
をフィードバックできます。
その結果をもとに、アイテムごとのスコアが蓄積され、次回以降の旅行ではユーザーに合った持ち物が提案されます。
↓アプリのリポジトリ
画面一覧
| URL | 内容 |
|---|---|
| /login | ログイン画面 |
| /signup | 新規登録画面 |
| /trips | 旅行一覧 |
| /trips/new | 新規旅行作成 |
| /trips/:tripId | 旅行詳細画面 |
| /trips/:tripId/feedback | フィードバック |
| /items/stats | スタッツ画面 |
【ログイン画面】

新規登録画面からsupabaseのメール認証を済ませるとログインできるようになります。ログインすると旅行一覧へ遷移します。
【旅行一覧】

作成した旅行が一覧で表示されています。この画面から新規旅行作成画面、旅行詳細画面へ移動できます。
【新規旅行作成】

持ち物リストには提案されたアイテムが入っています。候補リストから過去に自分が作成したアイテムを持ち物リストに追加することができます。
【旅行詳細画面】

旅行一覧から旅行を選択するとこの画面へ遷移することができます。
ここでは一般的な持ち物リストとしての使い方ができ、旅行が終わったら、「旅行を終了する」ボタンを押しふりかえり画面に移動します。
【フィードバック】

使わなかったアイテムと追加すればよかったアイテムを記録し、次回の持ち物の提案に繋げます。
【スタッツ画面】
使用技術
- React(TypeScript)
- Vite
- React Router
- Supabase
- Authentication
- Database
- Chakra UI v3
- Vitest / React Testing Library
- GitHub Actions(CI/CD)
主な機能
- メール認証によるログイン
- 旅行の作成
- 持ち物提案
- 持ち物リスト管理
- ふりかえり機能
- スタッツ画面
DB設計
items テーブル
| カラム名 | 型 | 説明 |
|---|---|---|
| id | uuid | 主キー |
| user_id | uuid | ユーザーID |
| name | text | 持ち物名 |
| useful_count | integer | 役立った回数 |
| unused_count | integer | 不要だった回数 |
| created_at | timestamptz | 作成日時 |
trips テーブル
| カラム名 | 型 | 説明 |
|---|---|---|
| id | uuid | 主キー |
| user_id | uuid | ユーザーID |
| title | text | 旅行タイトル |
| start_date | date | 開始日 |
| end_date | date | 終了日 |
| memo | text | メモ |
| is_completed | boolean | 完了状態 |
| created_at | timestamptz | 作成日時 |
trip_items テーブル
| カラム名 | 型 | 説明 |
|---|---|---|
| id | uuid | 主キー |
| trip_id | uuid | tripsテーブルの外部キー |
| item_id | uuid | itemsテーブルの外部キー |
| is_checked | boolean | 持ち物チェック状態 |
| created_at | timestamptz | 作成日時 |
持ち物最適化のロジック
仕組みはかなりシンプルです。
旅行終了後に、
- 使用しなかったもの
- 持っていけばよかったもの
を記録します。
そして、
score = useful_count - unused_count
としてスコアを計算し、一定以上のスコアを持つアイテムを次回旅行時に提案するようにしています。
現在は
score >= 3
を基準にしていますが、この数値は仮で設定しているため、今後調整していきたいと考えています。
苦労したところ
ログイン機能
今回初めて認証機能を実装しました。
そのため、
- 新規登録
- ログイン
- セッション管理
- 非ログインユーザーの制御
などにかなり苦戦しました。
特に、「ログイン状態をどこで持つか」「ルート制御をどうするか」は実装しながら理解していきました。
持ち物の正規化
仕様面でもかなり悩みました。
例えば、
- 歯ブラシ
- ハブラシ
のように表記ゆれがあると、別アイテムとして登録されてしまいます。
また、
- 服
- 着替え
のように、同じ意味でも異なる名前で登録できてしまう問題もあります。
現状は完全には解決できていません。
今後はAIなども利用して、意味的に近いアイテムを統合できないか考えています。
学んだこと
今回の開発を通して、以下のようなことを学びました。
- ログイン機能の実装
- セッション管理
- Supabaseを使った認証・DB操作
- 中間テーブルを用いたDB設計
特に、中間テーブルを使った設計は今回初めてしっかり理解できた部分でした。
今後の展望
旅行タイプ別の提案
例えば、
- 海外旅行
- 山
- 海
- 温泉
など、旅行タイプによって必要な持ち物はかなり変わります。
今後は旅行カテゴリごとに最適化できるようにしたいです。
AIによる提案
現在は単純なスコアベースですが、将来的にはAIも使いたいと考えています。
例えば、
- 着替え
- 服
や、
- 髭剃り
- カミソリ
のような意味的に近いアイテムをAIで統合できるようにしたいです。
おわりに
気づき
【要件定義の難しさ】
JISOUに入って3ヶ月経ち、React + Supabaseの構成なら一から自分でアプリを作ることができるようになりました!
しかし、そもそもどんなアプリを作るかやどういう仕様にするかを決めることは想像以上に難しく、今回の個人開発では苦労しました。
【SQL】
最初、中間テーブルを挟んだデータの取得を複数回に分けておこなっていました。データの数だけリクエストの数が増え、明らかに効率が悪いことに気づき修正しました。今までSQLを学んだことがなかったので少し勉強した方がいいと感じました。
【記事の重要性】
今回のアプリ開発でもたくさんの記事に助けられました。一人だったら解決するのに時間がかかり効率が悪いし、なんなら解決できるかわからないエラーもありました。記事を書いてくれた人のおかげで自分は快適に、短期間でアプリを作成することができると改めて感じました。
まだまだ改善点は多いですが、かなり勉強になった開発でした。
もし「こここうした方がいい」などあれば、ぜひ教えていただけると嬉しいです!
参考記事
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
