본문으로 건너뛰기
버전: 10.x

요청 제한 (Rate Limiting)

소개

라라벨에서는 애플리케이션의 캐시와 함께 사용할 수 있는 단순한 요청 제한(rate limiting) 추상화 기능을 제공합니다. 이를 통해 지정한 시간 동안 어떤 작업이 허용되는지 손쉽게 제한할 수 있습니다.

[!NOTE] 만약 외부에서 들어오는 HTTP 요청에 대한 속도 제한이 궁금하다면, 속도 제한 미들웨어 문서를 참고하시기 바랍니다.

캐시 설정

일반적으로 요청 제한 기능은 애플리케이션의 cache 설정 파일 내 default 키에 정의된 기본 캐시 드라이버를 사용합니다. 하지만 요청 제한 기능이 사용할 캐시 드라이버를 직접 지정하고 싶다면, 애플리케이션의 cache 설정 파일에 limiter 키를 정의하면 됩니다.

'default' => 'memcached',

'limiter' => 'redis',

기본 사용법

Illuminate\Support\Facades\RateLimiter 파사드를 사용하여 요청 제한 기능과 상호작용할 수 있습니다. 요청 제한 기능에서 가장 간단하게 사용할 수 있는 메서드는 attempt입니다. 이 메서드는 주어진 콜백을 지정한 초(seconds) 동안 실행 횟수를 제한합니다.

attempt 메서드는 해당 콜백에 남아 있는 실행 가능 횟수가 없다면 false를, 남아 있다면 콜백의 반환값 혹은 true를 반환합니다. attempt 메서드의 첫 번째 인수는 제한을 적용할 "키"로, 제한할 동작을 식별할 수 있는 임의의 문자열을 지정할 수 있습니다.

use Illuminate\Support\Facades\RateLimiter;

$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perMinute = 5,
function() {
// Send message...
}
);

if (! $executed) {
return 'Too many messages sent!';
}

필요하다면 attempt 메서드에 네 번째 인수를 추가할 수 있습니다. 이 네 번째 인수는 "만료 시간(decay rate)"으로, 사용할 수 있는 시도 횟수가 초기화될 때까지의 초(seconds)를 의미합니다. 예를 들어, 위 예시를 2분(120초)마다 5번 시도 가능한 형태로 수정할 수 있습니다.

$executed = RateLimiter::attempt(
'send-message:'.$user->id,
$perTwoMinutes = 5,
function() {
// Send message...
},
$decayRate = 120,
);

시도 횟수 수동 증가

요청 제한 기능을 직접 제어하고 싶을 때 사용할 수 있는 다양한 메서드가 있습니다. 예를 들어, tooManyAttempts 메서드를 사용하면 특정 제한 키가 분당 허용된 최대 시도 횟수를 초과했는지 확인할 수 있습니다.

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
return 'Too many attempts!';
}

RateLimiter::increment('send-message:'.$user->id);

// Send message...

또는, remaining 메서드를 사용해 특정 키의 남은 시도 가능 횟수를 가져올 수 있습니다. 시도 가능 횟수가 있다면, increment 메서드를 직접 호출해서 시도 횟수를 증가시킬 수 있습니다.

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
RateLimiter::increment('send-message:'.$user->id);

// Send message...
}

또한, 만약 한 번에 1 이상으로 시도 횟수를 증가시키고 싶다면, increment 메서드에 원하는 증가값을 지정할 수 있습니다.

RateLimiter::increment('send-message:'.$user->id, amount: 5);

제한 재사용 가능 시간 확인

시도 횟수가 모두 소진된 경우에는 availableIn 메서드를 사용해 추가 시도가 가능해지기까지 남은 초(seconds)를 확인할 수 있습니다.

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
$seconds = RateLimiter::availableIn('send-message:'.$user->id);

return 'You may try again in '.$seconds.' seconds.';
}

RateLimiter::increment('send-message:'.$user->id);

// Send message...

시도 횟수 초기화

clear 메서드를 사용하면 특정 제한 키의 시도 횟수를 초기화할 수 있습니다. 예를 들어, 메시지를 수신자가 읽었을 때 시도 횟수를 리셋하고 싶다면 다음과 같이 할 수 있습니다.

use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;

/**
* Mark the message as read.
*/
public function read(Message $message): Message
{
$message->markAsRead();

RateLimiter::clear('send-message:'.$message->user_id);

return $message;
}