モバイルアプリケーションへのPush通知を行う際に考慮すること

## 概要
バックエンドアプリケーションの開発をしていて、モバイルアプリ(今回はiOS)へPush通知を行う要件があった際に考慮したことをまとめました。検討した方法は以下の3つです。

1．APNsに直接送信する
2．Azure Notification Hub を使用する
3．Amazon SNS を使用する
4．Firebase Cloud Messaging(FCM) を使用する

それぞれ、手順とメリット・デメリットを以下の通りまとめました。なお、メリット・デメリットとも**バックエンドアプリケーション開発者側**の視点で記載しています。バックエンドアプリケーション側での実装・運用のしやすさを考慮しています。

## 前提
- モバイルアプリケーションは開発済みとする
- APNsの証明書/認証トークンは取得済みとする
- iOSにPush通知を行うための、Azure Notification Hub、Amazon SNS、FCMの設定は済んでいるものとする

## APNsに直接送信する場合

```mermaid
sequenceDiagram
	participant モバイルアプリ
	participant バックエンド
	participant APNs
	alt アプリ起動時
        モバイルアプリ ->> APNs: デバイス登録リクエスト
        APNs ->> モバイルアプリ: デバイストークン発行
        モバイルアプリ ->> バックエンド: デバイストークン登録
        バックエンド ->> バックエンド: デバイストークン保存
	end
	alt 通知発生時
		バックエンド ->> バックエンド: 対象のデバイストークン検索
		バックエンド ->> APNs: Push通知の送信（with device token）
		APNs ->> モバイルアプリ: Push通知
	end
```

### メリット
- システム構成がシンプルになる
- 他サービスのコストがかからない
- 実装の自由度が高い

### デメリット
- デバイストークンの管理をバックエンド側で行う必要がある
- APNs証明書や認証トークンの管理・更新をバックエンド側で行う必要がある
- セグメンテーション・ターゲティング・スケジューリングなどPush通知の高度な機能を独自に実装する必要がある

## Azure Notification Hub を使用した場合

```mermaid
sequenceDiagram
	participant モバイルアプリ
	participant バックエンド
	participant Azure Notification Hub
	participant APNs
	alt アプリ起動時
	    モバイルアプリ ->> APNs: デバイス登録リクエスト
        APNs -->> モバイルアプリ: デバイストークン発行
		モバイルアプリ ->> Azure Notification Hub: デバイストークン登録
	end
	alt 通知の登録時
		Note right of バックエンド: Tagはバックエンドでマスタ管理
		バックエンド ->> モバイルアプリ: Tag取得
		Note right of モバイルアプリ: 例：tag:favorite_beatles
		モバイルアプリ ->> Azure Notification Hub: Tagの登録
	end
	alt 通知発生時
		バックエンド ->> Azure Notification Hub: Push通知の送信（with Tag）
		Note right of バックエンド: 例：favorite_beatles
		Azure Notification Hub ->> APNs: Push通知の送信（with device token）
		APNs ->> モバイルアプリ: Push通知
	end
```

### メリット
- Azure Notification Hubの機能により、テンプレート・セグメンテーション・ターゲティング・スケジューリングなどPush通知の高度な機能を利用できる
- APNs証明書や認証トークンの管理・更新をバックエンドアプリケーション側で行う必要が無い
- デバイストークンの管理をバックエンドアプリケーション側で行う必要が無い

### デメリット
- Azure Notification Hub のコストがかかる([料金表](https://azure.microsoft.com/ja-jp/pricing/details/notification-hubs/#pricing))
- Azure に依存するため、サービスの停止や問題が発生した場合、通知が送信されない可能性がある

## Amazon SNS を使用した場合

```mermaid
sequenceDiagram
	participant モバイルアプリ
	participant バックエンド
	participant Amazon SNS
	participant APNs
	alt アプリ起動時
	    モバイルアプリ ->> APNs: デバイス登録リクエスト
        APNs -->> モバイルアプリ: デバイストークン発行
		モバイルアプリ ->> Amazon SNS: デバイストークン登録
		Amazon SNS -->> モバイルアプリ: EndpointARN 返却
	end
	alt 通知登録時
		Note right of バックエンド: SNS topic はバックエンドアプリケーションでマスタ管理
		バックエンド ->> モバイルアプリ: SNS topic取得
		Note right of モバイルアプリ: 例：topic:favorite_beatles
		モバイルアプリ ->> Amazon SNS: TopicのSubscribe登録
	end
	alt 通知発生時
		バックエンド ->> Amazon SNS: Push通知の送信（Publish To Topic）
		Note right of バックエンド: 例：topic:favorite_beatles
		Amazon SNS ->> APNs: Push通知の送信（with device token）
		APNs ->> モバイルアプリ: Push通知
	end
```
### メリット
- Amazon SNSがAPNsやFCMなどのPush通知サービスとのインターフェースを提供しているため、バックエンドアプリケーション側ではPush通知サービスの設定・管理を行う必要がない。
- デバイストークンへの直接送信ではなくTopicへのPublishを行えば、デバイストークンをバックエンドアプリケーション側で保持・管理する必要がなくなる。
- Push通知以外にも、Email、SMSに対応している


### デメリット
- Amazon SNSのサービス利用料が発生する。([料金表](https://aws.amazon.com/jp/sns/pricing/))
- AWS に依存するため、サービスの停止や問題が発生した場合、通知が送信されない可能性がある
- Azure Notification Hubに比べ、テンプレートやスケジュールの機能が限定的

## Firebase Cloud Messaging(FCM) を使用した場合

```mermaid
sequenceDiagram
	participant モバイルアプリ
	participant バックエンド
	participant FCM
	participant APNs
	alt アプリ起動時
	    モバイルアプリ ->> APNs: デバイス登録リクエスト
        APNs -->> モバイルアプリ: デバイストークン発行
		モバイルアプリ ->> FCM: デバイストークン登録
		FCM -->> モバイルアプリ: FCMトークン 返却
	end
	alt 通知登録時
		Note right of バックエンド: topic はバックエンドアプリケーションでマスタ管理
		バックエンド ->> モバイルアプリ: topic取得
		Note right of モバイルアプリ: 例：topic:favorite_beatles
		モバイルアプリ ->> FCM: TopicのSubscribe登録
	end
	alt 通知発生時
		バックエンド ->> FCM: Push通知の送信（Publish To Topic）
		Note right of バックエンド: 例：topic:favorite_beatles
		FCM ->> APNs: Push通知の送信（with device token）
		APNs ->> モバイルアプリ: Push通知
	end
```
### メリット
- FCMはAndroidにPush通知するためには必須であり、iOSへのPush通知の機能ももっているため両者へのPush通知を共通のインターフェースで送信できる
- TopicへのPublishを行えば、FCMトークンをバックエンドアプリケーション側で保持・管理する必要がなくなる。
- 無料([料金表](https://firebase.google.com/pricing?hl=ja))


### デメリット
- Firebase(Google) のプラットフォームに依存するため、サービスの停止や問題が発生した場合、通知が送信されない可能性がある

## まとめ
証明書類の管理運用や、デバイストークンのような個人情報あるいはそれに準じる情報の保持はできる限りバックエンドアプリケーション側で行いたくないものです。
AWSやAzureのサービスに外出しできるのなら、証明書の管理運用はクラウドサービスを管理している部署・チームに任せることができるでしょうし、個人情報の管理についてもクラウドサービスの利用ポリシーとして策定されているであろうセキュリティ対策に任せることができます。
もちろんクラウドサービスが持っている高度な機能を簡単に利用できることも大きな魅力ですが、上記の課題の解決によりバックエンドの開発者が抱える負担を軽減でき、より本質的な価値に集中できるようになることが最も大きなメリットであると考えます。
(個人的には、好きに選んでいいよと言われたらFCMかと思いますが、会社・プロジェクトにより様々な制約の中から選択することになると思います。)