この度ずっと通っていたフィヨルドブートキャンプを卒業しましたので、この記事でその最終課題として作ったアプリケーションについて書きます。
はじめに
どうも ot0m1 です。 現在GMOペパボという会社の Customer Reliability Team で働きながら、業務で必要な技術の習得とエンジニアへの職種変更を目的としてフィヨルドブートキャンプで学んでいました。 フィヨルドブートキャンプの課題及び Spotify の iOS 版アプリケーションを使っていた課題の解決として開発していたアプリケーションをリリースしました。この記事はその紹介となります。
アプリケーション の紹介
作ったアプリケーションは Srive という名前です。 Spotify + drive の造語です。
リポジトリは https://github.com/ot0m1/Srive で、https://srive.app/ からアクセスできます。
作った動機
僕は Spotify のヘビーユーザーで、2022年は日本のユーザーの上位2%に入るくらい利用していました。 72,415分聴いていたらしいです…!
また、車の運転も好きで、ほぼ毎週どこかにドライブに行っています。 ドライブ中は常に Spotify の iOS 版アプリケーションで音楽を聴いています。
Spotify の iOS 版アプリケーションを利用している際、以下のような問題を常々感じていました。
Spotify のデスクトップ版のアプリケーションだと同じアーティストのアルバム、シングを全体的に横断してリリースが新しい順 or 古い順に連続して再生ができるが、iOS 版のアプリケーションだと、以下の画面のようにアルバム単位、シングル単位で手動で遷移しないと再生ができない。
デスクトップ版のアプリケーションだとアルバム、シングル全体を横断してリリースが新しい順 or 古い順に連続して再生ができるが、
iOS 版のアプリケーションだと、以下の画面のようにアルバム単位、シングル単位で遷移しないと再生ができません。
曲全部を一気に聴きたいと思っても、Spotify によって作成されたコンセプチュアルなプレイリストしかなく、他のアーティストの曲などが含まれていたりします。 たまに有志が作成してくれた曲を網羅したプレイリストが存在することがあるが、あったりなかったりと運まかせです。
当然アプリケーション側で連続して曲をかけてくれる機能はあるのですが、それは Spotify 側がリコメンドして選んでくれたものであって、同じアーティストの曲を発表順に連続してかけてくれる性質のものではありません。 そのため、Spotify の iOS 版アプリケーションで同じアーティストの曲を連続して聴き続けようとすると、シングルやアルバムの演奏が終わると手動で次の曲を選択する必要があります。
車の運転などをしていると、スマートフォンの操作ができないのでどうしても連続再生ができません。そもそも次の曲にかける曲を手動で選択するという操作がめんどくさいです。 そういった問題を解決し、ドライブ中などスマートフォンの操作ができない場面でもずっと同じアーティストの曲を連続して網羅的に聴くためにこのアプリケーションを作りました。
※Android 版のアプリケーションは触ったことがないので iOS 版と同様の仕様なのか、デスクトップ版のアプリケーションのように連続して同じアーティストの曲を聴き続けられるのかは把握していないです。
なぜ僕がこのように網羅的に聴くことにこだわるかと言うと、僕がその時々に流行している曲や、アーティストのヒット曲だけを聴くというより、ジャンルやアーティストを深堀りするような聴き方をしているからという理由があります。 趣味で DJ をやっているのもあり、気になったアーティストは一通り全部聴いて把握しておきたいからです。いわゆるディグるというようなものにちょっと近いのかもしれません。 また、音楽史上重要なアーティストでまだ未履修なものも、勉強のような気持ちで一旦全部聴く、というようなこともします。
上記のような聴き方を目的として Spotify を利用しているので、同じアーティストの曲を連続してとりあえず全部聴きたいという気持ちが強くあります。
使い方
- https://srive.app へアクセス
- アーティストを検索
- 検索結果から希望のアーティストを選択
- シングル曲だけ、アルバム曲だけ、シングルとアルバムの両方の曲かを選択
- Create a Playlist をクリック
- Open a playlist in Spotify をクリック
これで Spotify に移行して作成されたプレイリストを再生すれば網羅的に聴けます!
こういう人に使って欲しい
- ドライブ好きな人
- 気になったアーティストがいたらとりあえず全曲聴いてみたいという人
- そういえばあの偉大なアーティスト未履修だったな、とか日頃思っちゃう人
上記に当てはまる Spotify ユーザーは是非使ってみてください。
※現在 Srive からの API の利用が Spotify 側で Development mode として制限されており、利用者の数に上限があります。 Srive から Spotify へログインできない場合、僕に twitter の DM などで 以下の Spotify アカウントの情報を教えていただければ利用者として登録します。
- メールアドレス
- ユーザー名(https://www.spotify.com/jp/account/overview/ のユーザー名と書かれている箇所の情報)
Spotify へ制限緩和の申請を行っており、緩和され次第誰でも利用可能になる予定です。
技術スタック
- 言語
- TypeScript
- ライブラリやフレームワーク
- React + Next.js
- テストライブラリ
- React Testing Library + Jest
- CI/CD
- GitHub Actions
- deploy
- Vercel
- domain
- Google Domains
それぞれの技術スタックの採用理由
TypeScript + React + Next.js
フロントもバックエンドも TypeScript を採用しました。 以下のような理由から TypeScript + React + Next.js という組み合わせになっています。
- Srive は Spotify の API をいい感じに叩いてくれるクライアントアプリという位置づけであり、データの永続化やメールの送信やファイルアップロードなどが無いかなりシンプルなアプリケーションである
- 現在勤めている会社のフロントエンドアーキテクチャ規約で、開発言語は TypeScript 、ライブラリは React 、SPA を作成する場合は Next.js を使用することが最も推奨されている
- 自分は転職より、現在勤めている会社でエンジニアへのジョブチェンジを優先して考えているので、フロントエンドアーキテクチャ規約で推奨されているものの経験を詰んでみたい
- React と Next.js は最近良く見聞きするので興味があった
- 自分の中の JavaScript の知識は jQuery でとまっているので、モダンなフロントエンドの開発というのがどういうものか経験したかった
ですが、当初は Ruby on Rails での開発を考えていました。 そのあたりは開発中に苦労したことで詳しく述べたいと思います。
React Testing Library + Jest
React の公式で勧めらているものを使おう、テストの経験が薄いので公式に素直に従おうという理由から採用しました。
GitHub Actions
現職の業務でも利用しており多少なじみがあるしもっと経験を積みたいこと、他の CI/CD は全然知らないこと、全く未経験のフレームワークを利用して苦労するのは予測されるから、CI/CD にかける苦労は最小限にしたいと思い、最も導入に苦労しなさそうだという理由から採用しました。
Vercel
デプロイ先の候補を色々調べてみると、Next.js なら Vercel という感じだったので採用しました。 ちょうど Heroku が有料化したタイミングだったので、Heroku 以外の選択肢を探していたので特に悩まずすんなり決まりました。 デプロイがめちゃくちゃ簡単で感動しました。全くといっていいほどつまりませんでした。
Google Domains
複数のレジストラを比較して、srive.app というドメインが安く取得できそうだったこと、Google Domains でドメインをとったことがなかったのでやってみたいという理由から採用しました。
開発中に意識していたこと
開発を習慣化すること
アプリケーションの完成までに必要なことをカンバンに書き出してみるとかなりの量になり、完成までに必要になる作業のことを考えると途方もなく感じてしまい開発に着手できないことがよくありました。
開発に着手し完成までもっていくために、とにかく毎日ちょっとずつでもいいので先に進むよう開発を習慣化させることを何よりも意識しました。 仕事の昼休みの一時間、仕事終わりのすぐは体が仕事モードになっており、仕事中と同じ感覚で IDE を立ち上げる、わからないところを調べる、という行為の心理的なハードルが自分の中で下がっていることを見つけ、そのタイミングのときは継続して手を動かすことを最優先としました。 習慣化でき、その時間帯はほぼ毎日開発を進めることができました。
開発できない日があっても気にしないこと
上記の習慣化だと平日のみが対象になりますが、少しでも継続できていれば大いに収穫だと考え、休みの日に進捗がなくても気にしないことを意識しました。 休みの日にちょっとでも進められたらラッキー、できなくても平日になれば習慣の力で着手できることがわかっているので大した問題ではないと考えることができました。
そのおかげで休みの日に進捗がなくてもあまり自分を責めなくなり、不必要なストレスから開放されたと感じています。 自分を責めてもアプリケーションの完成には何の貢献もしないので、手を動かさなかったことをあとから悔やんだり責めたりすることは完全に無意味だと割り切れるようになりました。
調べるときは公式サイトなどの一次情報を参考にすること
散々言われていることですが、何度言っても言い足りないですねこれは…!
わからないことを調べている際、ついついググった検索結果上位の日本語で書かれているブログなどを参考にしたくなりますが、それをぐっと堪えて一次情報を見に行くのが結局早いことが多いということがやっと身に付いてきました。
今回の技術スタックだと一次情報が英語であることが当たり前ではあるのですが、今は DeepL などがあります。Chrome 拡張なども活用すれば今までよりも格段に英語の文献を読むのが楽になっています。なので英語であっても臆せず一次情報にあたれるようになりました。
今回の開発にあたり、Spotify の開発者向けドキュメントを翻訳して自分用に日本語でまとめて何度も読み返しました。 特に OAuth での認可フローについてはかなり読み込んでいます。最終的にはライブラリを採用して置き換えましたが、読み込んだおかげで自分で OAuth の認可ロジックを実装することもできました。
一次情報はどうしても情報量が多く、やりたいことに対してのそのものズバリの解法でなかったりもしますが、それでもやはり以下に挙げるようなメリットの方が大きいです。
- 情報が正確で常に最新の情報になっている
- 後々役に立つ情報も一緒に習得できることが多々ある
- 考慮しておいた方がいいポイントなども併せて書かれていたりするので、手戻りを未然に防げることがある
情報が正確で常に最新の情報になっているのは自明すぎるわけですが、後者のメリットを本格的な開発では感じる事が多かったため、改めて意識したこととして書いています。
一次情報は情報量が多いな〜と感じてしまうことは多々ありますが、多いということはそれだけ知っておいが方がいいことがあるというわけです。 開発時に考慮すべき箇所や、有用なオプションなども一緒に得られるのが一次情報に当たる理由でもあります。 うかつに二次情報に飛びついてしまった結果、後々考慮漏れなどが発覚して結局書き直すということがありました。特にセキュリティ面での考慮漏れは大きな問題となることがあり得るため、十分に仕様を把握する必要があります。
なので、せっかく一次情報を参考する場合は必要そうなところだけをつまみ読みするだけでなく、もう少し広い範囲を一通り読んでみることをお勧めます。 それで一気に問題が解決して先に進むこともありました。
英語でもググること
むしろ最初にまず英語でググる、というくらいでもいいかもしれません。 日本語での検索でもわりと英語で書かれた一次情報には行き当たれますが、GitHub の issue でのやりとりなどがヒットしません。 利用しているライブラリの公式リポジトリの issue でのやりとりなどで、やりたいことが仕様上できない、できるがセキュリティ上の考慮点が必要である(その結果現在の自分の理解度では採用を見送った方がいいかもしれない)といったことがわかったりします。
公式リポジトリでのやりとりだと回答者が開発者やコミッターであったりと回答の質が担保されていること、質問もエンジニアの方がソースコードを引用してのつっこんだ内容だったりで、ライブラリへの理解が深まったりとやりとりを読むだけでも参考になることが多くありました。
RFC も見に行くようにしたこと
一次情報の参照ともかぶりますが、今まで漠然と自分が読むには高度すぎるなどと勝手に苦手意識を持っていた RFC も積極的に参考するように心がけました。 すぐには読み解けなくても、この積み重ねが後から効いてくると考えています。
開発中に苦労したこと
振り返ると苦労の連続でした。最後の方はもはやよくここまでわからないことが次から次に出てくるものだなぁとちょっと面白くすらなっていました。
ググって目についたものの安易なコピペをせず、一次情報をしっかり読んでできるかぎり理解しようと心がけたための苦労もありましたが、その分身に付いたものも多くあったと感じています。
英語でドキュメント読んだこと
上記でさんざん英語で読もう、みたいなことを勧めておりますが、やっぱり大変ではありました😢 DeepL がなかったらどうなっていたか…。
Ruby on Rails で作るという思い込み
フィヨルドブートキャンプにはエンジニアとしての力を身につけるためのプラクティスとして様々なカリキュラムが存在します。 カリキュラムは Linux のコマンドを作ってみたり、ボーリングのスコア計算プログラムを作ってみたり、さらにそれをオブジェクト志向でリファクタリングしてみたり、などなどです。 その際に利用する言語が Ruby となっており、基本カリキュラムは Ruby を使って進めていきます。また、Ruby on Rails 及び各種プラグインの使い方を学ぶというプラクティスもあります。
そのようにがっつり Ruby を学ぶコースであること、フィヨルドブートキャンプも Ruby コミュニティと密接な関係にあるあることから、自分の中でなんとなく自作サービスも Ruby on Rails で作るものだと思っていました。Ruby on Rails で自作サービスを作ることが今まで学んできたことの集大成となるとある意味思い込んでいました。
ですが技術選定の際、メンターの方とのやりとりで Srive の要件であれば Ruby on Rails は too much であり、Ruby on Rails で開発したからこその悩みやハマリポイントにはほぼ出会えないはず。そういった開発を経ても「自分の資産になる経験」は得られないのではないかという指摘をいただきました。
そのときのやりとりの詳細は https://github.com/ot0m1/Srive/issues/25 をご参考ください。 今冷静になって振り返るとだいぶ視野狭窄に陥っているな〜と感じます🤧
そういったご指摘をいただいき、色々自分の中で考えた結果 TypeScript + React + Next.js で作るという選択になりました。
TypeScript + React + Next.js 全部が初めてだったこと
TypeScript はまだしも、React と Next.js は全く触ったことがないところからのスタートだったので、何がわからないのかもわからないという状況でした。 技術書を数冊買って読んで、それぞれの公式サイトをひぃひぃ言いながらググりまくっていました。テストもどうやって書いていいか最初は検討もつきませんでした。
非同期処理の理解
上から順番に処理がひとつひとつ完了して進んでくれないというのが自分の中の直感と反しており、こういうことかな?となんとなく雰囲気をつかめるようになるまで大変でした。
コンポーネント間での状態の共有
Ruby on Rails だと @ をつけて変数を宣言するだでよさそうなところを、すごい複雑に書く必要があるのだなぁという感想でした。
この先 srive に対してやりたいこと
テストをもっと充実させられる箇所があるな〜と自分でも感じるのと、正直テストにまだ苦手意識があるのでその克服のためにもカバレッジを上げたいです。 Docker などの仮想環境を使ったテストにもチャレンジしたいところです。
最後に
フィヨルドブートキャンプのメンター、アドバイザーのみなさんには大変お世話になりました。ありがとうございました。