ブログに戻る

自社スタックに高速なIP-to-Country判定を組み込む

位置情報エンジニアリングAPI

Webアプリに国判定を追加するための実践ガイド。どこで呼び出し、どうキャッシュし、クリティカルパスからどう外すかを解説します。

# 自社スタックに高速なIP-to-Country判定を組み込む

国判定にかけてよい時間は、リクエストあたり数ミリ秒程度です。その軽さを保つための設計ポイントを見ていきましょう。

まずはクライアントIPを正しく取得する

proxyやCDNの背後にいる場合、ソケットから見えるIPアドレスは自社のエッジです。実際に自社インフラが設定しているヘッダーを読み取り、信頼するのは自社ネットワークから届いた値だけにします。

  • Cloudflare: CF-Connecting-IP
  • Most load balancers: leftmost untrusted entry in X-Forwarded-For
  • Direct: the socket peer address

X-Forwarded-Forを無条件にパースするのは危険です。クライアント側で任意の値を先頭に追加できるため、なりすましの穴になり得ます。

リクエストごとではなく、セッションごとに1回だけ呼ぶ

国判定はセッション作成時に実行し、国コードや分類結果をセッション、または署名付きCookieに保存して再利用します。IPアドレスが変わったときだけ再判定すれば十分です。これだけで、数千回のルックアップを1回に減らせます。

適切なTTLでキャッシュする

特定の/24に対する位置情報は、数時間単位では大きく変わらないことがほとんどです。IPアドレスをキーにした1時間程度のインメモリキャッシュを置けば、繰り返しアクセスの大部分を吸収できます。取得失敗などのネガティブな結果も、短めのTTLでキャッシュしておきましょう。障害時にルックアップが雪崩のように増えるのを防げます。

レンダリングを絶対にブロックしない

ルックアップには数百ミリ秒程度の厳格なタイムアウトを設定し、必ずフォールバックを用意します。

ts const geo = await Promise.race([ lookup(ip), timeout(300).then(() => null), ]); const country = geo?.country ?? defaultCountry;

通貨表示が想定と少し違う程度なら、まだ小さな不便で済みます。しかし、ページそのものが表示されなければ、その時点で売上機会を失います。

可能ならエッジで処理する

アプリケーションがエッジランタイム上で動いているなら、ユーザーに地理的に近い場所でルックアップできます。追加レイテンシはほとんど無視できる水準になります。エッジで判定し、その結果をリクエストコンテキストに付与して、アプリケーション側では単なるデータとして扱えるようにしましょう。

生データではなく、判断結果を残す

保存すべきなのは、生の位置情報レコードではなく、ビジネス上必要な結果です。たとえば「表示した通貨」や「適用したルール」を残します。そのほうがコストを抑えられ、プライバシーレビューでも説明しやすく、後から実際に検索したい情報にもなります。

現在の接続