@searchos/bot-proxy 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,18 @@
4
4
 
5
5
  ## 워크플로우
6
6
 
7
+ ### 봇 분류
8
+
9
+ ```
10
+ 봇 요청 (UA 기반 감지)
11
+
12
+ ├── AI 봇 (isAi: true) + aiRender 활성화
13
+ │ ai 캐시 → desktop 폴백 → origin
14
+
15
+ └── 일반 봇 (검색엔진, SNS, SEO 등)
16
+ desktop/mobile 캐시 → origin
17
+ ```
18
+
7
19
  ### Next.js + CloudFront (S3)
8
20
 
9
21
  ```
@@ -14,25 +26,28 @@ Next.js middleware
14
26
 
15
27
  ├── nextjsProxy() 호출
16
28
  │ │
29
+ │ ├── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
30
+ │ │ → 프리렌더 서버에서 프록시
31
+ │ │
17
32
  │ ├── UA로 봇 감지 (detectBot)
18
33
  │ │ 봇 아님 → null 반환 → 기존 middleware 실행
19
34
  │ │
20
35
  │ ├── IP 대역 검증 (verifyBotIp) → 로그에 ip_verified 기록
21
36
  │ │
22
- │ ├── 캐시 계산 (computeCacheKey)
23
- │ │ URL path → 정규화 → MD5 → {hash}_{device}
24
- │ │
25
- ├── CloudFront에서 캐시 조회
26
- │ │ GET https://{cf도메인}/v2/{사이트도메인}/{hash}_{device}.html
37
+ │ ├── [AI + aiRender + aiPath 매칭]
38
+ │ │
39
+ │ │ ├── ai 캐시 조회: {cf}/v2/{도메인}/{hash}_ai.html
40
+ │ │ 히트 HIT-AI 반환 + ai 워밍
27
41
  │ │ │
28
- │ │ ├── 히트 캐시 HTML 반환
29
- │ │ │ + 백그라운드: 로그 전송 + 캐시 워밍 요청
42
+ │ │ ├── desktop 폴백: {cf}/v2/{도메인}/{hash}_desktop.html
43
+ │ │ │ 히트 HIT-DESKTOP 반환 + ai 워밍
30
44
  │ │ │
31
- │ │ └── 미스 → null 반환 기존 middleware 실행
32
- │ │ + 백그라운드: 봇 로그 전송 + 캐시 워밍 요청
45
+ │ │ └── 미스 → null (origin) + ai 워밍 + 일반 워밍
33
46
  │ │
34
- │ └── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
35
- 프리렌더 서버에서 프록시
47
+ │ └── [일반 봇]
48
+ 캐시 조회: {cf}/v2/{도메인}/{hash}_{device}.html
49
+ │ 히트 → HIT 반환 + 워밍
50
+ │ 미스 → null (origin) + 워밍
36
51
 
37
52
 
38
53
  기존 middleware 로직 (인증, i18n, 리다이렉트 등)
@@ -48,25 +63,31 @@ Cloudflare Worker
48
63
 
49
64
  ├── cloudflareProxy() 호출
50
65
  │ │
66
+ │ ├── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
67
+ │ │ → 프리렌더 서버에서 프록시
68
+ │ │
51
69
  │ ├── UA로 봇 감지 (detectBot)
52
70
  │ │ 봇 아님 → null 반환 → origin fetch
53
71
  │ │
54
- │ ├── IP 대역 검증 (verifyBotIp) → 로그에 ip_verified 기록
72
+ │ ├── KV 바인딩 확인 (env.V2_CACHE)
73
+ │ │ 없음 → null 반환
55
74
  │ │
56
- │ ├── 캐시 계산 (computeCacheKey)
57
- │ │ URL path → 정규화 → MD5 → {hash}_{device}
75
+ │ ├── IP 대역 검증 (verifyBotIp) → 로그에 ip_verified 기록
58
76
  │ │
59
- │ ├── KV에서 캐시 조회
60
- │ │ env.V2_CACHE.get("{hash}_{device}")
77
+ │ ├── [AI + aiRender + aiPath 매칭]
78
+ │ │
79
+ │ │ ├── ai 캐시 조회: V2_CACHE.get("{hash}_ai")
80
+ │ │ │ 히트 → HIT-AI 반환 + waitUntil(로그 + ai 워밍)
61
81
  │ │ │
62
- │ │ ├── 히트 캐시 HTML 반환
63
- │ │ │ + waitUntil: 봇 로그 전송 + 캐시 워밍 요청
82
+ │ │ ├── desktop 폴백: V2_CACHE.get("{hash}_desktop")
83
+ │ │ │ 히트 → HIT-DESKTOP 반환 + waitUntil(로그 + ai 워밍)
64
84
  │ │ │
65
- │ │ └── 미스 → null 반환 origin fetch
66
- │ │ + waitUntil: 봇 로그 전송 + 캐시 워밍 요청
85
+ │ │ └── 미스 → null (origin) + waitUntil(로그 + ai 워밍 + 일반 워밍)
67
86
  │ │
68
- │ └── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
69
- 프리렌더 서버에서 프록시
87
+ │ └── [일반 봇]
88
+ 캐시 조회: V2_CACHE.get("{hash}_{device}")
89
+ │ 히트 → HIT 반환 + waitUntil(로그 + 워밍)
90
+ │ 미스 → null (origin) + waitUntil(로그 + 워밍)
70
91
 
71
92
 
72
93
  origin (고객 서버)
@@ -78,6 +99,26 @@ origin (고객 서버)
78
99
  npm install @searchos/bot-proxy
79
100
  ```
80
101
 
102
+ ## 옵션
103
+
104
+ ### 공통 옵션
105
+
106
+ | 옵션 | 타입 | 필수 | 기본값 | 설명 |
107
+ |------|------|------|--------|------|
108
+ | `projectId` | `string` | O | | SearchOS 프로젝트 ID |
109
+ | `siteDomain` | `string` | O | | 사이트 도메인 (`https://` 자동 제거) |
110
+ | `prerenderDomain` | `string` | O | | 프리렌더 서버 URL |
111
+ | `botLogEndpoint` | `string` | O | | 봇 로그 엔드포인트 |
112
+ | `aiRender` | `boolean` | | `true` | AI 봇에게 ai 캐시 우선 서빙 |
113
+ | `ocr` | `boolean` | | `true` | AI 워밍 요청 시 OCR 포함 여부 |
114
+ | `aiPathPrefixes` | `string[]` | | `[]` | AI 렌더 적용 경로 prefix (빈 배열 = 전체 경로) |
115
+
116
+ ### Next.js 전용
117
+
118
+ | 옵션 | 타입 | 필수 | 설명 |
119
+ |------|------|------|------|
120
+ | `cloudfrontDomain` | `string` | O | CloudFront 배포 도메인 (S3 캐시 조회용) |
121
+
81
122
  ## 사용법
82
123
 
83
124
  ### Next.js
@@ -88,15 +129,18 @@ import { nextjsProxy } from "@searchos/bot-proxy";
88
129
 
89
130
  export async function middleware(request) {
90
131
  const res = await nextjsProxy(request, {
91
- projectId: "...", // SearchOS 프로젝트 ID
92
- siteDomain: "example.com", // 사이트 도메인
93
- cloudfrontDomain: "...", // CloudFront 배포 도메인
94
- prerenderDomain: "...", // 프리렌더 서버 도메인
95
- botLogEndpoint: "...", // 봇 로그 엔드포인트
132
+ projectId: "...",
133
+ siteDomain: "example.com",
134
+ cloudfrontDomain: "https://d1234.cloudfront.net",
135
+ prerenderDomain: "https://proxy.searchos.kr",
136
+ botLogEndpoint: "https://botlog.searchos.kr/bot-ping",
137
+ // AI 옵션 (모두 선택사항)
138
+ aiRender: true, // AI 봇에게 ai 캐시 우선 서빙
139
+ ocr: true, // AI 워밍 시 OCR 포함
140
+ aiPathPrefixes: ["/blog/"], // /blog/ 하위만 AI 렌더 적용
96
141
  });
97
142
  if (res) return res;
98
143
 
99
- // 기존 middleware 로직
100
144
  return NextResponse.next();
101
145
  }
102
146
  ```
@@ -110,17 +154,28 @@ export default {
110
154
  async fetch(request, env, ctx) {
111
155
  const res = await cloudflareProxy(request, env, ctx, {
112
156
  projectId: "...",
113
- siteDomain: "https://example.com",
114
- prerenderDomain: "...",
115
- botLogEndpoint: "...",
157
+ siteDomain: "example.com",
158
+ prerenderDomain: "https://proxy.searchos.kr",
159
+ botLogEndpoint: "https://botlog.searchos.kr/bot-ping",
160
+ // AI 옵션 (모두 선택사항)
161
+ aiRender: true,
162
+ ocr: true,
163
+ aiPathPrefixes: [], // 빈 배열 = 전체 경로에 AI 렌더 적용
116
164
  });
117
165
  if (res) return res;
118
166
 
119
- return fetch(request); // origin
167
+ return fetch(request);
120
168
  }
121
169
  };
122
170
  ```
123
171
 
172
+ > **KV 바인딩 필수**: Cloudflare Worker는 `wrangler.toml`에 `V2_CACHE` KV namespace 바인딩이 필요.
173
+ > ```toml
174
+ > [[kv_namespaces]]
175
+ > binding = "V2_CACHE"
176
+ > id = "your-kv-namespace-id"
177
+ > ```
178
+
124
179
  ## 캐시 키 규칙
125
180
 
126
181
  ```
@@ -178,12 +233,20 @@ UA 기반으로 6개 카테고리의 봇을 감지:
178
233
 
179
234
  ## 응답 헤더
180
235
 
236
+ 캐시 히트 시에만 응답에 포함 (미스 시 null 반환, 헤더 없음).
237
+
181
238
  | 헤더 | 값 | 설명 |
182
239
  |------|-----|------|
183
- | X-Cache | HIT / MISS | 캐시 히트 여부 |
240
+ | X-Cache | `HIT-AI` / `HIT-DESKTOP` / `HIT` | 어떤 캐시에서 서빙되었는지 |
184
241
  | X-Bot | googlebot, chatgpt-user 등 | 감지된 봇 이름 |
185
242
  | X-Bot-Verified | true / false | IP 대역 검증 결과 |
186
243
 
244
+ | X-Cache 값 | 의미 |
245
+ |-------------|------|
246
+ | `HIT-AI` | AI 전용 캐시에서 서빙 |
247
+ | `HIT-DESKTOP` | AI 봇이지만 ai 캐시 미스, desktop 폴백으로 서빙 |
248
+ | `HIT` | 일반 봇, desktop/mobile 캐시에서 서빙 |
249
+
187
250
  ## 패키지 구조
188
251
 
189
252
  ```