サーバレスなオンラインじゃんけんアプリを作ってみた
Motivation
ソリューションアーキテクトを目指しながら日々業務に励んでいるエンジニアのSioです。最近は仕事でプロジェクト管理をするようになり、コーディングをする機会がなくなってしまい、修練の場を求めて自分で開発してみることにしました。ちょうど、AWSの資格勉強もしていたので、クラウドを使ったサーバレスなアプリケーションを作ってみようと思い、簡単なゲームを作ってみることにした結果、タイトルの通り、オンライン対戦ができるじゃんけんアプリをつくることにしました。
しばらく開発から離れていたことや、YouTubeで見た海外のエンジニアのソリューション設計を真似して全体のブループリントを作ってみたりして、思いの外時間がかかってしまったのですが、その分学びも多かったので、テーマごとに記事を分けてアウトプットしてみました。
オンラインでじゃんけんができたところで遊ぶ人もいないと思うので、とりあえず動けばOKというレベルでの実装にとどめているので、セキュリティとかあまり考えていない設計になっているので、そこは次回の宿題としたいと思います。
作ったサービス
今回は「オンラインじゃんけんアプリ」ということで、その名の通り、オンラインで誰かとリアルタイムでじゃんけんができるアプリを作りました。こだわりポイントを紹介すると、
- サーバ側はAWSを使ったサーバレスな設計
- AWS CDKを使ったIaCの実践
- クライアントーサーバ間はWebsocketで繋いで双方向の通信を実現
- 対戦中はそれぞれのクライアントで同期をとって状態を管理
- クライアント側でWebsocketをReactで使用
という感じになります。Motivationで書いた通り、海外のエンジニアを真似て、まず全体概要を描いてからそれぞれのコンポーネントを設計するという実際の仕事の流れを意識した開発の進め方にしました。
今回作成したソースコードは下記のgithubで管理しています。
backend(AWS CDK, nodejs)
frontend(reactjs)
完成までにどれくらいかかったか
構想を練り始めてから動くアプリが完成するまでに約2ヶ月かかりました。
じゃんけんなんて簡単に実装できるだろうとたかをくくっていたのですが、初めて実装するWebsocketや久しぶりのReactなどに苦戦して、思いの外時間がかかってしまいました。特にWebsocketを使った部分のサーバとクライアントの連携処理の設計などは初めてでしたので調べながら進めていたこともあり、多くの発見がありましたね。
振り返り
この記事では、全体的な振り返りをしようと思いますので、詳細は「個別テーマの振り返り」として別記事にしました。技術的な課題解決などはそちらにまとめようと思います。
どんなふうに進めたか
いつも趣味で開発する時は、いきなりVScodeを開いて、思いのままにコーディングするところから始めてみるのですが、今回は実践を意識して以下の流れで開発を進めました。
- テーマ決め:「オンラインでじゃんけんができるアプリ」というテーマを決める。
- 要件整理:アプリに必要な機能や想定ユーザ数・必要性能、アーキテクチャの検討(コンポーネントの全体配置、API、DBの整理)を行う。
- 設計(サーバサイド):使用するAWSのサービスと配置、接続構成の検討。サーバ側の処理の詳細についての設計を実施。
- 設計(クライアントサイド):使用する言語やフレームワーク、画面や状態遷移の整理を実施。
- 検証:今回初めて使ったり、慣れていない技術要素の検証を行い、使い方に習熟する。
- 実装:設計に従ってコーディングを実施する。※必要に応じて3,4の設計に戻ったり、5の追加の検証を実施。
- 振り返り:開発で得た知見をまとめる
実際の仕事でも同じような流れで開発が進んでいくと思うのですが、個人開発でやってみたのは初めてだったので慣れないところや難しいところも多くて結構大変でした。その難しかったところと、次回への教訓を残したいと思います。
① 不慣れな技術要素は適切な設計の段階的詳細化が難しい
今回は自分の慣れている技術だけを使うのではなく、要件に従って必要な技術やサービスを使うことにする方針にしました。先ほど説明した通り、設計を段階的に詳細化していくことで、全体の整合性をとりながら実装に着手できるように進めていました。ただ、その中で仕様に詳しくないサービスだったり、実装上の制約に詳しくない技術要素がいくつかあったので、その部分については検証や実装を経て見直しをする必要がありました。
具体的には、websocketとSQSについて最初にイメージしていたものとは違っており、後から設計の手直しをしました。
websocketについては、socket.ioのようなpub/subパターンができるイメージでいたのですが、実際に使ってみると、API Gatewayで作れるwebsocket APIではそういう仕様がなく、アプリケーションの設計に組み込む必要があり、その部分は追加で設計することになりました。
SQSについては、業務でMQを使っていたので、条件を指定したメッセージの取得ができるのではないかと思っていたのですが、そういう仕様はなくてMQと似ているようで別のものだったので、そこが設計上の制約になりました。
なので、最初に作成したアーキテクチャは、最後まで変える必要がないのではなく、情報が集まってくるにつれて必要に応じた修正を行う必要があるということがわかりました。
教訓
初期段階で完璧なアーキテクチャを作成することはできないので、必要に応じて見直す必要がある。見直す理由は、技術要素の仕様の理解不足だったり、把握できていない設計制約が顕在化する時であるため、可能な限り情報収集を行うことと、調べきれない部分は仮定としてまとめておくこと。
アーキテクチャ作成段階では、仕様や主要な設計制約を抑えておき、設計が進むにつれて適宜見直しを行う。
② 検証で色々試していたら時間が足りなくなる
設計や実装上で課題があるときに、それを解決するために5.検証を行うのですが、色々試すことは結構楽しくて、気がついたら半日経っていたなんてこともあるあるです。今回も検証していたら色々試してみたくなってあっという間に1日が終わるということもありました。学習という点で言うとそれで問題ないのですが、一方で早くアプリを完成させたいという思いもあり、前に進むことと知識を広げることのバランスを取る必要があります。それに、色々試してみたけど当初知りたかったことがわからなかったということは避けたいので、ある程度計画を持っておくべきだと思いました。
教訓
検証する時は、先に何を知りたいのかを明らかにしておくべきですね。当たり前のことではあるのですが、色々調べているとどんどん横道に逸れていってしまうことが多々あるので、参考文献もどこまで見るべきなのかということを判断する必要がありますね。そのために、最初に「これを知る」ということを決めておいて、それに関係あれば深掘りしてそうではなければブックマーク保存で後から見返すようにするという仕切りを入れる必要があると思いました。特に土日しか開発できる時間がない場合は、検証よりも実装に時間を使いたいですからね。重要なことです。
個人開発に限らず、仕事でも目的のない検証はすべきではないので、常に気を付けておかないといけないことなんでしょうね。
その他個別テーマの振り返り(技術的な振り返りはこちら)
準備中(後で更新)
- AWS API Gatewayのwebsocket APIでできることとできないこと
- AWSサーバレスアプリの構成管理方法(Lambdaのソースコードをまとめて管理する)
- 時間制御を伴うサーバからのクライアントの状態管理の実現方法
まとめ
久しぶりの個人開発で、忘れている文法を思い出したり、新しいSDKの使い方を習得したりすることで時間がかかってしまいましたが、一つのアプリを完成させることで多くの知識が身についたし、何かを作る感覚というのを思い出すことができました。今後も個人開発を継続していくことで、もっと良い設計ができたり、実装の時間が短縮できたりするのではないかと思いましたね。
次は、より実用的なサービスを考えたいのと、公開することを念頭にしたセキュリティ対策なども考えていきたいと思います。学んだことをアウトプットするということも続けていきたいと思います・
Discussion