Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7241b0d
docs: 429 계측과 의존성 정비 설계 추가
hmmhmmhm Jul 21, 2026
28b4114
docs: 429 계측 구현 계획 추가
hmmhmmhm Jul 21, 2026
6219da5
refactor: 운영 API 인증 로직 공통화
hmmhmmhm Jul 21, 2026
7b25be1
fix: 운영 API 인증 비교 타이밍 공격 방지
hmmhmmhm Jul 21, 2026
e58320b
feat: 정확한 429 원장 저장소 추가
hmmhmmhm Jul 21, 2026
4536370
fix: 429 원장 정확성과 보관 집계 보강
hmmhmmhm Jul 22, 2026
6ee7df2
fix: 429 원장 알람 선확정과 Node 20 테스트 지원
hmmhmmhm Jul 22, 2026
254480d
feat: 호출 제한 객체에 429 원장 라우팅 추가
hmmhmmhm Jul 22, 2026
d0eae33
fix: 호출 제한 통계 쿼리 형식 검증 강화
hmmhmmhm Jul 22, 2026
686000d
fix: 호출 제한 계측 저장소 인스턴스 재사용
hmmhmmhm Jul 22, 2026
451d6e0
feat: 429 응답을 정확한 원장 기록과 연결
hmmhmmhm Jul 22, 2026
ddd0539
fix: 호출 제한 응답 검증과 날짜 전환 보강
hmmhmmhm Jul 22, 2026
aee4f00
fix: 호출 제한 초기화 시각 계약 검증
hmmhmmhm Jul 22, 2026
d87c0d5
test: 호출 제한 통합 테스트 도우미 분리
hmmhmmhm Jul 22, 2026
747d645
feat: 인증된 429 통계 API 추가
hmmhmmhm Jul 22, 2026
1c29292
fix: 429 통계 집계 검증과 안전 로그 강화
hmmhmmhm Jul 22, 2026
d45a19c
docs: 정확한 429 통계 조회 방법 추가
hmmhmmhm Jul 22, 2026
552d41d
test: 429 통계 문서 계약 검증 강화
hmmhmmhm Jul 22, 2026
2b4b6cf
fix: 429 통계 날짜 및 보관 계약 명시
hmmhmmhm Jul 22, 2026
083b819
fix: 429 통계 예시 만료 방지
hmmhmmhm Jul 22, 2026
faab0cf
chore: 의존성과 보안 패키지 업데이트
hmmhmmhm Jul 22, 2026
201076d
ci: setup-node v7으로 업데이트
hmmhmmhm Jul 22, 2026
e1e6ecd
docs: 기여 환경의 Node 버전 정정
hmmhmmhm Jul 22, 2026
952b114
fix: KST 전환 시 429 계측과 통계 일관성 보장
hmmhmmhm Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'npm'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/external-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sync-worker-secrets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/workers-invocations-chart.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '24'
cache: npm
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
24
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

## 사전 준비

- Node.js: `20.x` (`.nvmrc` 참고)
- npm: Node 20에 포함된 버전 사용 권장
- Node.js: `24.x` (`.nvmrc` 참고)
- npm: `11.x` (Node.js 24에 포함된 버전 사용 권장)

```bash
nvm use
Expand Down
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,51 @@ curl -H "Authorization: Bearer $HEALTH_CHECK_SECRET" \

Better Stack 같은 외부 모니터링에서는 `fail`을 장애 알림 기준으로 보고, `degraded`는 느린 외부 API나 응답 품질 저하를 추적하는 경고 신호로 봅니다.

### 운영 통계

일일 호출 제한으로 차단한 요청의 집계는 인증된 `GET /api/rate-limit/stats`에서 조회합니다. 헬스 체크와 같은 `HEALTH_CHECK_SECRET`을 사용하며, 다음 두 인증 헤더를 모두 지원합니다.

```bash
curl -H "Authorization: Bearer $HEALTH_CHECK_SECRET" \
"https://mcp.aka.page/api/rate-limit/stats"

curl -H "x-health-check-key: $HEALTH_CHECK_SECRET" \
"https://mcp.aka.page/api/rate-limit/stats?service=cgv"
```

쿼리 필터는 `from`, `to`, `service`입니다. `from`과 `to`는 함께 지정하거나 둘 다 생략해야 하며 날짜 형식은 `YYYY-MM-DD`입니다. `service`에는 `oliveyoung`, `cgv`, `cu`, `gs25`, `lottemart`만 사용할 수 있습니다. 날짜를 생략하면 현재 KST 일자를 포함한 최근 7일을 조회합니다. 조회 가능한 보관 범위는 현재 KST 일자와 그 이전 29일이며, 한 번에 KST 달력 날짜 기준 최대 30일을 요청할 수 있습니다.

성공 응답은 전체 합계와 일별·서비스별 차단 요청 수와 고유 차단 주체 수를 제공합니다.

```json
{
"success": true,
"data": {
"totals": {
"blockedRequests": 3,
"uniqueIdentities": 2
},
"daily": [
{
"day": "2026-07-22",
"blockedRequests": 3,
"uniqueIdentities": 2
}
],
"services": [
{
"day": "2026-07-22",
"service": "cgv",
"blockedRequests": 3,
"uniqueIdentities": 2
}
]
}
}
```

데이터는 30일 동안 보관하며 집계 응답은 원본 호출 주체나 IP를 노출하지 않습니다. Worker가 생성한 `DAILY_RATE_LIMIT_EXCEEDED` 결정 중 원장 커밋에 성공한 경우만 정확한 집계 범위에 포함됩니다. Cloudflare 또는 네트워크 계층의 429와 클라이언트 전송 결과, 연결 종료 결과는 이 범위에 포함되지 않습니다. 원장 쓰기에 실패하면 요청을 fail-open 처리하고 애플리케이션 429를 반환하지 않습니다. 통계는 이 기능의 배포 시점부터 수집하며 이전 429는 소급 집계하지 않습니다.

배포 전 로컬에서 CLI 모드까지 확인할 때는 아래 명령을 사용합니다.

```bash
Expand Down
2 changes: 1 addition & 1 deletion biome.jsonc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.0/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.5/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
31 changes: 18 additions & 13 deletions docs/service-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,13 @@ MCP를 지원하지 않는 서비스를 위한 GET 기반 REST API입니다.
| `GET /api/cgv/theaters` | CGV 극장 목록 조회 |
| `GET /api/cgv/movies` | CGV 영화 목록 조회 |
| `GET /api/cgv/timetable` | CGV 상영 시간표 조회 |
| `GET /api/rate-limit/stats` | 인증된 일일 호출 제한 운영 통계 |

### 호출 제한 운영 통계

`GET /api/rate-limit/stats` 요청은 `HEALTH_CHECK_SECRET`을 `Authorization: Bearer` 또는 `x-health-check-key` 헤더로 전달해 인증합니다. `from`과 `to`는 둘 다 생략하거나 함께 제공해야 합니다. `service`에는 `oliveyoung`, `cgv`, `cu`, `gs25`, `lottemart`만 사용할 수 있습니다. 날짜를 생략하면 현재 KST 일자를 포함한 최근 7일을 조회합니다. 차단 이벤트는 30일 동안 보관합니다. 보관 범위 안에서 KST 달력 날짜 기준 최대 30일을 요청할 수 있습니다. 응답은 전체, 일별, 서비스별 차단 요청 수와 고유 차단 주체 수 집계만 반환하며 원본 호출 주체나 IP를 노출하지 않습니다.

Worker가 생성한 `DAILY_RATE_LIMIT_EXCEEDED` 결정 중 원장 커밋에 성공한 경우만 정확한 집계 범위에 포함됩니다. Cloudflare 또는 네트워크 계층의 429와 클라이언트 전송 결과, 연결 종료 결과는 이 범위에 포함되지 않습니다. 원장 쓰기에 실패하면 요청을 fail-open 처리하고 애플리케이션 429를 반환하지 않습니다. 통계는 이 기능의 배포 시점부터 수집하며 이전 429는 소급 집계하지 않습니다.

### 제품 검색

Expand Down Expand Up @@ -500,16 +507,16 @@ GET /api/cu/stores?keyword={키워드}&lat={위도}&lng={경도}
GET /api/cu/inventory?keyword={검색어}&lat={위도}&lng={경도}
```

| 파라미터 | 필수 | 설명 |
| :------------- | :--: | :----------------------------- |
| `keyword` | O | 검색 키워드 (예: 과자, 컵라면) |
| `lat` | | 위도 (기본값: 37.5665) |
| `lng` | | 경도 (기본값: 126.978) |
| `storeKeyword` | | 주변 매장 필터 키워드 |
| `size` | | 검색 결과 수 (기본값: 20) |
| `offset` | | 검색 시작 오프셋 (기본값: 0) |
| `searchSort` | | 정렬 방식 (기본값: `recom`) |
| `storeLimit` | | 매장 결과 수 (기본값: 10) |
| 파라미터 | 필수 | 설명 |
| :------------- | :--: | :------------------------------ |
| `keyword` | O | 검색 키워드 (예: 과자, 컵라면) |
| `lat` | | 위도 (기본값: 37.5665) |
| `lng` | | 경도 (기본값: 126.978) |
| `storeKeyword` | | 주변 매장 필터 키워드 |
| `size` | | 검색 결과 수 (기본값: 20) |
| `offset` | | 검색 시작 오프셋 (기본값: 0) |
| `searchSort` | | 정렬 방식 (기본값: `recom`) |
| `storeLimit` | | 매장 결과 수 (기본값: 10) |
| `storeCheck` | | `false`이면 주변 매장 조회 생략 |

### 올리브영 재고 확인
Expand Down Expand Up @@ -863,9 +870,7 @@ class CuService implements ServiceProvider {
};

getTools() {
return [
/* cu_search_products, cu_find_stores 등 */
];
return [/* cu_search_products, cu_find_stores 등 */];
}
}

Expand Down
Loading