2019-02-28に更新

WEBサービスの通知機能実装が面倒すぎるので困った

先日Crieitにコメント機能を付けました。そうなると必要になってくるのが、通知機能です。

記事を投稿した人はコメントがついたら通知が欲しいでしょうし、コメントした人も自分のコメントに返信が来たり、同じ記事にコメントがついた場合にはすぐに見たいと思いますので通知が欲しいはずだからです。

通知機能の選択肢

WEBサービスに通知機能を実装する場合、現在だと大まかにふた通りのやり方があると思います。

メール通知

昔からある一般的な方法です。一番無難な方法でもあると思います。通知メールを残しておけば何の通知だったかあとでも確認できますし、メール通知機能さえあれば必要最低限はまかなえると思います。

PUSH通知

FCMを利用したPUSH通知です。メールとは違い、端末に通知が来て直接アプリケーションの画面が開けるため、スピード感がありWEBサービスには向いています。

どちらがいいのか?

最終的には両方の通知機能を実装することでしょう。ただ、個人でWEBサービスを作っている場合や、スタートアップなどがスモールスタートする場合などは何でもかんでも最初から実装しておけばいいというわけではありません。

サービス的に両方絶対必要、ということであれば仕方ないですが、時間に限りがありますし通知機能の実装は非常に面倒ですので、絶対必要でなければどちらかの通知機能に絞った方が良い場合もあると思います。

どちらにどういうメリットがあり、どちらがどれだけ面倒か考えていきます。

メール通知

メール通知のメリットは前述の通り、とりあえず作っておけば最低限大体のことは満たせるということです。ただ、実装方法は色々ありますが、結構面倒な点もあったりします。

サーバー上のメールサーバーを用意する場合

Postfix等を使えば特に外部サービスを利用しなくてもメールを送信することができます。ただ、自分で設定をしなければならないので面倒です。一回くらいなら自分で頑張って設定しようかと言う気にはなるのですが、もしもう1台増やすか、ということになった時などにまた同じ設定をしなければならないのかと思うとうんざりします。

僕は仕事上インフラ周りも触ることはありますが、メールサーバーは正直必要最低限は最初から送信できたりすることもあり、WEBサーバーやDBの設定に比べて扱う頻度が低く、大体次触る頃にはほとんど設定方法を覚えていません。そのためネットで調べながら設定することになり、時々つまづくこともあるのでかなり面倒です。

特に普段サーバー環境構築をしない人からするともっと大変だと思います。例えば下記の記事に設定が書いてありますが、長い設定画面が出てきたあたりで読む気すら起こらなくなると思います。
Ubuntuでメールサーバー構築

メール送信サービスを利用する場合

上記の理由から、SendGridやMailgunメールサービスをつかってメール通知を実装するともっと楽になります。色々と機能もついており非常に便利です。ただ、これはこれでいくつか問題があったりします。

送信数制限

送信数制限があるため、多く送ると費用がかかるようになります。例えばSendGrid等は現在月12000通です。

さすがにそれなら超えないんじゃないか? と思いますが、1サービスではなく1アカウント毎の制限になりますので、いくつもサービスを作っていて、ある程度メールを送信するしている場合はわりと超えてしまうのではないかと思います。

今は良いけど今後サービス新しく作る場合にどうしようか? と悩むこともあると思います。

リレー方式の場合はダメな場合がある

僕が愛用しているGCEもそうですが、ポートに制限がかかっている場合があり、リレー方式の送信方法だとブロックされてしまい送信できません。マニュアルはありますがこれもちょっとうんざりする系です。
SendGrid でのメールの送信

API方式がいい

API方式は良いです。一番簡単だと思います。ただ、言語によってはなぜかリレー方式しか使えないライブラリがあったりするので、このあたり気をつけないとローカル環境では動いたのに本番では送信できないとなりますので気をつけましょう。

あとはどの方式にも言えますが、DNSでSPFの設定をちゃんとやっておく必要があります。これをやっておかないとスパムメール扱いされてしまう事が多いです。メールサービスであればマニュアルに書いてあることも多いと思います。

WEB PUSH

FCMを利用したWEB PUSHによる通知です。スマホなどで通知を受け取り、すぐに目的のURLにアクセスできるため、サービスにユーザーを頻繁に呼びこむのに優れています。

単にユーザーに通知を送るだけでなく、トピックを作っておいて、そこにユーザー端末を登録してトピックに通知を送ると登録されているユーザー全員に通知を送ることができる、などもあり、非常に便利です。(もちろん、そのあたりの登録、解除の仕組みなどもちゃんと作らないといけません。自前のDBに保存しておく必要もあります)

通知の履歴が残らない問題

通知の履歴が残らないため、通知を消してしまったり、通知からサービスにアクセスしても一旦どうでもよくて離脱し、再度気になった時にアクセスできない、といった問題が出てきます。(実際にはスマホには履歴が残っているのですが、見るのも面倒で知らない人も多いと思います)

そのためサービス側に独自の通知履歴を作らなければなりません。

独自の通知の実装

独自の通知の実装ですが、これがまた面倒です。というのも、通知というのは色々なところで発生します。例えばフォローしているユーザーやカテゴリに何かが投稿されたり、自分の投稿にコメントがついたり。

つまりDBの構造として単純なbelongsToで作ることができません。通知自体はあまり他のところで使われるものでもないのでpolymorphicであれば割とシンプルに困ることなく作れるかもしれません。何にしろ条件分岐にしろ、関連モデルに共通のメソッドを用意するにしろ、やることは増えるので面倒なのは面倒です。

元はといえば単にユーザーに最低限の通知をしたかっただけのはずなのに…。

フロントとの連携の問題

単に通知一覧を実装するだけであれば問題ないのですが、WEBサービスのヘッダ部分に新着通知アラートをだしたりすることになるとまた面倒なことになります。どこまで閲覧済みかという情報を保存しておかなければならないからです。

フロントエンドと連携する場合、ユーザーの確認とDBの更新のタイミングが必ずしも同じではなくなるため、適当に作ったりするとまだ確認していないのにある一瞬のタイミングで全ての通知を確認済みにしてしまって新着通知が消えてしまったり、逆にフロント側では新着確認済みになったのにリロードするとまた新着が復活してしまう、ということが発生したりします。

Facabookもこの不具合が多く非常に困ったため、Fluxを提唱したという話をどこかで見ました。ほんとに通知機能というのはやっかいなシロモノです。

個人のWEBサービスなら良いのですが、もし仕事でするとなると仕様策定側が便利にしたいと思ってあれこれ勝手に決めてしまうこともあるので大変そうです。

周辺機能の実装

通知を作るとなると、周辺にも色々と機能を実装する必要が出てきます。これも非常に面倒です。元はといえば単にユーザーに最低限の通知をしたかっただけのはずなのに…。

  • トピックやユーザーなどにウォッチ機能、もしくは通知解除機能を実装する必要がある
  • ユーザーの個人設定に一般的な通知許可設定を実装する必要がある、もしくはここにも分類毎の許可設定が必要

まとめ

こんな感じで、単に通知機能を作りたいだけのはずなのですが、周辺部分も含めると結構工数がかかってしまい、なかなか厄介です。考えれば考えるほど、こだわればこだわるほど色々できてしまう箇所ですので、いかに絞って仕様を策定するかは非常に重要になると思います。
(メールサービス関連はざっと調べただけですので誤っている情報もあるかもしれません。検討される際は実際に確認してください)

記事を書きつつ気持ちを落ち着けて考えてみましたが、CrieitとしてはとりあえずSendGrid等のAPI送信で試そうかなと思います。一応公式のライブラリの方はAPI方式っぽいので。(SendGrid公式のLaravelやRailsのサンプルはリレーっぽいのでなんか不親切な感じがします)

…と決めたら決めたでまた悩む…。

追記)
FCMにする。

追加)
結局メール(API)も入れました。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント