# DRF Throttlingで「scope」を使う2つの手法比較:ScopedRateThrottle vs UserRateThrottleの継承 DRFでscopeベースのスロットリングを設定する際、よく使われる2つのパターンがあります。 * **手法A**:`UserRateThrottle`(または`SimpleRateThrottle`)を継承し、**scopeを埋め込んだカスタムクラス**を作成して、ビューに`throttle_classes`で直接付与します。 * **手法B**:`DEFAULT_THROTTLE_CLASSES`に`ScopedRateThrottle`を登録し、ビューには`throttle_scope = "login"`だけを書きます。 「結局同じ効果では?」という疑問に答えると、次のとおりです。 > **単一の速度制限を「ユーザーID(または未認証IP)+ scope」で設定する場合、**結果はほぼ同じです。 > ただし **適用方法(ミス防止)、拡張性(複数ポリシー/カスタム基準)、コード構造(設定中心 vs コード中心)**で差が生じ、選択基準が決まります。 --- ## 共通点:両方とも「scope + (user id or IP)」でキーを作成します {#sec-431a00e0f2d6} * `ScopedRateThrottle`はビューに`throttle_scope`がある場合、`scope` + ユーザーID/IP でキーを構成し、`DEFAULT_THROTTLE_RATES`から該当スコープのレートを取得して適用します。 * `UserRateThrottle`も基本的に認証ユーザーは **user id**、未認証は **IP** を基準に制限し、複数を使う場合はクラスを継承してscopeを変える形をDRFが公式例として示します。 --- ## 差異1) 「scopeをどこに書くか」:ビュー属性 vs クラス属性 {#sec-d624b1b24a23} ### 手法A:クラスにscopeを固定(明示的) {#sec-8806ad9d3f5f} ```python from rest_framework.throttling import UserRateThrottle from rest_framework.views import APIView class CustomDomainSaveThrottle(UserRateThrottle): scope = "custom_domain_save" class SaveCustomDomainView(APIView): throttle_classes = [CustomDomainSaveThrottle] ``` * scopeは**クラスに固定**されます。 * ビューは「このクラスを使う」だけで完了。 * ビューごとにscope文字列をタイプミスするリスクが減ります(クラス名が実質的にドキュメントになります)。 ### 手法B:ビューにscopeだけを書き、共通throttleが解釈(設定中心) {#sec-21174dce63ed} ```python REST_FRAMEWORK = { "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.ScopedRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "login": "5/min", } } from rest_framework.views import APIView class LoginView(APIView): throttle_scope = "login" ``` * scopeは**ビューに直接**書きます。 * 共通throttle(`ScopedRateThrottle`)が「このビューはloginスコープ?」と判断し、設定からrateを取得して適用します。 * コードが短く、settingsでポリシーを一目で管理しやすいです。 --- ## 差異2) 「適用を誰が保証するか」:基本登録 vs ビュー別装着 {#sec-693e9b27f525} ### 手法Bのポイント(誤解が多い) {#sec-579edda7168e} `DEFAULT_THROTTLE_CLASSES`に`ScopedRateThrottle`を入れても、throttle_scopeが設定されていないビューには適用されません。 つまり「全体設定に入れたら全APIがブロックされる?」という心配は通常不要です。 ### 逆に手法Aの強み {#sec-1d7d8c13bc83} 全体設定を触らずに、**特定ビューにだけ**望むthrottleを「装着」できます。 (チーム/サービス構成上settingsを大きく変更できない場合や、特定アプリ/エンドポイントだけ強制したいときに便利)。 --- ## 差異3) 拡張性:単一制限を超えるとAが有利になる {#sec-76818ce0201b} 見た目はほぼ同じに見えるのは「1ビューに1scope、1速度制限」までです。 その後は差が出ます。 ### 1) 「バースト + 持続」など **複数throttle** を1ビューに掛けたい場合 {#sec-c0ea02305999} DRFドキュメントでも複数`UserRateThrottle`を同時に使うパターン(バースト/サステイン)を例示しています。 ```python class Burst(UserRateThrottle): scope = "burst" class Sustained(UserRateThrottle): scope = "sustained" class SearchView(APIView): throttle_classes = [Burst, Sustained] ``` `ScopedRateThrottle`だけでは「1ビューにscopeを2つ」自然に表現しにくく、結局 **クラスが必要** になります(またはカスタム実装)。 ### 2) 「誰を基準に制限するか」が変わる瞬間 {#sec-39de8e67072d} `ScopedRateThrottle`はデフォルトで **user id / IP** 軸で動きます。 しかし実務ではこうした要件がすぐに出てきます。 * ログイン:**IP + usernameの組み合わせ**で制限したい(アカウントターゲット攻撃対策) * 組織/テナント:**tenant_id**でまとめて制限したい * API Key:**キー単位**で制限したい この場合は結局、`get_cache_key()`などのロジックをカスタマイズする必要があり、**手法A(継承/カスタムクラス)** へ自然に移行します(DRFでもカスタムthrottleを推奨する場面です)。 --- ![API連携を開く2つの鍵](/media/editor_temp/6/e98f026a-a38e-43ca-8c86-fa7966dd3cdf.png) ## それで何を使えばいい? {#sec-1cf080d47909} ### ほとんどの「ビュー別レートリミット」なら → 手法B(ScopedRateThrottle)推奨 {#sec-924ae91c07d2} * コード最小化 * settingsでポリシー一括管理 * ビューには`throttle_scope`だけ書けば完了 * scopeのないビューには適用されない ### 以下のいずれかに該当するなら → 手法A(継承/カスタムクラス)推奨 {#sec-335f8d95a231} * 1ビューに**バースト+持続**など**複数制限**を同時に掛けたい * 「user/IP」ではなく**カスタム基準**(username+IP、tenant、API key等)が必要 * 全体設定を触れにくく、**特定ビューにだけ強制装着**したい * クラス名でポリシーを「ドキュメント化」したい(読む人が意図をすぐ把握) **関連記事:** - [DRF Throttling 完全攻略:設定、適用、カスタムガイド](/ko/whitedec/2026/1/26/drf-throttling-complete-guide/)