この記事はヌーラボブログリレー2025 冬 の12日目として投稿しています。
こんにちは!ウェブサイトユニットの野津です。
最近のお気に入りの将棋の駒は角行です。
ウェブサイト運用をしていると避けては通れないリダイレクトの実装方法について比較しました。
目次
リダイレクトの必要性
リダイレクトとは、とあるウェブサイトのページにアクセスしたユーザーを自動的に別のページに転送する仕組みのことです。
ウェブサイトを運用していると、不要になったページ削除や統合などが日々発生します。
例えば、削除したページをユーザーがブックマークしていた場合、アクセスするとページを閲覧することができませんが、リダイレクトを設定しておけば、このページにアクセスしたときに関連する別のページに自動遷移させて機会損失を減らすことができます。
また、SEOの観点でも検索エンジンの評価を落とさないようにするために適切なリダイレクトの設定が必要です。
リダイレクトの実装方法
リダイレクトの実装方法は様々で、主に使用しているものは以下3種類です。
- Nginx によるリダイレクト
- Lambda@Edge によるリダイレクト
- CloudFront Functions によるリダイレクト
|
特徴 |
1. Nginx |
2. Lambda@Edge |
3. CloudFront Functions (CFF) |
|
実行場所 |
サーバー上 (EC2インスタンス) |
Amazon CloudFront の関数関連付けにある以下4つ
|
Amazon CloudFront の関数関連付けにある以下2つ
|
|
対応言語 |
Nginx設定ファイル |
Node.js, Python |
JavaScript |
|
メリット |
・サーバー内で完結するため追加コストがかからない ・実装パターンなどの知見が豊富 |
・フル機能のプログラミング言語が使える ・外部ネットワークへのアクセスが可能 |
・起動が早い ・コストがLambda@Edgeより安い ・KVSと連携可能 |
|
デメリット |
・設定ファイルが肥大化しやすい ・オリジンに負荷がかかる |
・バージョン管理が複雑化しやすい ・コールドスタートの可能性がある ・IAMロールの設定・管理が手間 |
・コードサイズ上限 (10KB) ・言語仕様に制約がある ・履歴管理するにはIaC化が必須 |
1. Nginxによるリダイレクト
Nginxの設定でコントロールする方法です。
主に動的なウェブサイトをEC2インスタンスで動作させる場合に使用している手法です。
基本的には rewrite や return を使いますが、ルールが増えてくると管理が大変になるため、map モジュールを使うことでURLの対応表を作ることもできます。
書き方の例(nginx.conf):
http {
# リダイレクトマップの定義
map $request_uri $new_uri {
default "";
/old-page-a /new-page-a;
/old-page-b /new-page-b;
}
}
server {
# マッチした場合のみリダイレクト
if ($new_uri) {
return 301 $new_uri;
}
}
運用しているウェブサイトの改修を重ねるにつれ、リダイレクト設定の行数が肥大化してきました。
新しく追加したリダイレクト設定が既存のリダイレクトの処理に影響しないかどうかの確認も必要です。
また、リクエストがオリジン(EC2インスタンス)に到達してからリダイレクトを返すため、若干レスポンスが悪くなるのとオリジンへの負荷がかかるという課題もあります。
2. Lambda@Edge によるリダイレクト
CloudFrontに設定できる機能の一つで、世界中のエッジロケーションでNode.jsやPythonを実行できるサービスです。
自由度が高いですが、リダイレクトのようなシンプルな処理に使うには、少しオーバースペックかもしれません。
気になっているのがバージョン管理機能です。
Lambda@Edgeは、コードを更新するたびに新しいバージョンが発行する必要があるため、軽微なミスを修正するだけで過去のバージョンが増殖していきます。
書き方の例(Node.js):
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const oldUri = request.uri;
const redirects = {
'/old-page': '/new-page',
'/blog/old': '/blog/new'
};
if (redirects[oldUri]) {
return {
status: '301',
statusDescription: 'Moved Permanently',
headers: {
location: [{
key: 'Location',
value: redirects[oldUri],
}],
},
};
}
return request;
};
CloudFrontへの関連付け方法
CloudFrontの設定で関数の関連付けができます。
単純なリダイレクトのみの設定であればユーザーに一番近いビューワーリクエストで処理します。
3. CloudFront Functions (CFF) によるリダイレクト
今寄せていこうとしているのが CloudFront Functions (CFF) です。
Lambda@Edgeと同様にCloudFrontに紐づけて使うことができ、より軽量で、アクセスが来た瞬間に実行されます。
Lambdaのようなバージョン管理の概念がなく、常に「最新のコード」が反映されるためスッキリしています。
逆に言うと、履歴管理をするためにはGitなどでのIaC化が必須です。
CFFには「コードサイズが最大10KB」という制約があります。
そのため、リダイレクトの設定が増えていくと、CloudFront KeyValueStore (KVS) で対応する必要がありそうです。
KVSはCFFから参照できる「キーと値の保管場所」です。リダイレクトリストをコードから切り離してKVSに保存することで対応します。
書き方の例(JavaScript ):
import cf from 'cloudfront';
// KVSのID
const kvsId = 'kvs-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
async function handler(event) {
const request = event.request;
const key = request.uri; // URLをキーにして検索
try {
// KVSからリダイレクト先を取得
const newUrl = await cf.kvs(kvsId).get(key);
// 見つかったらリダイレクト
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
"location": { "value": newUrl }
}
};
} catch (err) {
// KVSにキーがない場合はそのままオリジンへ
return request;
}
}
KeyValueStore (KVS) の中身
上記のコードは、KVS内に以下のようなデータが登録されていることを前提としています。
request.uri で取得できるパス(例: /old-page)をKeyとして検索し、対応するValue(例: /new-page)を引いてくる仕組みです。
|
Key (アクセスされたパス) |
Value (リダイレクト先) |
|
|
|
|
|
|
|
|
|
まとめ
リダイレクトの実装方法は、サイトの歴史とともに混在しがちです。
しかし、運用フローがバラバラだとミスの原因になりますし、属人化も進んでしまいます。
今後はCloudFront Functionsをベースにして管理の省力化を進めていく予定です。
最後に、 リダイレクトは便利ですが、設定ミスには気をつける必要があります。
- リダイレクトループ(A→B→A…と無限に転送される)
- オープンリダイレクト(悪意あるサイトへの踏み台にされる脆弱性)
- クエリパラメータやスラッシュ(/)の扱いの不備
これらは、実装方法を変えても変わらず注意が必要です。
AIにコード生成をサポートしてもらう時代だからこそ、角行のように気づかないところから問題を解決(自動テストを整備)したり、王将(情報)を守ったりといった仕組みを取り入れながら進められればと思います。
健全なリダイレクトライフを!



