個人開発した爆速な賃貸検索サービスの構成(2024年版)
個人で運営している賃貸物件の検索サービス Comfy に関しての技術記事である『【個人開発】爆速な賃貸物件の検索サービスを作った』は、いままでたくさんの人に読んでいただくことができました。ありがとうございます。
リリースから本日で丸三年という節目でもあり、記事に記載したリリース当初の構成からずいぶんと変更してきたので、現状のシステム構成を公開いたします。
Comfy とは
Comfy は 日本全国の賃貸物件を超高速に検索できる Web サービス です。
とてもこだわって UI を作り込んでいるので、もしよければこちらからお試し頂けるとうれしいです。
現状のシステム構成概要
2024年11月現在のシステム構成はこちらです。
図の中で赤く囲った部分が、リリース当初からの変更点です。
それ以外の箇所に関しては大きな変化はなく、上記の以前の記事に書いたとおりです。
リリース当初からの 5 つの変更点
1.【フロントエンド】 Cloudflare Pages から Vercel に
リリース当初は、フロントエンドのデプロイ先として Cloudflare Pages を使用していましたが 2022 年に Vercel に移行しました。
背景としては、Next.js の SSR (サーバサイドレンダリング)を使用して、地域を絞り込んだランディングページを用意したかったためです(例えば東京都港区のランディングページとして https://comfy.maison/location/3-13103 を用意する感じです)。
当時はまだ App Router 導入前の Next.js で、たしか Cloudflare Pages は Next.js の SSR に対応していませんでした(もしくは、かなり面倒なことをしなければ実現できなかった)。
Vercel に移行しても、使用帯域や SSR の build の回数、他の条件・制約に関してフリープランの適用内に収まっています。使い勝手自体も Cloudflare Pages と大して変わりませんでした。
特に不満に思った点はなく、Vercel へ移行してよかったと思っています。(もう移行作業自体が 2 年以上前なので、はっきりと覚えていませんが…)
2.【フロントエンド】 Preact から React に
また、Vercel へ乗り換えて Next.js の component(next/script や next/link など)を使ったり SSR でページを追加した際に、それまで使用していた Preact だといろいろなエラーが出たりうまくいかないことがあったので、素直に React を使うことにしました。
Preact 自体は軽量なのですが、そもそも React 本体のサイズはあまりボトルネックになっていなかったのと、多くの人が利用している React の方が確実に様々な恩恵を受けれるだろうという判断でした。
Preact から React へは、ほぼ作業無しで移行できるかと思っていたのですが、なにかと build のエラーが発生したりして大変だったことを覚えています…(詳細は覚えていません。GitHub 等の記録をさかのぼって確認することはできるので、気になる方がいればご連絡ください。別の記事にできるかもしれません)
3.【フロントエンド】 Leaflet から MapLibre GL JS に
インタラクティブな地図機能の実現には、Leaflet というライブラリを使用していましたが、ちょうど今から一年ほど前に MapLibre GL JS というライブラリに移行しました(なお、Google Maps は有料だったので、最初から選択肢に入っていません)。
この背景は、都道府県や市区町村のポリゴン(自治体の境界線からなる図形)に関して、ベクトルタイルを静的に配信したかったことです。
ここの話はかなりややこしいかつやや専門的な話なのですが、Leaflet をつかっていた際には、バックエンドの処理として、リクエストの度に市区町村などのポリゴンを都度選定し処理してレスポンスを返すということを行っていました。
この処理自体が若干重かったこともあったのですが、バックエンドのファイルやライブラリで地理情報も多分に扱わざるを得ず、煩雑な作りになっていました。
自治体のポリゴンデータを PMTiles という静的なベクトルタイルを配信する構成に変更することによって、バックエンドでの地理情報に関する処理をほぼ除外することができ、とても簡素な仕組みにすることができました。
この変更は、バックエンドの複雑性を大幅に減らしコードも大量に減ったため、バックエンドの Rust へのリプレース時にも非常に有用な変更となりました。
また、このリプレースによって、地図の操作性も格段に上がり、地図表示も圧倒的に美しくなりました(下記はその時のリリースの告知ツイートです。)
4.【バックエンド】 Python ✕ FastAPI から Rust ✕Actix Web に
バックエンドに関しては、リリース当初からほぼフルリプレースしており、今動いているコードでリリース当初からあったコードは一行もありません。
リリース当初は、Python3 で実装しており、フレームワークとして FastAPI を使用していました。バックエンドを高速で処理させることはサービスの根幹であり、高速化の工夫のひとつとして C++ による Python の拡張モジュールを実装していました。
今後もバックエンドに様々な機能を追加したいと考えていた時に C++ の拡張モジュールを引き続きずっとメンテナンスするのが突如めんどくさい気持ちになりました。
かといってフルリプレースする必要もないかなと思っていたのですが、試しに Rust でコードを書いてみたりしたところ Rust の素晴らしさに目覚め、C++ の拡張モジュールを引き続きメンテナンスするよりも Rust に乗り換えた方がよいという結論に達しました。
Web フレームワークとして Actix Web をさくっと選定し、開発期間は約 1 ヶ月しかかからず、性能も約 1.5 倍に向上しました。さらに全く同等の機能を実装したのですが、コードの行数は約 40 % になりました。
Rust での実装は、開発体験も非常によく、想像以上の結果が得られてとても満足でした。
このリプレースの詳細は、下記の記事にまとめていますので、もしよければご参照いただければと思います。
5.【インフラ】 Google Compute Engine から Cloud Run に
リリース当初からずっと、バックエンドの動作環境として Google Cloud Platform を使用しています。
上記のバックエンドの Rust への移行時に、それまで使用していた Google Compute Engine (GCE、AWS でいう EC2) から Cloud Run へ移行しました。
背景としては、Rust と Actix Web を使って移行前の logging を実現させようとすると面倒な処理が必要となることがわかり、たしか 3 日間ほどかなり悩んだ後に、標準出力をそのまま logging できる Cloud Run へ移行を決めました。
実は Cloud Run への移行時も、ディスクが使えずすべてデータをメモリで保持する必要があるなどいろいろな問題があった(オブジェクトストレージはマウントできるのですが、検証したところ本サービスの使用だとそれも問題が多かった)のですが、それはまたどこかで書ければと思います。
Cloud Run への移行は、結果としてコストの大幅な削減に成功し、これはどのリプレースよりも内心嬉しい結果をもたらしました。
おわりに
長文ながら最後まで読んでいただき、本当にありがとうございます。
もしなにかひとつでも参考になることがあれば幸いです。
この 11 月から、note で毎日なんらかの記事を投稿するという試みをしています。今後は技術記事もこちらで書いていこうと思います。
今回の Comfy の構成に関わる話でもそうでない話でも、もし書いてほしいテーマなどがあれば、ぜひぜひリクエストいただけると嬉しいです。
P.S.
Comfy のリリースから今日でちょうど 3 年が経ちました。
この節目の日に、このような振り返りの記事が書けたこと、思い出すと今まで取り組んできたことが多々あったという事実、リリースからこれまで大きな障害を起こすこともなく一度たりともサービス停止することなく運営できてきたこと、そしてなにより、本当にたくさんのユーザさんに使っていただき、たくさんの嬉しい言葉を頂いてきたこと、すべて開発者としてこの上なく幸せなことです。
本当にありがとうございます。
これからさき、もっともっと多くの人に愛して頂けるよう、もっともっと多くの人のお役に立てるよう、引き続きサービスを磨き上げていきたいと常日頃考えています。
リアルな子育てと同様、うまくいかないことも多々あり、なかなかユーザさんのリクエストにも応えられていないことも多くありますが、今後もサービス、開発者ともども、引き続きどうぞご愛顧のほどよろしくお願いいたします。