Discord RSSフィードBot開発記
投稿日 October 3, 2025 • 1分で読めます • 76文字 • 言語を選択: Korean、English
Table of contents
なぜDiscord Botを作ったのか?
やや唐突だが、様々なニーズが重なって、私は複数の大手テック企業の技術ブログフィードを取得してくれる**「フィードニャン」**を開発することにした。ニーズとは以下の通りだ。
- Ktor + Exposedの組み合わせでWebアプリケーション開発を経験してみたかった。
- Claude Codeを初めて使ってみようとした。
- 技術ブログを継続的に書かなければという必要性を強く感じた。
何を作ろうか悩んでいたところ、ブートキャンプで知り合った知人がDiscord Botを作ると言っていたので、私も軽く作ってみたくなった。軽く開発できる開発範囲、今まで経験したことのないDiscord Botという新しい開発領域、そして実際のユーザーを経験できるという点が私をフィードニャン開発へと導いた。
適正アーキテクチャとは何か?
しかし開始するやいなやKtor + Exposedの組み合わせは除外することにした。AWS EventBridgeスケジューリングを通じてLambda関数を呼び出すサーバーレス構造がコスト削減の面でも効率的で、常に実行されている必要もないロジックなので妥当でもあった。そうしてサーバーレスの観点から見ると、JVM系言語のLambda cold start問題が負担に感じられた。そこでKtor使用体験を諦めて、サーバーフレームワークのないシンプルな関数を作ることにした。
結論から言えば、単に経験してみたかった技術スタックよりも、技術ブログフィードBotを開発するのに最も適した適正アーキテクチャを最優先に考慮することにした。軽いプロジェクトでもそれに合った適正技術を選択するコツを身につけておくことが、今後も良い影響を発揮するのではないかと思った。
Lambdaを構成する言語としてはGo言語を採用した。TypeScriptもまずまずの性能を持ち、開発経験もあるが、バンドリングとトランスパイリングの過程を経なければならないという点から、最近は避けている。そこで軽くて速い性能を持つGo言語で開発を進めることにした。
そしてMongoDBを採用して、チャンネルに登録されたフィードリストを確認し、最後に送信したフィード情報を登録して重複送信を防止する用途で使用した。DynamoDBも少し考えてみたが、無料のMongoDBのM0クラスターの方がはるかに魅力的に感じられた。
IaCツールとしてPulumiを採用した。以前の会社で使っていたAWS CDKはCloudFormationと強く結合している感じで、真の意味でのIaCとは言いにくいと感じた。そこで思い切って初めて使うIaCツールをいきなり導入した。使ってみると確かにAWS内のサービスのみ構成できるCDKとは異なり、MongoDBクラスターのようなコンポーネントも一緒に構成できるという点が大きなメリットに感じられた。
最後にClaude Code、AI Agentの初体験をしてみたいというのが今回のシンプルなプロジェクトを始めた主な動機だったので、欠かせない要素だ。確かに初めて使うPulumiに慣れるのにも大いに助けられ、discordgoのようなライブラリもハードルなく自然に活用できた。
シンプルなアプリにも設計過程が必要だ
実は最初はスケジューラー + Lambdaでシンプルに実装できると思っていた。しかし突然コマンドをサポートすべきではないかという欲が出てきた。固定のフィードリストを一方的に送信するよりも、フィードリストを追加・削除し、現在のフィードリストを確認できるコマンドがあれば、確かに相互作用も可能なBotとしての意義を持てると思った。
こうなったからにはアーキテクチャダイアグラムくらいは描いてから進むことにした。今回の機会にシンプルなプロジェクトを作る場合でも、簡単な設計案くらいは作成してから進む方が考えの整理にも役立ち、開発範囲を確定できるので、むしろ時間をかなり短縮するプロセスだということに気づいた。
また思い切ってMongoDBを導入したが、実は初めて使うものだった。そこでMongoDBスキーマも一度整理してから進むことにした。ドキュメント型NoSQLを活用するためのスキーマはどのように設計するのが良いだろうか?さあ、まだよく分からない。まるでJSONを設計するようにDiscordチャンネルごとにフィード情報をまとめる方式にしてはおいたが、後でMongoDBを深く使うことになれば、その時もっと勉強してみなければ。
{
"_id": ObjectId("discordChannelId"),
"feeds": [
{
"blogName": "Naver D2",
"rssUrl": "https://d2.naver.com/d2.atom",
"addedAt": ISODate("2024-12-30T10:00:00Z"),
"lastSentTime": ISODate("2024-12-30T10:00:00Z"),
"lastPostLink": "FE News 25年9月のお知らせをお届けします!",
"totalPostsSent": 100
}
],
"createdAt": ISODate("2024-12-30T10:00:00Z"),
"updatedAt": ISODate("2024-12-30T10:00:00Z")
}
トラブルシューティングと言えるだろうか
先ほどPulumiでMongoDBクラスターも構成できると話したが、最初に構成するのに約3分かかり、M0クラスターはアップデートができないという問題があった。したがってPulumiインフラ構成は実質的にAWS中心で進めることになった。しかしそれでもシークレット値を管理する部分でCDKに比べて圧倒的な利便性を感じることができた。
今回のプロジェクトで最も心残りなのは、MongoDB IPの制限を開けておいたという点だ。IP制限をかけるためにはNAT GatewayとVPC接続が必要だ。しかしコストが約100倍に増加すると予想されたため、現在のプロジェクトでは進めないことにした。これも後でMongoDBをまた使うことになれば、再挑戦する価値のあるポイントとして残しておかなければ。
内部ロジックの中では、重複フィードをチェックするロジックがなかなか厄介だった。Discordチャンネル初回登録時にlastSentTime値を間違って与えてメッセージテロを経験した。これは新しいフィード登録時に該当フィードの最新記事を基準に送信時刻とURLを合わせておくことで解決した。もう一つの問題は、1つのフィードで1回のスケジューリング内に2つ以上のフィードをアップロードした時、次のスケジューリング時に同じフィードがアップロードされる問題だった。これはrss.xmlのようなRSSファイルが時間の逆順で表現されるため、時間とURLベースの重複チェックロジックを通過してしまったようだ。そこでフラグ値を1つ置いて、最初のアイテムを対象に最後の送信記事情報を更新するように変更した。
感じたこと
まずAI Agentと一緒に作ったなりの初のアウトプットだと感じられて、やりがいがあった。今後もAIツールを積極的に活用しながらアウトプットをもっと最大化できるようにしなければ。
そして今やAIのおかげでコード作成能力よりも設計能力の方が重要になってきているということを痛感した。今回こうしてシンプルなプロジェクトを作るのにも設計部分でつまずくのを見て、自分自身の設計経験がかなり不足していたということにも気づいた。
だから本格的に規模のあるサイドプロジェクトを作らなければならない。できれば今回のような練習試合をもう少しやるのもいいが、以前から夢見てきた自分の名前で作った自分だけのサイドプロジェクトを、そろそろ急いで作ってみたくなった。
そしてブログも月に一度は必ず書くようにしよう。