ケチな元同期メンバーと無料で集合駅検索WEBサービスKokoneをリリースしたお話

# 集合駅検索サービスKokoneをリリース🎉

「お友達や同僚と久々に集まりたい！ けど、どの駅に集合したらみんなから近いんだろう🤔」
そんな悩みを解決するサービス、Kokoneをリリースしました🎉

https://kokone-app.com/?utm_source=zenn&utm_medium=referral&utm_campaign=release-article-top

Kokoneは、__「集まりたい目的」__ と __「みんなの駅」__ を入力することで、
__最適な集合駅を提案__ してくれるサービスになっています！

![how-to-use-kokone](https://storage.googleapis.com/zenn-user-upload/9a5b5c1a311b-20240303.png)

Kokoneでは「集まりたい目的」を重要視してしており、
"飲み会"や"カフェ"といった一般的な選択肢に加え、任意のキーワード(例. ボルダリング, レンタカー, ラーメン)などで、集合駅とその周辺情報を検索できるサービスになっています。
是非、皆様の集いの機会に一度活用してみてください😊

## 記事の概要

今回この記事では、主にリリースのご報告と開発チームのご紹介、利用した技術スタックについて、ざっくりとですがご説明できればと思っています！

Kokoneは今のところ無料でサービス運営できておりますので、
個人開発されている方や無料でシステム開発されたい方、システム構成に悩まれている方に、参考になればと思います！

また、Next.js AppRouterを使ってみたりした所感も書いたりしておりますので、ご興味ある方はぜひご一読ください！

## 開発チームの紹介

「Kokone」は元会社(某SIer系企業)の同期5名で、
お勉強やアウトプットの機会を兼ねて、趣味としてこのサービスを開発しています！

開発の進め方にはアジャイルを採用しており、
各々の本業との業務量や頑張りたい量に合わせて、そのスプリント内で実施可能なチケットをゆるーくアサインしていく様なスタイルで、細く長く開発を続けています🏃‍♀️

### 開発期間

2023年9月11日に開発を開始し、約3ヶ月弱かけて2023年12月3日に正式リリースしました！

__初期コミット日__
![initial-commit](https://storage.googleapis.com/zenn-user-upload/007159c3a631-20240303.png)

__リリースツイート__
@[tweet](https://twitter.com/kokone_official/status/1731215615783047581)

## 技術スタック

Kokoneで利用している技術スタックをご紹介します！
基本的に、Kokoneは細く長く続けることを目標としているため、
収益化できなくともサービスを継続し続けれる様に、無料で使える技術スタックを可能な限り利用させて頂いています。
(結果、冒頭で申した通り、現在のところ有難くも悲しくも無料でサービス運営させて頂いております🙇‍♂️ユーザーが増えたらきっと無料で運営できなくなるので、ぜひひいひい言わしてください)

### 全体構成

すごく単純なアプリケーションのため、下記の様な極めてシンプルな構成で作っています。

![overall-design](https://storage.googleapis.com/zenn-user-upload/9baa792453b3-20240303.png)

|ロール|利用プラットフォーム|採用理由|
|:---|:---|:---|
|DNS/CDN|[Cloudflare](https://www.cloudflare.com/plans/free/)|無料から使えるDNSとキャッシュ|
|WEBサーバー|[Render.com](https://render.com/)|無料から使えるランタイム環境として採用|
|DB|[PlanetScale](https://planetscale.com/)|無料から使え、スケーリングに強いMySQL環境として採用|
|FaaS|[AWS Lambda](https://aws.amazon.com/jp/pm/lambda/?gclid=CjwKCAiAuYuvBhApEiwAzq_YieSDXBSTWNEt5wuvcgj_ABnUa6_p-SXaHqO3mA-Q20OGQhpgJTYJqxoCy2gQAvD_BwE&trk=861693db-de3d-495d-bb69-8f432a93b7a2&sc_channel=ps&ef_id=CjwKCAiAuYuvBhApEiwAzq_YieSDXBSTWNEt5wuvcgj_ABnUa6_p-SXaHqO3mA-Q20OGQhpgJTYJqxoCy2gQAvD_BwE:G:s&s_kwcid=AL!4422!3!651510561789!e!!g!!aws%20lambda!19828231338!143940518861)|駅検索のロジックを実行。Pythonの行列計算を行うため、FaaSとして外出し。|

### DNS/CDN

#### Cloudflare
無料から使えるDNS/CDN環境として、[Cloudflare](https://www.cloudflare.com/plans/free/)を利用しています。
無料プランでは、クライアントからのデータアップロード制限が100MBであるものの、
通常のWEBアプリケーションで利用する分には全く問題なく、帯域幅などには制限がないため、
小規模サービスレベルでは、ほとんどのケースで無料の範囲内でご利用頂ける素敵なサービスでした。

更にDNSに加えてCDN(静的コンテンツのキャッシュ)やリクエストの分析機能までを提供してくれているため、とりあえずDNSにCloudflareを採用しておけば、多くの場合問題ないかと思います！

### WEBサーバー

#### Render.com
無料から使えるランタイム環境として、[Render.com](https://render.com/)を利用しています。
個人開発の味方だったHerokuの後継となるサービスとして有名なRender.comですが、
Heroku同様に15分間アクセスがないとサーバーがスリープしてしまうため、常時稼働しておくために、15分に１回サーバーにリクエストをかけてあげる必要があります。

また、注意点としましては、
2024年3月現在、Render.comには日本リージョンが存在しないため、
選べるリージョンの中で東京から最も遅延が少ないシンガポールリージョンを選択してあげる必要があります。

天然ほっけさん調べによると、
シンガポールリージョンを利用した際のオーバーヘッドは、
約95msec程度であり、今回Kokoneのサービスでは、そこまでブラウザ~サーバー間の通信が発生しないため、この遅延は許容することにしています。
(別のおすすめホスティング環境あればぜひ教えてください🙇‍♂️"無料"のやつでw)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392931/50a56b83-b3a2-1d71-9189-cd2bf3b890d3.png)
(出典: https://feedback.render.com/features/p/tokyo-region)

#### Next.js AppRouter
フレームワークには、Next.js(AppRouter)を採用しています。
膨大な駅データを利用するため強力なキャッシュが利用できる点、
また、個人的にAppRouterを検証してみたかった点が採用の決め手でした。

使ってみた所感としては、PagesRouterとは全く別のフレームワークと考えて良いくらい、
コンポーネント設計や使えるファンクション、書き方などがかなり異なる印象でした。

特に、CC(ClientComponent)からSC(SeverComponent)へのデータの受け渡しに悩むことが多く、
(CookieかQueryParameter経由でしか受け渡せない理解)、コンポーネント自体はほぼほぼCCで書いているという感じになりました。

AppRouterで、「問題なく移行できた」、「使い安い」という意見を良く散見しますが、
個人的には、クリックで開くナビバーやヘッダーなどを採用しているUIでは、
基本的にレイアウト上でOpen/Closeステータスの保持が必要となるため、レイアウトをほぼCCで書かなければならなく、SCの恩恵をほとんど受けられないなんてケースは多くないのかな、、、と疑問思ってます。
(`このあたりの知見のある方、ぜひご意見ご教示ください！！！🙇‍♂️🙇‍♂️🙇‍♂️`)

このコンポーネントの構成などは技術選定する時点でUIが決まっていれば、今後Next.jsのAppRouterを採用するか決める際に考慮してみてもいい気が個人的にはしました。

### 周辺情報の取得(API)

周辺情報の検索には、元々 [Google Places API](https://developers.google.com/maps/documentation/places/web-service?hl=ja) を利用していました。
Google APIには20,000円のクレジットが含まれていますが、
1リクエストで4円ほどかかってしまい、各検索された集合駅毎に周辺情報をリクエストするには不十分だったため、無料で使える[HotPepper　グルメサーチAPI](https://webservice.recruit.co.jp/doc/hotpepper/reference.html#a1to)を可能な限り利用するように、修正しました！

* [Google Places API](https://developers.google.com/maps/documentation/places/web-service?hl=ja)
* [HotPepper　グルメサーチ API](https://webservice.recruit.co.jp/doc/hotpepper/reference.html#a1to)

### DB

#### PlanetScale

Kokoneでは、
Vitessをベースとして水平スケールに対応したRDBと、開発体験が良く、無料枠が充実しているという噂を聞き、前々から興味のあった[PlanetScale](https://planetscale.com/)を採用しました。
スキーマ情報をブランチ管理できる開発体験はすごく良い感じでした。

駅データは、[駅データ.jp](https://ekidata.jp/doc/)が提供してくださってるCSVファイルを元にクエリに変換し、データベースに保存しています。(ありがとうございます🙇‍♂️)

### FaaS

#### AWS Lambda

集合駅の決定ロジックは、WEBサーバーのバックエンドから別途[AWS Lambda](https://aws.amazon.com/jp/pm/lambda/?gclid=CjwKCAiAuYuvBhApEiwAzq_YieSDXBSTWNEt5wuvcgj_ABnUa6_p-SXaHqO3mA-Q20OGQhpgJTYJqxoCy2gQAvD_BwE&trk=861693db-de3d-495d-bb69-8f432a93b7a2&sc_channel=ps&ef_id=CjwKCAiAuYuvBhApEiwAzq_YieSDXBSTWNEt5wuvcgj_ABnUa6_p-SXaHqO3mA-Q20OGQhpgJTYJqxoCy2gQAvD_BwE:G:s&s_kwcid=AL!4422!3!651510561789!e!!g!!aws%20lambda!19828231338!143940518861)を呼び出す構成にしています。
AWS Lambdaでは、太っ腹なことに100万リクエスト/月以内、40万GB/sのコンピューティングタイムの無料枠が含まれていて、小~中規模のサービスであれば十分に無料で利用できる環境が整っています。

関東のみでも駅の組み合わせが約2百万通り（約2,000C2)近くあったため、
高速に最適な中間駅を決定するために行列計算が必要であり、行列計算が得意なPythonを使ってFaaSで実行させる構成にしています。

また別途このあたりを検討・実装してくれたメンバーが、このあたりの詳しいロジックとかは記事を書いてくれるかなと🪨

---

## 最後に

見てくださりありがとうございます！お金の話しが多く恐縮でした！
Kokoneは皆様のアンケートの結果を元に、
今後どんどんサービス改善に努めていきたいと思っていますので、是非フィードバックご協力をお願いいたします！
(こちらのZennでもXの公式アカウントでも、どこからでもどしどしご意見ください！)

https://qicoka.com/survey/65e448c9a69a52d3346c3d98?key=link

---

集合駅検索WEBサービスKokoneへのリンク

https://kokone-app.com/?utm_source=zenn&utm_medium=referral&utm_campaign=release-article-bottom

Kokoneの公式Xアカウント

https://twitter.com/kokone_official