👨‍💻

[個人開発]大学生のために履修プランを共有するアプリを作成してみた

2024/05/09に公開

はじめに

初めまして!現在大学3年生のRyoと申します!
先日、大学生の履修プランを共有するサービス「ClassPlannner」をリリースしました。
初めて個人開発を行い自分の納得のいくところまで完成させることができたので、実装と合わせて紹介させていただきます!

プロダクトURL

Github URL

開発の背景

私の所属する学部の卒業要件は非常に複雑なため、卒業までに何を履修すべきか把握するのが難しいです。具体的には、学部内に2つのコースが設けられており、卒業までに4つのプログラムを達成する必要があります。2つのコースでは必修授業が異なり、4つのプログラムごとに必修科目や選択必修科目(決められた授業から一定数の単位を取得)が異なるためです。これを読んでも想像が難しいと思いますが、一言で言うと「卒業までの単位数がパッと見てわからない」という問題点があります。
加えて、Xの投稿を見ていると、「先輩の過去の履修プランを知りたい」「履修登録期間が短く困っている」などの悩みを目にしました。
そのような問題を解決するには、履修プランを共有できる場所があれば解決できると考えました。既存のアプリで自分の授業を管理するアプリはよくあると思いますが、それを共有するアプリはあまり無くオリジナリティを出せるプロダクトだと感じました。また、ちょうど春休みの学習の成果として何かアウトプットを残したいと考え、履修計画共有するためののWebアプリ「ClassPlanner」の開発を始めました。

主な機能

ユーザー関連

ユーザーの新規登録・ログイン機能

メールアドレスを使用して、履修プランを投稿するためのユーザーを登録することができます。ユーザー登録をするとメールアドレスにメールが送られ、指定のリンクにアクセスするとユーザー登録が完了します。この認証技術は後ほど記述しますが、Supabaseの認証機能を採用しています。

PCプレビュー スマートフォンプレビュー

マイページ関連

登録が完了すると マイページにアクセスできるようになり、ユーザー情報編集、投稿した口コミ一覧を閲覧・削除、過去のプランを削除するページにアクセスすることができます。
ユーザー情報は「大学名、ユーザー名、学部・学科名、学年」を編集することができます。この情報は履修プラン一覧のページで表示され、閲覧者が同じ大学のプラン投稿を素早く見つけることなどに役立ちます。

ユーザー名を編集した例

履修プラン関連

プラン閲覧・プランに対する口コミ投稿

ログインしていない状態ではプラン一覧の閲覧と口コミを投稿することができます。そのページから固有のページに遷移することができ、授業の詳細や投稿者の感想などを見ることができます。
口コミに関しては匿名で投稿することができ、気軽に投稿できることを意識しました。ログイン状態で投稿すると後から削除することができますが、ログインしていない状態で投稿した口コミは削除できません。

履修プラン一覧を閲覧するページ

プラン作成・編集・削除

プランを投稿するためにタイトルと、内容と、教科名を合わせて投稿することができます。こうすることで一覧表示されたときにどんなプランなのかを閲覧者に伝えることができます。また投稿したプランを編集・削除することができます。編集画面ではタイトル関連と、授業関連のそれぞれで編集できるようにし、編集済みのものはその後テキストボックスにアクセスできないことをUI上で確認できるようにしています。

履修プランを編集するページ

こだわりポイント

デザインに関して

私はデザインの経験はありませんでしたがUIを構築する上で以下の点を意識しました。

  1. 色を使いすぎないこと
    自分の考えとして色は使いすぎれば使い過ぎるほど統一感がなくなり、見る人の意識を集中させることができないと考えています。そこで白or黒 + 何かしらの色をベースにしようと考え白+オレンジ色をベース にしました。
    また背景の画像はHaikeiというサービスを使用して取得させていただきました。様々な形のパターンがあり、使いやすく見た目もお気に入りです、
  1. 柔らかい雰囲気を演出すること
    私が柔らかい雰囲気を演出させるために工夫したこととして、暖色を使うこととやローディングに一癖あるものを使用するということが挙げられます。このアプリは大学生に寄り添ったアプリなので、「かっこよさ」よりも「親しみやすい暖かい雰囲気」の方が適している考えました。
    またローディングに関してはreact-spinnersというライブラリを使用しました。このライブラリは複数のローディングアニメーションアイコンを提供しているライブラリです。特徴的なものがあり今回の雰囲気と合致していると考えたため使用させていただきました。

技術的なことに関して

  1. データ取得を極力SSRで実現
    これまでの開発ではデータフェッチングに関して特に意識せずに実装していましたが、今回はSSR(サーバーサイドレンダリング)を使用することでパフォーマンス向上に努めました。SSRで取得することで初回読み込み速度が高速になることや、サーバー側でレンダリングするため読み込み速度がPCのスペックに依存しずらいという利点があります。また、今回はユーザーが投稿してそれを表示しているという形のアプリケーションで変更が頻繁に行われるため、SSGではなくSSRを採用しています。

https://github.com/kameiryohei/Ie-ClassPro/blob/main/app/allPost/components/CourseCardCore.tsx#L6-L16

またここではAPIのエンドポイントを動的に変更させるためnext/headerのheadersを使用して開発環境とデプロイ後でエラーが発生しないように工夫しています。
プロフィールページで実装しているユーザー情報に関してはUseUser.tsというカスタムフックスでsessionの管理をしておりsessionからユーザ固有のIdを取得しているためuseSWRを使用してデータフェッチを行いました。これによりuseEffectで実装していた時に比べ高速でデータフェッチができるようになり、キャッシュを有効にできたためユーザー体験を向上させることができました。

  1. CRUD操作の全てを実装したこと
    過去の開発では読み取り(Read)と作成(Create)で止まってしまう開発が多く、全てのCRUD操作を自力で実装したいという気持ちがあり今回取り入れました。全ての操作を実装することで履修プランを後から編集する機能などを実装できたため、履修プランを投稿するまでの敷居を低くすることができ、ユーザー体験を向上させることができたと感じています。個人的にはCRUD操作はアプリケーション機能の基礎でその基礎を今回学べたことは今後の開発やステップアップに活かせると感じました。

苦労した点

バックエンドとフロントエンドの連携について

これまで外部のAPIを使用することはありましたが、自分で記述したことがなかったため初めの方はエラーの解決にかなり時間を割きました。具体的には、あるデータが送れないDBに保存できないというエラーが続き、クライアント側かサーバー側どちらが原因なのかをつきとめることに苦労しました。初めは時間をかけて解決していたのですが、後半以降はPostmanというWebAPIをテストするツールを使用することで格段に開発効率を上げることができました。以前から認知はしていましたが必要ないと思い使っていませんでした。今後は積極的に使用していきたいと思います!

個人開発での目標設定について

今回の開発では「履修プランを共有できるWebアプリを作ろう!」という曖昧な目標設定をしてしまったせいで開発を進める中で実装の順番を決めることできませんでした。その結果、自分の実装したい順番で行い、後々修正する箇所が発生してしまったという反省点がありました。ハッカソンでは複数人で開発を行うことがスタンダードなので、ミーティングで要件などを決めていましたが、個人での開発となると初期段階が曖昧となってしまいました。この経験から、個人のチームでの問わずにどんな機能を実装するのかを言語化しておくことが重要だと感じました。

使用技術

フロントエンド

フロントエンドには言語にTypescript、フレームワークにNext.js、CSSフレームワークにTailwindCSS、UIライブラリにShadcn/Uiを採用しました。

  1. Typescriptを選定した理由
    Typescriptは静的型付き言語であるためJavascriptでは実現できなかった、型によるエラーを実行前に教えてくれる点型による補完が効く点が強力だと感じたため採用しました。
    今回の開発でもnumber型の変数にstring型の値を入れてしまうというミスがありましたが、Typescriptを使用することで型エラーが出るのでエラーの原因に時間をかけるということが少なくなりました。
    また型による補完についてですが、例えばuserという情報の中のnameuniversityなどの情報を取得したいと言う場面で、userの後に".(ドット)"で繋ぐだけで中身情報の候補を表示してくれます。このように型定義をすることで開発を効率的に進めすことができる点が強力です。

  2. Next.jsを選定した理由
    Next.jsを採用した理由として、過去に参加したハッカソンでReactを使用した経験があり、そこでの学びを活かして新しい技術を触りたいと思ったからです。また簡単にでSSR(サーバーサイドレンダリング)やSSGを実装できる点、ファイルベースルーティングのおかげで開発効率が上げることができる点も強力なので採用しました。

  3. TailwindCSSを選定した理由
    TailwindCSSはHTMLのクラス名に直接CSSを記述できるため開発効率が上がる点や、Shadcn/Uiを導入するために採用しました。

  4. Shadcn/Uiを選定した理由
    UIライブラリはShadcn/UiとMaterialUIと比較して、Shadcn/UiはTailwindベースで書かれているためカスタマイズ性に優れている点、一度に全てのコンポーネントをインストール必要がないので軽量である点が優れていると考え、採用しました。

バックエンド

バックエンドにはNext.jsで簡易的なAPIを作成できる機能であるAPIRoute、BASS(Backend as a Service)であるSupabase、TypescriptのORMであるPrismaを使用しました。

  1. APIRouteを採用した理由
    APIRouteはNext.jsのappディレクトリ配下にapiディレクトリを作成し、route.tsという名前のファイルを作成することでAPIを作成することができます。新しくバックエンドの言語を学習するという選択肢もありましたが、現状の自分の力でプロダクトを作成したいと思ったため選定しました。
  2. Supabaseを採用した理由
    またSupabaseはBASSであるため認証機能を簡単に構築できる点や、データベースが標準で搭載されている点が非常に便利です。管理画面も非常に見やすく、DBのセキュリティー設定も簡単に行える点が強力と感じています。また以前にFirebaseを採用した経験があるのですが、採用しているDBがNoSQLとPostgreSQLで異なるので違いを感じたいという気持ちもありました。
  3. Prismaを採用した理由
    Prismaは私のようなSQLを知らない人でも簡単にスキーマ設定やデータベース操作が行える点が優れているるので採用しました。また、型安全なデータベースアクセスが特徴で、TypeScriptと組み合わせると強力な型サポートを受けることが点ができる点が魅力的でした。

今後の展望

ニーズに合わせて機能を修正・追加すること

今回のプロダクトを周りの人に使ってもらい、フィードバックから修正を繰り返し、より良いアプリケーションに成長させていきたいと思っています。自分だけの考えだと「この機能って本当に必要?」という疑問などに気づきずらいと思います。なのでユーザーが本当に求めている機能は何なのかと言う思考を養うためにも、まずは周りから意見をいただきたいと思っています。

ページネーションの追加とプランに対するいいね機能の追加

現在の履修プラン一覧を表示している画面では全てのプランを取得する操作になっているため、プラン数が多くなるとサーバーに負荷を与えてしまう実装となっています。そのためにページネーションを追加し一回に取得するプランの数を制限したいと思っています。
次に、気になったプランを後で見返したい機能や、プラン投稿者がこのプランが需要があるのかどうかを評価する指針としての「いいね機能」を実装したいと思っています。

終わりに

ここまで読んでいただきありがとうございます!
個人的にこのプロダクトを作る中で、詰まる点が多くありましたが試行錯誤しながら解決することができ、課題解決力を養えたと感じています。時間をかけて一つのプロダクトを作成することは大変でしたが、達成したときの充実感はとてもありました。また、作成しながらフロントエンド技術を深める機会にもなり、バックエンドの処理についても簡易的ではあるものの学ぶことができました。アウトプットは学習する上でも重要だと感じたためこのように記事を書いて理解と深めるという習慣をつけていきたいです。今後はバックエンド言語やDBについても学び、最終的には実務で採用されているような技術スタックでフルスタックアプリケーションを作成することを目標としています。その目標に向け、今回の開発での学びは活かせるものが多かったと考えています。今後も学び続け、エンジニアとしてのスキルを向上させていきたいと思います!

Discussion