# Worksmobile API Rate Limit 정책

작성일: 2026-06-09

## 목적

Worksmobile relay worker는 외부 API 제한을 초과하지 않도록 Works API 호출에 rate limit을 적용한다.
일반 조회, 수동 enqueue, 비교 화면처럼 backend 내부 처리량이 병목이 아닌 경로는 기본 제약하지 않는다.

## 기준

- 제한 단위: API별
- 제한값: 240 requests/min
- 환산 간격: 같은 API key 기준 요청 시작 간격 250ms 이상
- API key: HTTP method + normalized path
- query string은 rate limit key에서 제외한다.
- 리소스 ID가 포함된 path segment는 `{id}`로 정규화한다.

예:

- `POST /v1.0/users`
- `PATCH /v1.0/users/{id}`
- `POST /v1.0/users/{id}/alias-emails/{id}`
- `GET /v1.0/orgunits`
- `PATCH /scim/v2/Users/{id}`
- `POST /oauth2/v2.0/token`

## 적용 범위

Backend `WorksmobileHTTPClient`는 optional limiter 주입 지점을 제공한다.
기본 client 생성자는 limiter를 갖지 않고, `WorksmobileRelayWorker`에 전달되는 client copy에만 limiter를 적용한다.
또한 Worksmobile relay worker에만 Redis leader lock을 적용해 여러 backend replica 중 하나만 outbox relay를 수행하게 한다.

적용 대상:

- Worksmobile relay worker가 수행하는 Directory API 조회/쓰기
- Worksmobile relay worker가 수행하는 SCIM API 조회/쓰기
- Worksmobile relay worker가 수행하는 OAuth token 요청

기본 제외 대상:

- admin 화면의 조회/비교 API
- 수동 sync 요청의 enqueue 단계
- Worksmobile outbox에 job을 적재하는 내부 처리

## 구현 정책

- production 기본 client는 limiter를 갖지 않는다.
- relay worker에는 limiter를 가진 client copy를 전달한다.
- relay worker는 Redis leader lock을 보유한 replica에서만 `worksmobile_outbox` ready job을 조회한다.
- leader lock은 Worksmobile relay 전용이며, 다른 relay worker나 일반 backend 작업에는 적용하지 않는다.
- leader lock 설정은 환경변수로 열지 않고 코드 상수로 고정한다.
  - key: `baron:worksmobile:relay:leader`
  - ttl: 30s
- 기본 limiter는 API key별 요청 시작 시각을 직렬화한다.
- context가 취소되면 대기 중인 요청은 `ctx.Err()`로 실패한다.
- 테스트나 특수 호출자는 `WorksmobileRateLimiter`를 주입해 limiter 동작을 검증하거나 대체할 수 있다.

## 운영 메모

- 현재 worker 정책은 burst를 허용하지 않는 보수적 제한이다.
- 외부 API가 `Retry-After`를 제공하는 경우, 별도 retry/backoff 정책을 추가할 수 있다.
- 여러 backend replica에서 relay worker가 동시에 시작되더라도 Redis leader lock으로 하나의 replica만 relay를 수행한다.
- Redis 연결이 초기화되지 않은 환경에서는 leader lock을 주입하지 않으며, 단일 인스턴스/dev 실행처럼 기존 방식으로 동작한다.
