iOS開発から見るcluster

この記事は [クラスター Advent Calendar 2021](https://qiita.com/advent-calendar/2021/cluster) 14日目の記事です。
昨日は、[yoshioka_ko57](https://zenn.dev/yoshioka_ko57) さんの、「[デザインデータの読み解き](https://zenn.dev/yoshioka_ko57/articles/understand_design_data)」 でした。普段やり取りさせてもらっているデザインデータですが、データの節々から様々な工夫や配慮を感じながら日々作業させてもらっています。圧倒的感謝:pray:

こんにちは。クラスター株式会社でソフトウェアエンジニアをしている橋本です。今年も残すところ半月ほどとなりましたが、みなさまいかがお過ごしでしょうか。私は、この残り半月という事実を到底受け入れられそうにありません...:innocent:

さて、[モバイル版clusterのアプリ](https://apps.apple.com/app/id1490075175?mt=8&l=ja)の[outroomがネイティブ化](https://note.com/cluster_official/n/n764ffc8cf06b?magazine_key=m2977d6e59c50)されてから1年と少し経ちました。この1年の間にどのようなiOSの開発が行われてきたかをお話していきたいと思います。

## 組織の話
clusterアプリはWindows（+VR）、Mac、iOS、Androidそして最近リリースされたQuest2と様々なプラットフォームをサポートしていますが、クラスター株式会社でプラットフォームを開発しているのは現在24人ほどです。その中でiOSエンジニアは3人で、それぞれがUnityなど他の領域と兼務しつつ日々機能開発を行っています。

iOSの開発でこの1年で特に大きく変わったことは、iOSエンジニアのが1人増えたことです！！めでたい！！いつもお世話になってます:pray:

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">バーチャルSNSを運営しているクラスター社に入社しました！<br>バーチャル世界の発展に向けてやっていきます！<a href="https://t.co/U2ZKXNE62g">https://t.co/U2ZKXNE62g</a></p>&mdash; izumi (@rizumi_jp) <a href="https://twitter.com/rizumi_jp/status/1366539836639694849?ref_src=twsrc%5Etfw">March 2, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## iOS開発のアーキテクチャの話
さっそくですが、clusterのネイティブ開発がどのように行われているのかをざっくりですが紹介していきたいと思います。まずはこちらの概要図を御覧ください。
![スクリーンショット 2021-12-14 3.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117102/e24308c2-3eef-e4b4-2890-52f90c0f6d7f.png)
clusterはワールドやイベント入室前の`outroom`と入室後の`inroom`[^1]という大きく2つ領域に分かれていて、それぞれが(ほぼ)独立して開発されています。この独立性は[UnityのUaaLという機能](https://qiita.com/mizoguche/items/09719bb1ea3c3265dcdc)を使うことで実現しています。その中でも今回は`outroom`側(iOS開発)の話をメインにしていこうと思います。※上の図はinterfaceへの依存などは省略しているのであしからず。

まず、clusterのiOS開発では[MVVM](https://ja.wikipedia.org/wiki/Model_View_ViewModel)をGUIアーキテクチャとして採用しています。このアーキテクチャの採用理由としては、（今では）ネイティブアプリ開発でメジャーなアーキテクチャであることや、[Android側](https://qiita.com/kyokomi/items/67bf126ec0398bc81853)と同じようなアーキテクチャをとることで、iOSとAndroidお互いのコードベースを参照しやすくするからと言った点があります。また、画面遷移は[Coordinatorパターン](https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps)を採用していて、Deeplinkや通知機能など様々な起動経路からの画面遷移に強い作りになっています。

その他の採用技術としては、データバインディングに[RxSwift](https://github.com/ReactiveX/RxSwift)、オブジェクトの永続化に[CoreData](https://developer.apple.com/documentation/coredata)、ApiClientの生成に[openapi-generator](https://github.com/OpenAPITools/openapi-generator)が使われています。まだ一部分ではありますが、CollectionViewのCellに[SwiftUI](https://developer.apple.com/jp/xcode/swiftui/)を使ったりと、技術的なチャレンジもこの1年の間に行っています。また、`outroom`や`inroom`のやりとりを担う`Bridge`部分では[Protocol Buffers](https://developers.google.com/protocol-buffers)を使用しているのはユニークな点かなと思います。以上でざっくりとしたアーキテクチャや採用技術の説明は終わりになりますが、続いて具体的な機能開発の事例の紹介に移りたいと思います。

## 機能開発の話
clusterではこの1年で[様々な機能がリリース](https://note.com/cluster_official/m/m2977d6e59c50)されてきました。特に`outroom`開発では[メッセージ機能](https://note.com/cluster_official/n/nf4af2d5e7f31?magazine_key=m2977d6e59c50#3Zwuq)をはじめとした、ソーシャル機能や`inroom`との連携を生かした、[PictureInPicture風の機能](https://note.com/cluster_official/n/n8e95d8fd9b37?magazine_key=m2977d6e59c50#MFc8T)[^2]や、それを用いた[ポータル設置機能](https://note.com/cluster_official/n/n8e0e3a4f6769?magazine_key=m2977d6e59c50#8LO1Z)や[新規サーバー作成機能](https://note.com/cluster_official/n/n2878d9062123?magazine_key=m2977d6e59c50#a4ec7f04-25d0-4ece-b527-27c37a5369a9)などをリリースしてきました。他にも、[ナビゲーションメニュー](https://note.com/cluster_official/n/n0479ae928a2f?magazine_key=m2977d6e59c50)などの基本的な機能郡をはじめ、[ClusterRound](https://note.com/cluster_official/n/nf26e8bdb498f)の対応など様々な改善が行われています。ここでは、PictureInPicture風の機能開発を中心に詳しく話していこうと思います。
![スクリーンショット 2021-12-14 0.46.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117102/ccd0c48f-03b4-5abd-b236-505668b3a14d.png)
この機能を使うと、cluster内のワールドやイベントに参加しながら、次にいきたいワールドやイベントを探したり、探したワールドにみんなで行くためのポータルを今いるワールド内に設置したりすることができるようになります。具体的にどのような実装になっているかというと、`inroom`側から「PictureInPictureを開始して」というメッセージを前述の`Bridge`を経由して`outroom`側で受け取ると、`outroom`側でUnityが描画している画面をもっている`UIWindow`を任意の形に変形させることで、PictureInPicture風の画面を実現しています。また、PictureInPicture風の画面をスワイプして移動させたりするのも`outroom`側の実装が担っています。

このように例に上げた実装はとてもシンプルですが、基本的に`outroom`側の実装は`Swift`で書かれていて、3DCGやUnityの知識があまりなくても、`スマホからも参加できるメタバース`のユニークな機能を開発することができるということがわかるかと思います。メタバースはあまり関係ないなと思われていた世のiOSエンジニアのみなさんに、「clusterにはメタバースの世界を加速させるような活躍をする場所がたくさんあるよ」ということを知ってもらえたら幸いです。

## さいごに
clusterでのiOS開発の雰囲気が少しでも伝わったでしょうか？体力の都合上かなりざっくりとしたことしか書けませんでしたが、もし興味があるよ！って方がいましたら[採用ページ](https://www.wantedly.com/projects/533956)を見てもらえればと思います。

次回の [クラスター Advent Calendar 2021](https://qiita.com/advent-calendar/2021/cluster)は[alert](https://qiita.com/194_alert)さんの「ワールド紹介動画の撮影について」です。クラスター社にはバーチャルプロカメラマンが何人かいますが、どんな内容になるか楽しみですね...!

[^1]: outroomとinroomは社内用語です
[^2]: [AVKit](https://developer.apple.com/documentation/avkit)のPictureInPictureの機能を使っているわけではないので、`PictureInPicture風`としています