【個人開発】爆速な賃貸物件の検索サービスを作った

:::note info
2024年11月現在の最新の構成に関する記事を[こちら](https://note.com/choo/n/n850bce11c1bb)に書きました。
よろしければそちらもご参照下さい。
（Qiita の本記事は、2022年4月時点の構成に関しての記事で、多少古い内容が含まれています。）
:::

個人開発で **[賃貸物件の検索サービス Comfy](https://comfy.maison/)** を作りました[^0]。グラフや地図でサクサク絞り込める UI が特徴のサービスです。**とにかく気持ち良い使い勝手を実現**するために色々工夫しています。

![comfy_20211130_light.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138646/1ffac3b2-6db5-5d30-3d47-1bdd8b3a8011.gif)

既にリリースからは 4 ヶ月以上経っているのですが、改めてサービスの概要や、システム構成及び使用した技術・サービスをご紹介しようと思います。[^article]。


[^0]: 2021年の 7 月に最初のリリースをしたのですが、色々あっていったん閉鎖した後 11 月に再リリースしました。
[^article]: この記事は、2021年7月の初期リリースの直後に Zenn に投稿した記事の大幅な改訂版になります。 Zenn の記事は 7 月のサービス閉鎖後しばらくして非公開にしたのですが、多方面から再公開のご要望を頂いたので、この度新たに書き直して公開することにしました。

サービスの概要
============

**[Comfy は日本全国の賃貸物件を検索できる Web サービス](https://comfy.maison/)** です。画面 UI は上の GIF 画像のような感じです。
こだわったポイントを色々書くよりも実際にさわって頂いた方が新感覚の UI や気持ちよさを体感頂けるかと思いますので、 **[実際のサービス](https://comfy.maison/)** をぜひお試し頂ければ幸いです！


# システム構成

![Comfy_System_Architecture_20220401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138646/06b1986b-b38a-1464-b65d-9be1ce4ddc04.png)

図の通り、システムは大きく 3 つに分けられます。

- フロントエンド
- バックエンド
- データ基盤

使用技術は図の通りではあるのですが、フロントエンドとバックエンドについてはもう少し詳細に紹介いたします。


# フロントエンド

Comfy は**ページ遷移のない SPA（Single Page Application）** として作っています。

## フレームワーク

フレームワークとして **[Next.js](https://nextjs.org/) と [Preact](https://preactjs.com/)** を使用しています。
Preact は、React と全く同じシンタックスで書ける軽量版 React といったフレームワークです。多分 React に置き換えても全く問題なく動作します。

**状態管理は React の標準機能である Props と State** のみ使用しています。
Redux、Recoil 等の状態管理ライブラリや React の Context は、特に必要と感じていないため使用していません。

## 使用ライブラリ

- **[Leaflet](https://leafletjs.com/)**
  地図の表示に使用しています。Google Maps 的なライブラリですが、Google Maps API が有料である今、**無料で使える地図ライブラリの数少ない選択肢**です。Google Maps API に似た API が整備されており、ドキュメントも非常に調べやすくかつ分かりやすく書かれていて、素晴らしいライブラリです。
Leaflet では表示する地図を選択できるのですが、**[OpenStreetMap](https://www.openstreetmap.org/#map=5/35.588/134.380) というフリーの地図ソース**を使用しています。
- **[chart.js](https://www.chartjs.org/)**
  棒グラフの表示に使用しています。柔軟な表現力を持ち、美しい API を備えた素晴らしいライブラリです。
- **[React Slick](https://react-slick.neostack.com/)**
  物件ごとの画像ビューアに使用している、カルーセルのライブラリです。初期リリースの 1 日前に選定し、あまり使いこなせていないまま今にいたります…　もう少しスムーズに動作させたかったりしますが、まだまだ使い倒す必要がありそう。

その他、スライダーやモーダル、セレクト、ハンバーガーメニュー等は全て自作コンポーネントです。

## デプロイ先

静的サイトのホスティングサービスである **[Cloudflare Pages](https://pages.cloudflare.com/) を使用**しています。
[Vercel](https://vercel.com/) や [Netlify](https://www.netlify.com/) など他サービスも今まで使用してきましたが、無料プランで帯域制限がないのは Cloudflare Page のみだったことが今回の選定理由です。実際、使用帯域幅はリリース後 1 週間強で 80 GB ほどいったので正解だったと思っています。
Cloudflare Pages は使い勝手も最高です。個人的には、バックエンドの API サーバへの DNS と合わせて使うのには特に最高だと思いました[^a]。

[^a]: なお、選定に当たっては[この記事](https://zenn.dev/catnose99/scraps/6780379210136f)を参考にしました。


# バックエンド

バックエンドはフロントエンドからのリクエストを処理する API サーバとして機能します。

## 言語・フレームワーク

Python3 で動作させています[^python]。Web フレームワークとして Python ベースの [FastAPI](https://fastapi.tiangolo.com/) (+ Uvicorn + Gunicorn) を使用しています。

**高速化の工夫をかなり色々と頑張っています**。Elasticsearch や Solr などのライブラリや Algolia 等のサービスは使っていません[^search]。色々なチューニングと同様、ボトルネックとなる処理に対して様々な高速化を試行錯誤してみて、細かいチューニングをたくさん積み上げていった感じです[^tuning]。リリース後もたくさん対策を実施しており、まだまださらなる高速化の余地もたくさんあるので、今後も引き続きチューニングしていこうと思います。
工夫は非常に多岐に渡るのでここには書ききれませんが、強いていえばコンピュータサイエンスの様々な知識と、書籍『[ハイパフォーマンス Python ](https://www.amazon.co.jp/dp/4873117402)』の内容がとても役に立ちました[^3]。

[^python]: Python 大好きなのです。
[^search]: これらのライブラリやサービスをガチガチにチューニンせずに使うよりは速く動作すると思います。（ベンチマーク取ったわけではないのではっきりとは分かりませんが…もしベンチマークに興味ある方いたらぜひコメントなど頂ければと思います！）
[^tuning]: もちろん、どんなに頑張っても速度出ないだろうという方針は最初から排除しています。そして結果的にはシンプルな検索エンジンを自前実装しているような感じになっています。。。
[^3]: 高速化に関して書けるネタ・話せるネタはたくさんあるので、今後の記事執筆、イベント登壇などでちょいちょい表に出せればと思っています。

## 使用ライブラリ

**Python に標準で入っている RDBMS の SQLite** を使っています。ただし SQLite は必要最小限の使い方しかしていません[^sqlite]。読み込むデータはなるべくメモリに乗るようにして、メモリには乗りきらない一部のデータのみ SQLite に乗せてディスクを参照するようにしています。
その他バックエンドに関しては全て自前実装です（たしか…書き忘れていたら追記します…）。

[^sqlite]: リリースする数日前くらい前までは、SQLite は使用せず全てファイルシステムベースでいこうと思っていたくらい。

## デプロイ先

バックエンドは **GCP (Google Cloud Platform) 上の GCE (Google Compute Engine、AWS でいう EC2)** で動かしています。
GCP で使用しているサービス・機能は下記のとおりです。

- Google Compute Engine
- Google Cloud Storage
- Google Cloud Load Balancing
- Google Cloud Logging

当初は Docker コンテナベースの実行環境を想定していたのですが、コンテナが重く起動時間がかかることからスケールアウト時の起動の遅さが心配なため、**GCE インスタンス上でそのままアプリケーションを走らせています**。また、Managed instance groups を使って、負荷によってオートスケールするようにしています。

ちなみに、GCE のインスタンスは e2-small (2vCPU, 2GB RAM) を使用しています。e2-micro (2vCPU, 1GB RAM) でも十分高速に動作するのを確認したのですが、一度本番環境で使用してみたところ**じゃんじゃんスケールアウトしてインスタンス数が大変なことになってしまった**のでｗ、それ以来怖くて e2-small にしています（そのうち調査・対応して e2-micro にしたいとは思っています）

まとめ
=====

個人開発で、**[新しい賃貸物件検索の web サービス Comfy](https://comfy.maison)** を作りました。
まだまだ色々改善すべき点も盛りだくさん[^improvement]で、引き続き進化させていく予定です。今後は技術面でも積極的に発信していきたいと思っているので、疑問点や聞きたいことなどあれば、この記事のコメントや **[Twitter](https://twitter.com/choo_s)** の DM など頂ければと思います。

ここまでお読み頂きありがとうございました。
もしよければぜひ、いいねやリツイートなど頂けるととても励みになります！！
よろしくお願いいたします！！！

[^improvement]: まだユーザさんの改善要望に関しても対応しきれていません…頑張ります！