바닐라 요청률 제한 가이드
요청률 제한은 시간 창 안에서 설정된 횟수만큼 실행하도록 허용합니다. 용량이 남아 있는 동안 호출이 즉시 실행됩니다. 제한에 도달하면 용량이 다시 생길 때까지 이후 호출을 거부합니다.
TanStack Pacer는 주로 클라이언트 측 작업을 위한 인메모리 요청률 제한기를 제공합니다. 서버 측 JavaScript에서 실행할 수는 있지만 분산 할당량 또는 강제 적용 시스템은 아닙니다.
요청률 제한의 작동 방식
이 예제는 창마다 세 번의 실행을 허용합니다.
Rate Limiting (limit: 3 calls per window)
Timeline: [1 second per tick]
Window 1 | Window 2
Calls: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
Executed: ✅ ✅ ✅ ❌ ❌ ✅ ✅
[=== 3 allowed ===][=== blocked until reset ===][=== new window ===]
요청률 제한은 버스트를 허용합니다. 수락된 호출에 균등한 간격을 두지는 않습니다.
요청률 제한을 사용하는 경우
다음과 같은 경우 요청률 제한을 선택합니다.
- 클라이언트 작업이 고정 할당량을 따라야 합니다.
- 할당량을 소진할 때까지 호출을 즉시 실행할 수 있어야 합니다.
- 거부된 호출을 버리거나 별도로 처리할 수 있습니다.
- 남은 용량이나 용량이 복구될 때까지의 시간을 측정해야 합니다.
다음과 같은 경우 다른 유틸리티를 선택합니다.
- 실행 사이에 균등한 간격을 두어야 합니다. 스로틀을 사용합니다.
- 최종 호출만 중요합니다. 디바운스를 사용합니다.
- 모든 작업을 최종적으로 실행해야 합니다. 큐를 사용합니다.
- 항목을 함께 실행해야 합니다. 배칭을 사용합니다.
- Promise 결과, 재시도 또는 중단 지원이 필요합니다. 비동기 요청률 제한을 사용합니다.
창 타입
windowType 옵션은 용량이 복구되는 시점을 제어합니다.
고정 창
고정 창은 첫 실행이 수락될 때 시작됩니다. 수락된 모든 실행은 해당 창이 끝날 때까지 횟수에 포함됩니다. 그 후 용량이 한꺼번에 재설정됩니다.
const limiter = new RateLimiter(sendEvent, {
limit: 3,
window: 1000,
windowType: 'fixed',
})
고정 창은 창이 재설정될 때 전체 할당량을 사용할 수 있게 되므로 경계 근처에서 버스트를 허용할 수 있습니다.
슬라이딩 창
슬라이딩 창은 수락된 각 실행을 별도로 추적합니다. 오래된 타임스탬프가 창에서 벗어날 때 실행 하나씩 용량이 복구됩니다.
Sliding Window (limit: 3 calls per window)
Timeline: [1 second per tick]
Calls: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
Executed: ✅ ✅ ✅ ❌ ✅
[=== full ===][oldest execution expires][=== one available ===]
const limiter = new RateLimiter(sendEvent, {
limit: 3,
window: 1000,
windowType: 'sliding',
})
용량을 한꺼번에 복구하지 않고 점진적으로 복구해야 한다면 슬라이딩 창을 사용합니다.
TanStack Pacer에서 요청률 제한 사용하기
TanStack Pacer는 두 가지 코어 API를 제공합니다.
rateLimit은 요청률이 제한된 함수를 반환합니다.RateLimiter는 헬퍼 메서드, 콜백, 동적 옵션, 상태를 노출합니다.
편의 함수
import { rateLimit } from '@tanstack/pacer'
const sendLimitedEvent = rateLimit(sendEvent, {
limit: 5,
window: 60_000,
})
sendLimitedEvent('event-1') // true
sendLimitedEvent('event-2') // true
반환된 불리언 값은 제한에 따라 호출이 수락되었는지를 나타냅니다. 래핑된 함수의 반환 값은 포함하지 않습니다.
클래스 API
import { RateLimiter } from '@tanstack/pacer'
const limiter = new RateLimiter(sendEvent, {
limit: 5,
window: 60_000,
onReject: (limiter) => {
console.log('Try again in:', limiter.getMsUntilNextWindow())
},
})
if (!limiter.maybeExecute('event')) {
showRateLimitMessage()
}
제한기가 활성화되어 있으면 maybeExecute()는 수락된 실행에 true를, 거부된 호출에 false를 반환합니다.
결과 및 오류
동기 요청률 제한기는 래핑된 함수의 반환 값을 유지하거나 오류를 포착하지 않습니다. 오류는 maybeExecute()에서 전파됩니다. 오류를 발생시킨 실행은 실행 창에 추가되지 않습니다.
Promise 결과와 설정 가능한 비동기 오류 처리가 필요하다면 비동기 요청률 제한을 사용합니다.
거부된 호출 처리하기
거부된 호출은 나중에도 실행되지 않습니다. 불리언 반환 값이나 onReject를 사용해 피드백을 제공하거나 다른 곳에서 재시도하거나 작업을 큐에 넣습니다.
const limiter = new RateLimiter(sendEvent, {
limit: 2,
window: 1000,
onReject: (limiter) => {
console.log('Rejected calls:', limiter.store.state.rejectionCount)
},
})
거부된 작업을 최종적으로 반드시 실행해야 한다면 일반적으로 큐 처리기가 더 적합합니다.
용량 검사하기
클래스는 계산된 헬퍼 두 개를 제공합니다.
limiter.getRemainingInWindow() // Accepted executions still available.
limiter.getMsUntilNextWindow() // Time until at least one execution is available.
두 헬퍼 모두 현재 limit, window, windowType, 실행 기록을 사용합니다.
제한기 재설정 및 구성하기
reset()은 실행 타임스탬프, 카운터, 정리 타이머를 지웁니다. 다음 호출은 전체 용량으로 시작합니다.
limiter.reset()
설정을 업데이트하려면 setOptions()를 사용합니다.
limiter.setOptions({
limit: 10,
window: 30_000,
})
옵션을 변경해도 기존 실행 기록은 지워지지 않습니다. 새 설정을 새로운 창으로 시작해야 한다면 reset()을 호출합니다.
enabled, limit, window 옵션에는 제한기 인스턴스를 받는 함수를 지정할 수 있습니다.
const limiter = new RateLimiter(sendEvent, {
enabled: (limiter) => limiter.store.state.executionCount < 100,
limit: (limiter) => (limiter.store.state.rejectionCount > 10 ? 2 : 5),
window: 60_000,
})
제한기를 비활성화하면 래핑된 함수의 실행을 막습니다. 기존 실행 기록은 삭제하지 않습니다.
실행 관찰하기
onExecute는 실행된 인수와 제한기 인스턴스를 받습니다. onReject는 제한기 인스턴스를 받습니다.
const limiter = new RateLimiter(sendEvent, {
limit: 5,
window: 1000,
onExecute: (args, limiter) => {
console.log('Sent:', args)
console.log('Remaining:', limiter.getRemainingInWindow())
},
onReject: (limiter) => {
console.log('Rejected:', limiter.store.state.rejectionCount)
},
})
타입 검사를 거친 설정을 여러 인스턴스에서 공유하려면 rateLimiterOptions()로 정의합니다.
상태
애플리케이션이 유지한 일부 상태를 복원하려면 부분 스냅샷을 initialState로 전달합니다. 이 스냅샷은 기본값과 병합됩니다. 지속 가능한 필드만 복원합니다. 대기 중인 타이머는 복원되지 않습니다.
일반적으로 유용한 상태는 다음과 같습니다.
executionCount: 완료된 수락 실행의 총횟수입니다.executionTimes: 현재 창 계산에 사용되는 타임스탬프입니다.isExceeded: 현재 제한에 도달했는지 나타냅니다.rejectionCount: 창이 가득 차서 거부된 호출 수입니다.status:'disabled','exceeded'또는'idle'입니다.
전체 옵션과 상태 타입은 RateLimiter API 레퍼런스를 참고합니다.