🧍

【チーム開発 第 2 弾】ジョジョ立ち倶楽部 ~エンジニア未経験からのフレームワーク挑戦記~

2024/04/05に公開

はじめに

 これは、

  • エンジニア未経験の 36 歳
  • 文系大学出身(高校数学赤点ギリギリ)
  • 非効率で無駄なことが大好き
  • Ruby と、Ruby on Rails の学習を終え、API について知ったばかり

  そんな一人の男が、第 1 回目のチーム開発を経て、およそ 3 ヶ月のプログラミング学習を通して得た知識と技術で、初めてフレームワークを使ってチーム開発に挑んだ軌跡(ブログ)です。

(第 1 回目のチーム開発については、こちら)
https://zenn.dev/iranorih/articles/5d777bdd7f3359

アプレンティスについて

 この 3 ヶ月間、アプレンティスというカリキュラムに参加して、プログラミングの学習を続けています。カリキュラムの一環として、今回このブログに書いているチーム開発を行いました。

https://apprentice.jp/

 今回のチーム開発のテーマは、

『ワクワクするものを開発せよ』

チームメンバーとの話し合い

 以前同じチームだった人もいれば、初めましての人もいる新チームでの開発。まずは、テーマに沿ったアプリのアイディアを集めました。

  • わくわくを主目的としたエンタメ系のアプリにするか
  • 課題を解決する目的のアプリに、わくわく要素を散りばめるか

 こんなことを考えながら話し合い、ついに私たちのチームが作成するアプリが決まりました!

今回作成したアプリ

【アプリ名】ジョジョ立ち倶楽部

https://youtu.be/gNwxkVXvyjg

【決定理由】

  • 世の中にまだ「ジョジョ立ち」に特化したアプリがない
  • 公表していないが、ジョジョ好きの人たちは多い(個人の見解)
  • 『ジョジョの奇妙な冒険』は、セリフ集やジョジョ立ちといったワードができるなど、根強い「わくわく要素」をもっている

 つまり、ジョジョに対して元々わくわくしているユーザーを集めて、わくわく要素満載のジョジョ立ち写真を投稿・共有することで、わくわくの相乗効果を得て活気あふれるウェブアプリにしようということです!!

 アプリの仕様等については、こちらをご覧ください。

https://docs.google.com/document/d/1IOrOboLc1B1FWmgJ0CkqVHPj1bOAZTtJMEbaKCelp5Q/edit?usp=sharing

開発に使用したプログラミング言語とツール

【フロントエンド技術】

  • Next.js 14.1.3

【バックエンド技術】

  • Ruby 3.2.3
  • Rails 7.1.3.2
  • ImageMagick 6.9.13-7

【データベース管理】

  • MySQL 8.0.36

【打合せで使用したツール】

  • Canva (ホワイトボードを活用して、リアルタイムで情報を共有・可視化)
  • figma (ワイヤーフレームやデザインプロトタイプの作成で使用)
  • Discord(チャットやボイスチャンネルの活用)

開発の進め方

  • 週に 2 回のチーム会(実装週間は 3 回以上)
  • Canva の付箋を使って、スケジュールを管理

  • 全て Canva で管理・共有することで、タスクを可視化!
  • これまで話し合ったことも全て残せるので、備忘録としても活用!

アプリ完成までの壁

 「ジョジョ立ち倶楽部」というアプリを完成させる上で、私たちの前に立ちはだかる大きな壁は、「未知」という壁でした。

  • まだ React や Next.js を未学習の状態(この後のフェーズで学習するカリキュラムになっている)
  • ユーザーを登録して、ログインできるようにするには?
  • 画像ファイルのアップロードをできるようにするには?
  • 詳細ページで、投稿に対するコメントができるようにするには?
  • いいね数を取得して、昇順で表示してランキングページに反映するには?
  • スライダー機能や CSS を充実させて、ジョジョの世界観を表現するには?

 これまで、簡単な TODO アプリやブログ投稿アプリしか作ったことがなかったですが、初めてフレームワークを使ってアプリを実装できる(第 1 回目のチーム開発は、カリキュラムの趣旨でフレームワーク不使用という制限付きだったため)ので、「未知」という壁に挑むわくわく感が勝っていました。

タスク分解

 まずは、テーブル設計を全員で行いました。

 その後は、未知の機能(先述)が多かったため、1,2 日間という単位で終わる(と思われる)タスクを抽出して分担 → 次のチーム会で進捗の確認と機能の共有 → 実装を終えたら次の機能のタスクを抽出して分担 →…というように、自分たちが見通せるところまでのタスクを抽出・分担・実装を繰り返していきました。

 タスク分解は、第 1 回チーム開発の反省点でもありました。前回は「3 歩進んで 2 歩下がる」という実装感でしたが、今回は「1 歩ずつ確実に進める」という感覚で実装することができました!

 今回私が担当したタスクは、

  • チーム会の進行
  • アプリ仕様書の作成
  • ワイヤーフレームの作成
  • RailsAPI と基本的な CRUD 処理の実装
  • 画像ファイルのアップロード周り
  • 一覧ページ・投稿フォーム・詳細ページ・編集ページの実装
  • 詳細ページにコメントを投稿できる機能の実装
  • 一覧ページの CSS とスライダー機能の実装

 私が苦手意識のあるログイン周りやデザイン性のある CSS などは、チームのメンバーがやってくれました。かたじけパーリナイ...!!

開発過程での振り返り(技術面)

1. React と Next.js の基礎を身に着ける

【課題】

 アプリのフロントエンドで使用予定の React と Next.js を未学習

【対応】

  Next.js のチュートリアルページで使い方を調べ、RealWorld のフロントエンドを Next.js で実装することに挑戦

https://nextjs.org/learn-pages-router/basics/create-nextjs-app

https://realworld-docs.netlify.app/docs/specs/frontend-specs/templates/

【結果】

 今回のアプリで使いたい最低限の CRUD 処理を搭載したブログアプリを作ることに成功!

 さらに、詳細ページにコメントを投稿できる方法を調べ、RealWorld のコードに追記して、学習内容を先取りできた!

2. ログイン機能

【課題】

 「新米には任せないタスク」「個人情報を扱う重要な箇所」「セキュリティを十分に考慮したコードに仕上げる」といった情報ばかりを目にして、「ログイン機能って難しそう…」という固定観念にとらわれた!

【対応】

(1) Rails チュートリアル(8 章以降)でバックエンドの仕組みを学習!

https://railstutorial.jp/

(2) JWT についてチームメンバーに解説してもらう!

 チームメンバーがこの部分を担当し、分かりやすく解説してくれたおかげで、理屈は 3 割程度分かったような気がします!

【結果】

(1)  「セッション」「ハッシュ化」「トークン」の基礎知識を 3 割程度獲得!

(2)  間違っている可能性大ですが、自称 3 割の知識でログイン機能と JWT 認証をまとめてみました。↓

~ JWT 認証~

 JWT は、ヘッダー・ペイロード・署名の 3 つの部分からなる。

  1. ヘッダー(Header)

    • パスポートの表紙のようなもの
    • ヘッダーの中には「このトークンは何の種類か」と「どのような方法で保護されているか」といった情報が書かれている
  2. ペイロード(Payload)

    • トークンの中身の部分
    • パスポートの中の個人情報ページのようなもの
    • ペイロードには、認証されたユーザーの名前やメールアドレス、権限などが含まれる
  3. 署名(Signature)

    • トークンが本物であることを確認するための鍵のようなもの
    • 鍵が正しい場合、トークンは信頼できるものとみなされる
    • 署名は、ヘッダーとペイロードを一緒にして暗号化される
    • この署名を検証することで、トークンが本物であることを確認する

~ログインの仕組み~

  1. ログイン:
    • メールアドレスとパスワードを送信
  2. 認証
    • サーバー側で、受け取ったアドレスとパスワードを検証
  3. JWT の生成
    • ユーザー ID などの情報をサーバーはペイロードに含め、シークレットキーを使って署名を行い、JWT を生成する
3. 画像ファイルのアップロード ① 「Active Storage」

【課題】

 画像がどういうデータで、どのような仕組みで扱われているか全く想像もできない状態!

【対応】

 Rails のライブラリで「Active Storage」というものがあると知りました!

 そこで早速、Rails だけを使って画像をアップロードするだけのアプリを作ってみました。今回は、ローカル環境で動かすことを想定していたので、クラウドサービスなどは使用しませんでした。

https://railsguides.jp/active_storage_overview.html

https://qiita.com/hmmrjn/items/7cc5e5348755c517458a

【結果】

 上記の記事を参考に実装してみると、「あれ?簡単にできたぞ!!!」という誤った成功体験を味わってしまいました。

 しかし、Rails の view テンプレートではなく、RailsAPI と Next.js を使って実装したときエラーが連発…!

 結局、「画像がどういうデータで、どのような仕組みで扱われているか」という点を理解していないまま Active Storage 頼みの実装に終わっていたためだったと反省…

4. 画像ファイルのアップロード ② 「CarrierWave」

【課題】

 「Active Storage」が便利過ぎて、画像がどういうデータでどのような仕組みで扱われているかといった部分を理解できていなかった!

【対応】

 以下の記事を参考にして、ローカル環境の特定のディレクトリに、アップロードされた画像を保存する仕組みにしました。

https://zenn.dev/yukihaga/articles/e63a224431bc96

https://qiita.com/STHEXA/items/05a492bd9cf4cf31ba98

https://qiita.com/TK_WebSE/items/f499232e35de5b9d273e

【結果】

 「画像ファイルはバイナリデータ(0 と 1 で表されるアレ)として扱われることが多い」「プログラム内で操作する際には、文字列として扱うことができる」ということが分かりました!

 また、画像ファイルのアップロードと、取得して画面に表示するコードを書く際には、console.log や puts を使って、パラメータにどのような形でデータが入っているかを確認することが大切だということも学びました!

5. 詳細ページにコメント機能を実装

【課題】

 そもそも、人の投稿にコメントを付ける仕組み自体が分からない!(勝手な予想: posts テーブルと comments テーブルの id を紐づければ取得して表示できそうな気がする)

【対応】

 以下の記事を参考にして実装してみました。

https://zenn.dev/goldsaya/articles/cfe875600d825a

https://qiita.com/kurawo___D/items/d2fefdd329f5310113aa

【結果】

 routes.rb で、comments リソースを posts リソース内にネストすることで、欲しかったパスを獲得できました!

 comment.rb に「belongs_to :post」、post.rb に「has_many :comments」を記載して、後はこれまで通り MVC モデルの書き方で実装できました!

6. いいねの数を取得してランキングページに反映

【課題】

 「いいね機能」の実装方法を知らない…!(自信のある予想: 数の取得は、.order(likes_count: :desc)でランキングページに反映できそう)

【対策】

 以下の記事を参考にして調べました。

https://zenn.dev/ganmo3/articles/c071ba9aecaa51

https://qiita.com/RIN_HM/items/968abd9e31df6631a3ed

【結果】

 期日までに実装することはできない(他に優先すべき機能が残っていた)ため、今回は断念しました…!知識として押さえておき、今後しっかりと拡張・実装していきます。

7. 一覧ページの CSS とスライダー機能の実装

【課題】

 Next.js を使うので、フロントのデザイン性を高めたい…のだが、「おしゃれでモダンなデザイン」がとんなものなのか引き出しがない!

【対応】

 デザイン性の高いページってどんなのだろう →ZOZOTOWN とか X(旧 Twitter)とか!?→ 公式ページを見に行き、検証ツールを参考 → スライダー機能があるとおしゃれ! → 検証ツールを開いて、「swiper」というコードを発見

 というわけで、以下の記事を参考に実装しました。

https://swiperjs.com/

https://zenn.dev/h_ymt/articles/589367fa1d6c25

【結果】

 自分の画面ではいい感じに画像を配置してスライドできたのですが、発表者の画面だと、画像がぎゅっと詰まって表示されてしまいました…。

 まだまだ応用を利かせられるほど Swiper の仕組みを理解できていないので、今後も勉強していきます。

開発過程での振り返り(マネジメント面)

1. ジョジョ立ちだョ! 全員集合

【きっかけ】

 ジョジョ立ち写真を投稿・共有するアプリを紹介するときに、作成している本人たちの写真が投稿されていたら、面白い(わくわくしちゃう)のではないか!?(個人の見解です)

【行動】

 メンバーの一人だけ住居地が離れていたのですが、近くに来る予定があるとのことだったので、メンバー全員で直接会って、ジョジョ立ち写真を撮りました!

【結果】

 リモートでは顔を合わせていたものの、直接会うのは初めてだったので新鮮な感覚でした。

 カフェのフリー Wi-Fi は、接続が弱すぎることを知りました。

 まだアプリが完成したわけではないけれど、ジョジョ立ち写真撮れた打ち上げみたいになりました。このお陰で、チーム開発に更なる勢いが加わった気がします!

2. タスクの時間の見積もり

【課題】

 スキルや経験の浅さから、タスクの分解がまだまだ不鮮明…!

【対応】

 週次または日次のチーム会を設け、進捗状況を確認し、必要に応じてタスクの再割り当てをし、お互いにフォローし合えるようにしました。

【結果】

 期日当日まで、細かな修正を行うことになりました。ただ、「誰か一人にタスクを丸投げしている」「どこかのタスクが終わるまで動けない」「手戻りが発生する」といったことを避けることができました!

チームメンバーとの振り返り

 開発したチームメンバーと集まり、アプリの振り返りだけでなく、メンバー一人一人の「ここがすごい!」「ここをもっと良くしよう!」ということについても伝え合いました。

1. メンバーの方からいただいた「ここがすごい!」
  • リーダーシップがあって、チームをまとめてくれた
  • 全体の雰囲気を良くしてくれた
  • 率先して話し合いを進行してくれた
  • いつも周りを見て、タスクなどを分担してくれた
  • 日々の学習が技術力に表れていた
  • 分からないことを聞いたときに、分かりやすく丁寧に教えてくれた
  • 開発で、最後まで細かい部分を修正してくれて、熱を感じた

 第 1 回のチーム開発では、コードの書き方に悪戦苦闘し(今でもそうですが)、担当タスクの機能を実装するのに、予定より多くの時間を費やしてしまうということがありました。

 今回は、その点を改善して、自分が進行面や技術面をカバーできるようになりたいと思っていたので、メンバーにも褒めてもらえて嬉しい気持ちでいっぱいです。

2. 「ここをもっと良くしよう!」

 メンバーからは、「特にないです」と変に気を遣わせてしまったようなので、自分で考えたことを書きます!

  • (マネジメント面の振り返りでも書きましたが)タスクを見積もる経験値がまだまだ浅く、計画を何度も修正していく形になってしまった。

=> 今後も経験を重ねていき、必要以上に見直さなくても良いような計画・スケジュールを立てることができるようにする。

  • エラーが発生した際に、エラー文を読んでも即座に問題を理解できず、解決のために適切な情報を得るのに時間がかかってしまった。

=> コードに console.log や puts などのデバッグ文を追加して、エラーを起こしている変数や関数の中身を確かめて、仮説を立てて、エラーの原因や解決法を素早く見つけられるようにする。

  • フレームワークやライブラリなどの便利機能に依存しすぎて、その基本的な仕組みや原理への理解が浅い場合があった。

=> 基本的な概念や仕組みを学習するための時間を確保する。また、公式ドキュメントやチュートリアル、書籍などを通じて、技術の基礎を引き続き理解する。

おわりに

 この記事では、エンジニア未経験からフレームワークを使ったチーム開発に挑戦した私の体験を共有しました。挑戦の過程で、新しいことを学び、成長する機会を得ることができました。

 このプロジェクトでは、未知の技術や機能に対する不安や課題に直面しながらも、チームメンバーと協力して解決策を見つけ、成果を生み出すことができました。また、チームメンバーとのコミュニケーションやフィードバックの重要性を、改めて感じることができました。

 これからも、技術の学習と実践を継続し、未知を恐れずに新しいことにチャレンジしていきたいと思います。また、チームとしての協力やコミュニケーションの大切さを忘れずに、共に成長し続けたいです。

 最後に、このプロジェクトに携わった全てのメンバーに感謝の意を表します。皆さんのサポートと協力がなければ、私の成長はありませんでした。共に学び合い、成長し合える仲間として、これからもよろしくお願いします!

Discussion