位置情報を使った即時型マッチングアプリ(iOS/Android)
今、会える。地図から始まり、メッセージなしで待ち合わせまで完了するマッチングアプリ。

Overview
プロジェクト概要
今この瞬間に会える人同士を地図の上で結び、メッセージのやり取りをせずに待ち合わせまで終えられる、スマートフォン向けのマッチングアプリを開発しました。地図を開くと今会える人が距離と目的つきで表示され、気になる人に1タップでリクエストを送れます。相手が承認すると、アプリが二人にとって公平で安全な待ち合わせ場所を提案します。iOSとAndroidのアプリに加えて、運営向けの管理画面(Web)も作りました。
従来のマッチングサービスは、検索、いいね、メッセージ、日程と場所の調整と、会うまでの手順が長く、途中で多くの利用者が疲れてしまうことが課題でした。また、クライアントは以前、長い期間をかけても動くものが手元に残らないまま開発が中断した経験があり、本プロジェクトでは「途中で止まらないこと」と「進捗が目に見えること」も重視されました。当社が1名の体制で、要件定義からUI/UXデザイン、アプリとサーバーの実装、テスト、ストア公開までを担当しました。
※ お客様名・製品名は記載していません。掲載している画面とデータは、説明用に再構成したイメージです。
- 分類
- 位置情報を使った、即時型のマッチングアプリ
- 対応プラットフォーム
- iOS/Android(1つのコードで両OSに対応)、運営向け管理画面(Web)
- 対応環境
- iOS 15以上 / Android 8.0以上
- 体制
- 1名
- 進め方
- 5段階に分け、段階ごとに動くアプリとソースコードを引き渡し
- 業種
- コミュニケーション・マッチングサービス
- ロール
- 要件定義 / UI/UXデザイン / アプリ実装 / サーバー実装 / テスト / ストア公開
- 技術
- Flutter / Dart / Riverpod / Supabase / PostgreSQL / PostGIS / Supabase Edge Functions / Mapbox / Firebase Cloud Messaging / GitHub Actions / Codemagic

01 — 利用の流れ
メッセージ0通。数タップで、待ち合わせまで
利用の流れは、「準備する」「見つける」「会う」の3つのフェーズ、9つのステップで設計しました。会える時間と目的を選んでONにすると、近くの人が地図に表示されます。気になる人に1タップで「会いたい」を送り、相手が承認するとマッチが成立し、プッシュ通知で届きます。続けてアプリが待ち合わせ場所の候補を提案し、二人で場所を選んで合流します。会ったあとは★5段階で相互に評価します。会うまでのメッセージは0通です。
- 会える時間と目的を選んでONにする
- 近くの人を距離・目的・時間で絞り込む
- 1タップのリクエストと承認でマッチが成立
- 待ち合わせ場所の候補をアプリが自動で提案
開発中の課題と解決
ありえない状態の遷移と、二重のマッチを防ぐ
- 課題
- リクエスト、承認、待ち合わせ、道中と状態が次々に変わるため、通信のタイミングによっては、承認されていないのに道中になる、同じ人が二重にマッチする、といった不整合が起こりえます。
- 解決
- 利用者の状態をサーバー側で1つの状態機械として管理し、ありえない遷移をDB関数で拒否しています。承認からマッチの作成までを1つのDB関数(トランザクション)で行い、行ロックで二重にマッチしないことを保証しました。リクエストは5分で期限切れになり、定期ジョブで処理します。

02 — 中間地点アルゴリズム
“真ん中”ではなく、二人が会いやすい場所へ
このアプリで最も難しく、最も重要なのが待ち合わせ場所の決め方です。緯度・経度の単純な平均は、川や線路の上に落ちたり、片方だけが遠かったり、目印のない場所や暗い路地を指したりします。そこで、二人の位置から探索の中心を計算し、半径内の「会える場所」を空間検索で最大20件取り出し、二人から全候補までの所要時間を1回のAPI呼び出しでまとめて取得します。各候補を、公平さ(0.35)・近さ(0.25)・安全性(0.25)・目的との一致(0.15)の重みで点数化し、上位3〜5件を提示します。計算はすべてサーバー側で行い、相手の正確な位置がアプリに届くことはありません。
- 二人の所要時間が公平になる候補を優先
- 明るく人のいる、名前のある場所だけを提示
- カフェ・ごはんなど目的に合うカテゴリを優先
- 上位3〜5件から、二人で選べる
開発中の課題と解決
「真ん中」で本当に会えるか(特に地方)
- 課題
- 都市部では中心のすぐ近くにお店がたくさんありますが、地方では幾何学的な中点が田んぼや農道の上に落ちることも珍しくありません。
- 解決
- 中心から半径1km以内の候補の数で都市モードと地方モードを自動で判定し、地方モードでは車での所要時間で計算して、コンビニ・道の駅・駐車場などを優先します。候補が見つからなければ、3km → 5km → 10km → 20kmと探索範囲を段階的に広げ、必ず「名前のある安全な場所」を返します。

03 — 位置情報と安全の仕組み
位置情報は、必要なときに、必要な分だけ
相手に見える位置の詳しさを、利用の段階に合わせて5段階に分けました。待機中は、ぼかした位置と丸めた距離(例:約240m)だけを見せます。マッチが成立すると候補の地点と所要時間だけを見せ、待ち合わせ場所へ向かう間だけ、お互いの現在地と到着予定をリアルタイムで共有します。合流したら共有はすぐに止まり、道中の位置は保存しないため、あとから追跡もできません。待ち合わせ中はSOSボタンを常に表示し、押すと110番への発信を案内して、運営に緊急通知を送ります。
- 待機中は、ぼかした位置と丸めた距離だけを表示
- 道中だけ、お互いの現在地と到着予定を共有
- 合流後は共有を自動で停止し、位置の履歴を残さない
- 身分証による年齢確認・通報・ブロック・SOS
開発中の課題と解決
何度も見られても、正確な位置を推定されない
- 課題
- ぼかした位置でも、何度も取得して平均すると、元の正確な位置を推定されるおそれがあります。
- 解決
- 正確な位置は、その利用者とサーバー処理だけが読める列に分けて持ちました。他のユーザーには、ONにするたびに決まる半径100m程度のランダムなずれを加えた位置を返し、ONの間はそのずれを固定します。位置を持つ行はONの間だけ存在し、OFFにしたときや10分間更新がないときは自動で削除します。

04 — 運営の仕組みとストア公開
アプリだけで終わらない。運営・公開まで、ひとつの仕組みに
運営向けの管理画面も、アプリと同じFlutterで作り、Web向けにビルドしました。身分証の審査は、生年月日から18歳以上であること、顔写真とプロフィールの一致、有効期限内であることを確認するチェックリスト形式にし、担当者による判断のばらつきを抑えています。差し戻すときは理由を選ぶと、ユーザーに再提出の案内が自動で届きます。開発は5つの段階に分け、段階ごとにTestFlightとGoogle Playの内部テストでアプリを配信しました。最後に総合テストとストア審査への対応を終え、App Store/Google Playの公開版、ソースコード、運用手順書を引き渡しました。
- iOS/Androidを1つのコード(Flutter)で開発
- 身分証の審査・通報対応・利用停止の管理画面
- 2台の実機で位置情報と通知を検証
- App Store/Google Playへの公開と引き渡し
開発中の課題と解決
開発が途中で止まるリスク
- 課題
- クライアントは以前、長い期間をかけても動くものが手元に残らないまま、開発が中断した経験がありました。
- 解決
- 価値の大きい機能から5段階に分けて開発し、段階ごとに「実機で動くアプリ」と「ソースコード一式」を引き渡しました。地図のメイン画面を早い段階から実機で操作できるようにし、各段階の完了の基準(例:2台の端末でマッチが成立する)を着手前に合意してから進めています。
Scope
担当範囲
当社は、要件定義から、UI/UXデザイン、アプリとサーバーの実装、テスト、ストアでの公開までを担当しました。
| 工程 | 担当 |
|---|---|
| 要件定義 | 「今すぐ会う」という体験を最短の手順で実現することを最優先に、利用フロー・機能・非機能要件を整理。初回リリース(MVP)と将来フェーズの線引きを合意 |
| UI/UXデザイン | Figmaで、画面設計、デザインシステム、クリックで操作できる試作を作成 |
| アプリ実装 | Flutter/Dartで、iOSとAndroidで共通のUIとロジックを開発。運営向けの管理画面もFlutterで作り、Web向けにビルド |
| サーバー実装 | Supabaseで認証・データベース・リアルタイム通信・ストレージを構成。PostGISの空間処理と、Edge Functionsによる中間地点の計算・外部API連携・通知の送信 |
| テスト | 単体・ウィジェット・ゴールデン・結合テストと、2台の端末にGPXファイルで移動を再現させる実機での位置テスト |
| ストア公開 | 総合テストとストア審査への対応を終えて公開版を作成し、ソースコードと運用手順書を引き渡し |
Architecture
使用技術・システム構成
- スマートフォンアプリ
- Flutter / Dart / Riverpod(状態管理) / go_router(画面遷移・ディープリンク) / geolocator(位置情報)
- 地図
- Mapbox Maps SDK for Flutter / Mapbox Studio(オリジナルの地図スタイル)
- サーバー・データ
- Supabase(Auth / Realtime / Storage) / PostgreSQL+PostGIS / Supabase Edge Functions(TypeScript/Deno)
- 外部サービス
- Mapbox Matrix API/Directions API / ホットペッパーグルメAPI / OpenStreetMap
- 通知・監視
- Firebase Cloud Messaging / Crashlytics / Analytics
- ナビゲーション
- Googleマップ/Appleマップ(URLスキームで連携)
- CI/CD
- GitHub Actions(静的解析・テスト) / Codemagic(ビルド・テスト版配信)
主な技術の選定理由
ネイティブアプリ(Flutter)
Webサービスとしても検討しましたが、待ち合わせ中のバックグラウンドでの位置共有と、通知の確実性を優先しました。1つのコードでiOSとAndroidに対応できます。
Supabase(PostgreSQL+PostGIS)
PostGISの空間検索をそのまま使え、サーバーの保守も不要だからです。Firestoreは空間検索が苦手なため採用しませんでした。
Mapbox
ブランドに合わせたオリジナルの地図スタイルを作れること、Matrix APIの無料枠があることが決め手です。
メッセージ機能を持たない
「会うまでを短く」というコンセプトを優先しました。投稿を監視する運営の負担もなくなります。
ナビゲーションは外部の地図アプリに任せる
曲がり角ごとの案内を自前で作ると、開発と保守のコストに見合わないためです。利用者も使い慣れています。
Process
開発の進め方
- 1
第0段階:要件と画面の流れを確定。クリックで操作できる試作で画面の流れを合意しました。
- 2
第1段階:地図のメイン画面・現在地・ON/OFF。体験の中心を最初に実装し、テスト版を配信しました。
- 3
第2段階:マッチング・中間地点の計算・待ち合わせ・道中ナビ。2台の実機で、リクエストから合流まで成立することを確認しました。
- 4
第3段階:会員登録・身分証の確認・プロフィール・管理画面・通報/ブロック。登録から審査、運営の操作まで一通り通しました。
- 5
第4段階:総合テスト・ストア申請・公開・引き渡し。ストア版で一連の体験が動くことを確認しました。
- 6
週1回の進捗レポート(画面録画とスクリーンショット付き)、GitHub Projectsの課題ボード、段階ごとの確認会で、進捗をいつでも確認できるようにしました。
Quality & Security
品質・セキュリティ・運用
テストの方針
中間地点のスコア計算や状態遷移の単体テスト、主要画面のウィジェットテスト、見た目の崩れを検知するゴールデンテスト、登録から評価までの結合テストを行いました。2台の端末にGPXファイルで移動を再現させ、都市と地方の座標で候補が正しく出るかも確認しています。
身分証の確認と年齢確認
身分証を撮影して提出し、運営が審査します。承認されるまではONにできず、18歳未満は利用できません。書類は非公開のストレージに保存し、管理者だけが期限付きのURLで閲覧できます。
断る・ブロック・通報・評価
リクエストはいつでも見送れ、理由は相手に伝わりません。ブロックした相手とはお互いの地図から完全に消え、通報はすぐに管理画面へ届きます。評価が低い人や通報が多い人は、運営の確認対象になります。
アクセス制御
すべてのテーブルで行単位のアクセス制御(RLS)を有効にしています。外部APIのキーと計算処理はサーバー側にまとめ、アプリには秘密情報を持たせません。
法令とストア審査
年齢確認、利用規約、通報・ブロック、アプリ内でのアカウント削除、位置情報の利用目的の表示を、初期設計に入れました。出会い系サイト規制法に関わる届出の要否と年齢確認の方法は、所轄の警察署への事前相談と弁護士の確認を前提に進めています。
運用コスト
外部サービスは無料枠や定額プランで収まる構成にし、利用量に応じて課金されるAPIは、呼び出す回数そのものを減らす設計にしました。
Results
成果
メッセージをなくし、位置情報と中間地点アルゴリズムで「会うまで」を短くすることに挑みました。技術の選択から進め方まで、すべてを「安全に、確実に、すぐ会える」ために設計しています。
- MVPとして定義した機能を、1つのコードでiOSとAndroidの両方に実装しました。管理画面もFlutterで共通化しています。
- 5つの段階すべてで確認の基準を満たし、実機のテスト版とソースコードを引き渡しました。
- 登録から合流・評価までの9ステップを実装し、会うまでのメッセージは0通です。
- 都市では店舗に、地方では道の駅やコンビニに寄せ、どこでも「名前のある安全な場所」を返すアルゴリズムを実現しました。
- バックグラウンドでの位置共有と確実に届く通知で、ポケットに入れたまま合流できる体験にしました。
FAQ
技術面のよくあるご質問
- Q. なぜメッセージ機能を持たないのですか?
- 「会うまでを短く」というコンセプトを優先したためです。1タップのリクエストと承認、アプリによる場所の提案で、文章のやり取りを不要にしました。投稿監視の負担もなくなります。
- Q. 相手に、正確な現在地が知られることはありませんか?
- 待機中に他の人へ返すのは、ONにするたびに決まる半径100m程度のランダムなずれを加えた位置と、丸めた距離だけです。詳しい位置は、二人とも会うことに合意したあとの、待ち合わせの間だけ見えます。道中の位置は中継するだけで、データベースには保存しません。
- Q. 近くにお店が少ない地方でも、待ち合わせ場所は出ますか?
- 出ます。探索の中心のまわりにあるスポットの数からモードを自動で判定し、地方モードでは車で計算します。範囲を1kmから20kmまで段階的に広げ、それでもなければ最も近いコンビニか駅を提示します。座標だけの地点は返しません。
Tech Stack
