ルール
避ける 意図しない グローバル 変数 キャッシュ Node.js
および Python サーバでは グローバル変数 変数 持続 リクエストを越えて
リクエストにまたがって持続します、 そのため データ リーク そして レース を引き起こします。
対応言語 JavaScript、 TypeScript、 Pythonはじめに
Node.jsサーバーのグローバル変数は、単一のリクエストだけでなく、プロセスのライフタイムにわたって持続します。リクエスト・ハンドラがユーザ・データをグローバル変数に格納すると、そのデータは異なるユーザからの後続のリクエストでもアクセス可能なままです。これは、ユーザ A のセッションデータ、認証トークン、または個人情報がユーザ B に漏れるというセキュリティ上の脆弱性を生み出します。
なぜそれが重要なのか
セキュリティへの影響(データリーク):ユーザー固有のデータをキャッシュするグローバル変数は、リクエスト間のデータリークを引き起こします。あるユーザーの認証状態、セッションデータ、または個人情報が他のユーザーから見えるようになり、プライバシーとセキュリティの境界を侵害します。
レースコンディション:複数の同時リクエストで同じグローバル変数が変更されると、予測できない動作が発生する可能性が高くなります。ユーザーAのデータがユーザーBのリクエストによって処理の途中で上書きされ、不正な計算や破損した状態になったり、ユーザーがお互いのデータを見たりする可能性があります。
デバッグの複雑さ:グローバル変数のキャッシュによって引き起こされる問題は、リクエストのタイミングと同時実行性に依存するため、再現が難しいことで有名です。バグは負荷のかかる本番環境では断続的に現れますが、シングルスレッドの開発テストではほとんど現れません。
メモリーリーク:クリーンアップされずにデータが蓄積されたグローバル変数は、時間の経過とともに無制限に増大する。リクエストのたびにグローバルキャッシュや配列にデータが追加され、最終的にはサーバーのメモリを使い果たし、プロセスの再起動が必要になります。
コード例
非準拠:
let currentUser = null;
let requestData = {};
app.get('/profile', async (req, res) => {
currentUser = await getUserById(req.userId);
requestData = req.body;
const profile = await buildUserProfile(currentUser);
res.json(profile);
});
function buildUserProfile(user) {
return {
name: currentUser.name,
data: requestData
};
}
なぜ間違っているのか: グローバル変数 currentUser と requestData は、リクエスト間で持続します。複数のリクエストが同時に実行されると、ユーザAのbuildUserProfile()が実行されている間にユーザBのリクエストがcurrentUserを上書きし、ユーザAにユーザBのデータが表示される可能性があります。
✅ 準拠:
app.get('/profile', async (req, res) => {
const currentUser = await getUserById(req.userId);
const requestData = req.body;
const profile = buildUserProfile(currentUser, requestData);
res.json(profile);
});
function buildUserProfile(user, data) {
return {
name: user.name,
data: data
};
}
なぜこれが重要なのか:リクエスト固有のデータはすべて、リクエストハンドラにスコープされた ローカル変数に格納される。各リクエストは、他の同時リクエストにリークすることのない、 孤立したステートを持ちます。関数はグローバルなステートにアクセスするのではなく、 パラメータを通してデータを受け取るので、競合状態が発生しません。
結論
リクエスト固有のデータはすべて、フレームワークが提供するローカル変数かリクエストオブジェクトに保持します。グローバル変数は、コンフィギュレーション、コネクションプール、読み取り専用キャッシュのような、本当に共有される状態のためだけに使用してください。グローバルな状態が必要な場合は、適切な同時実行制御を使用し、データがユーザー固有にならないようにします。
.avif)
