開発合宿第一弾!! オンライン合コンアプリを作った話
- 投稿者
- だいそん
コロナで自粛ムードが続くことはや数ヶ月、みなさんいかがお過ごしでしょうか。RUNTEQ事業部のだいそんです。
突然ですが、みなさん最近恋してますか?
東京都では毎日のように200人超えの新型コロナウイルス感染者が出ていますね。そんな中不要不急の外出をするのは憚られますし、ましてや合コンなんてできるはずもないですよね…
濃厚接触はしたくない、でも濃厚接触はしたい
この記事はそんな社会的な課題を解決するアプリを社内の開発合宿で作りましたよという内容になります。技術的なところにフォーカスしてお話します。
(開発合宿全体の概要は別ブログにまとめてあるのでもしよかったらこちらも読んでみてください!)
オンライン開発合宿の成果発表会を行いました! | 株式会社スタートアップテクノロジー
作ったアプリ
オンライン合コンアプリ 「Fall In Love」
アプリコンセプト
- オンラインで手軽に合コン
- オンラインならではのドキドキ💓ワクワク💘マッチング👨👩👦(お互い良いと思ってたらその旨が通知される)
なぜつくったか
- Withコロナ時代において合コンも形を変えていかなければならない
- 実際の合コンでこんな原体験があった
- (友人)『あの子お前のこと良いと思ってたらしいよ』
- (私)『まじかあぁじゃぁアタックしておけばよかったわ』
→ オンラインの合コンなら他の参加者にバレずに相手に好意を伝えられるのではないかという仮説
アプリデモ
「限りなく手軽に」をコンセプトとしていたので招待リンクを踏むだけでビデオチャットができるような仕様にしました。
「求愛コール」ボタンを押すとその相手だけに通知がいきます。 相手が「求愛コールに応える」ボタンを押すとカップル成立。二人だけでチャットができるようになります。
技術スタック
- SkyWay
- Firebase
- Firestore
- Nuxt.js
- Vuetify
- Netlify
Skyway
複数人でのビデオ通話を実現するためにSkyWayを使いました。 SkyWay | アプリやWebサービスに、ビデオ・音声通話をかんたんに導入・実装できるSDK
ドキュメントと公式のサンプルコードを元に作りました。 Javascript SDK | ドキュメント | SkyWay(アプリやWebサービスに、ビデオ・音声通話をかんたんに導入・実装できるSDK)
skyway-js-sdk/examples/room at master · skyway/skyway-js-sdk
詰まったところ
ユーザー同士でメッセージをしたりLoveをしたりというアプリの性質上、ユーザーを識別できないといけません。 さらに、ビデオチャットルームに何回出入りしてもLoveの状態などを引き継ぐために同じユーザーとして識別されないといけません。 従ってSkywayにより生成されるオブジェクト(= Stream)に何かユニークなものを設定させる必要がありました。
ドキュメント通りにPeer
(通信拠点の単位となるオブジェクト)を作成するとpeerIdがランダムで発行されるのでビデオチャットルームに入り直すと別のIDとなってしまいLoveの状態などを引き継ぐことができません。
ソースを読むと Peerの生成時に独自の値を設定できるようでその仕組みを活用することにしました。(this.userId
の部分)
this.peer = new Peer(this.userId, { key: "hoge-key" })
こうすることで何度ビデオチャットルームに出入りしてもユーザーを特定することができるようになりました。
Firebase
チャットの機能を用意する必要があったのでFirestoreを利用しました。 可能な限りシンプルに使えることを意識したのでAuthenticationは利用してません。
詰まったところ
ドキュメント設計に苦労しました。 最終的にFirestoreのデータ構造はこんな感じになりました。
// ルームコレクション
rooms: {
"room0001": {
// ユーザーサブコレクション
users: {
"user0001": {
name: 'だいそん',
likeUsers: ["user0002", "user0003"], // 配列
likedUsers: ["user0002", "user0004"] // 配列
// ↑ 要はウィリアンとは両想いだけど加藤さんへは片思い
// 逆に井上さんの好意には応えられず。
// LIKEボタンを押したタイミングで自分のユーザーのlikeUsersとLIKE対象のユーザーのlikedUsersを更新するイメージ
},
"user0002": {
name: 'ウィリアン',
likeUsers: ["user0001"],
likedUsers: ["user0001"],
},
"user0003": {
name: '加藤'
},
"user0004": {
name: '井上'
}
},
// 部屋全体のメッセージサブコレクション
messages: {
"message0001": {
content: "だいそんだよ!!!",
name: "だいそん",
createdAt: "2020-05-10 10:00"
},
"message0002": {
content: "うぃりあんだよ!!!",
name: "うぃりあん",
createdAt: "2020-05-10 10:00"
}
},
// プライベートメッセージのサブコレクション
privateMessages: {
"message0001": {
content: "君かわウィーね!",
name: "だいそん",
member: {
user0001: true,
user0002: true
}
},
}
}
}
RDBではありえない設計がNoSQLだとありえます。 e.g. - Message(部屋全体のメッセージ)とPrivateMessage(個人間のメッセージ)を分けた - LikeUser(いいねした人)やLikedUser(いいねしてくれた人)を配列で持たせる - Messageドキュメントに送信者の名前なども冗長的に持たせる
などなど。もちろんこれがベストではないとは思うのですが一応やりたいことは実現できました。
感想
実装期間的にはトータル1人日くらいだったと思います。 実はこのアプリが最優秀賞をいただいたのですが、技術的には特段新しいものでもないのでアイデアで優勝をもぎ取ったようなものですね。 普段Railsばかり触っていますが、こういったモックレベルのものであればFirebaseは爆速で作れるなーと改めて実感しました。 これをRailsでやろうとすると1人日では済まないと思います。また、非機能要件的なところでいうと同時上限接続数なんかもActionCableだと結構厳しめだった気がしますが、Firestoreでは1,000,000と実質無限です。実際デモでも一気に15人くらい繋いでもちゃんと機能してたのはFirebaseさんさすがという感じでした。
個人開発ではもちろんのこと業務においてもFirebaseを使えるところは使っていきたいなと思いました。
もしこちらのアプリを自社プロダクトとして使ってみたいという方がいればお気軽にご連絡ください!笑