Spillway 연동 가이드
사이트에 접속이 몰릴 때 방문자를 순서대로 줄 세워, 서버가 감당할 수 있는 속도로만 들여보내는 대기열을 붙이는 방법입니다. 사이트 코드에는 몇 줄만 넣고, 어느 페이지·버튼에 대기열을 걸지와 입장 속도는 관리 콘솔에서 바로 바꿉니다.
1준비물
Spillway 담당자에게 아래 네 가지를 받습니다. 관리 콘솔에서 직접 확인할 수 있는 것은 콘솔 위치를 함께 적었습니다.
| 항목 | 예시 | 어디서 |
|---|---|---|
| 고객사 id | acme-shop | 콘솔 [사이트 연동] → 연결 정보 |
| 엔진 주소 | https://spillway-engine.example.workers.dev | 콘솔 [사이트 연동] → 연결 정보 |
| 서명 키 | 43자 문자열 (비밀 값) | 콘솔 [사이트 연동] → [서명 키 보기] |
| 콘솔 계정 | 이메일 + 임시 비밀번호 | 담당자가 발급 (첫 로그인 때 비밀번호 변경) |
현재 가드는 Cloudflare Workers 로 서빙되는 사이트를 지원합니다. 다른 환경(Nginx, Spring 등)은 담당자에게 문의해 주세요.
2대기 타입 고르기
대기실마다 대기 타입을 하나 고릅니다. 한 사이트에 두 타입의 대기실을 함께 둘 수 있습니다.
단일 페이지 사용 가능
정해진 주소에 들어올 때 줄을 세웁니다. 예: 오픈 이벤트 페이지, 메인 페이지. 사이트 코드는 가드만 있으면 됩니다.
버튼·이벤트 사용 가능
페이지는 자유롭게 보고, 버튼을 누를 때(구매·예약·전송) 줄을 세웁니다. 페이지에 스크립트 한 줄과 버튼 속성이 필요합니다.
구간(시작~종료) 준비 중
시작 주소부터 종료 주소까지 한 흐름(예: 주문서~결제)에 머무는 인원을 제한합니다.
3가드 설치 (공통)
가드는 사이트 Worker 맨 앞에서 요청을 검사하는 작은 라이브러리입니다. 두 대기 타입 모두 이 단계가 필요합니다.
① 설치
npm i github:chandarasoft/spillway-guard#v0.5.0
② Worker 코드 맨 앞에 추가
import { guardPage } from "spillway-guard";
export default {
async fetch(request, env, ctx) {
const blocked = await guardPage(request, env, {
tenant: "acme-shop", // 고객사 id
engineUrl: env.SPILLWAY_ENGINE_URL, // 엔진 주소
});
if (blocked) return blocked; // 대기 화면으로 보내거나, 입장권 없는 API 요청을 막음
// … 기존 처리
},
};어느 주소·API 에 대기열을 걸지는 코드에 적지 않습니다. 가드가 엔진에서 대기실 규칙을 받아 오므로(10초 캐시), 규칙을 바꿔도 사이트를 다시 배포할 필요가 없습니다.
③ 설정 값 넣기
"vars": {
"SPILLWAY_ENGINE_URL": "https://spillway-engine.example.workers.dev"
}npx wrangler secret put SPILLWAY_TOKEN_SECRET
4단일 페이지
콘솔 설정
- [대기실] → [새 대기실] → 대기 타입 단일 페이지
- 대기 대상 경로에 줄을 세울 주소를 넣습니다.
*는 그 아래 모든 주소입니다.
예:/,/event/*· 제외:/event/notice - [주소 확인] 칸에 실제 주소를 넣어 줄을 서는지 바로 확인합니다.
- 입장 제어에서 초당 입장 인원을 정하고 저장합니다. 저장 즉시 반영됩니다.
방문자가 겪는 흐름
사이트 코드는 3단계(가드)만으로 끝입니다. 대기 화면의 문구·색상·로고는 콘솔 [대기 화면]에서 바꾸고 미리보기로 확인합니다.
5버튼·이벤트
콘솔 설정
- [대기실] → [새 대기실] → 대기 타입 버튼·이벤트, 대기실 id 예:
checkout - 대기 대상 API 에 막을 요청을 넣습니다. 예:
POST /api/orders(메서드 없이/api/vote/*는 모든 메서드) - [API 확인] 칸에서
POST /api/orders를 넣어 막히는지 확인하고 저장합니다.
페이지에 넣을 코드
<script src="https://spillway-engine.example.workers.dev/sdk.js"
data-tenant="acme-shop" defer></script><form action="/api/orders" method="post"> <button type="submit" data-spillway-room="checkout">구매하기</button> </form>
버튼을 누르면 줄을 서야 할 때만 페이지 위에 대기 창이 뜹니다. 차례가 되면 창이 닫히고 원래 동작(폼 전송, 클릭 처리)이 그대로 이어집니다. 한가할 때는 창이 뜨지 않고 바로 진행됩니다. 입력해 둔 내용은 그대로 남습니다.
코드로 제어할 때 (선택)
// 입장권을 헤더에 붙여 호출. 입장권이 만료돼 429 가 오면 다시 줄을 세우고 한 번 재시도
const res = await Spillway.fetch("checkout", "/api/orders", {
method: "POST",
body: JSON.stringify(order),
});
// 줄만 세우고 이후 동작은 직접
try {
await Spillway.gate("checkout");
openPaymentWindow();
} catch (e) {
if (e.name === "SpillwayCancelled") { /* 사용자가 대기 창을 닫음 */ }
}| 기능 | 설명 |
|---|---|
data-spillway-room | 버튼·링크에 붙이면 클릭 전에 줄을 세움 |
Spillway.gate(room) | 입장권을 받을 때까지 대기 (유효한 입장권이 있으면 바로) |
Spillway.fetch(room, url, init) | 입장권을 x-spillway-token 헤더로 붙여 호출 |
| 입장권 유효 시간 | 대기실의 "입장 후 유지 시간" (기본 10분) — 그동안은 다시 눌러도 바로 처리 |
429 {"spillway":"queued"} 를 돌려줍니다. 입장권은 헤더나 쿠키(__spw_{고객사}_{대기실})에서 읽습니다.6보안 정책(CSP)
사이트가 Content-Security-Policy 를 쓰고 있다면 버튼·이벤트 타입에 엔진 주소를 허용해야 합니다. 빠지면 브라우저가 sdk.js 를 막습니다 (개발자 도구에 "Provisional headers are shown" 만 보임).
Content-Security-Policy: default-src 'self'; script-src 'self' https://spillway-engine.example.workers.dev; frame-src https://spillway-engine.example.workers.dev; …
script-src 는 sdk.js, frame-src 는 대기 창(엔진 화면을 iframe 으로 띄움) 때문에 필요합니다. 단일 페이지 타입은 사이트를 떠나 엔진 화면으로 이동하므로 CSP 변경이 필요 없습니다.
7CDN·프록시 뒤에 있을 때
CloudFront 같은 CDN 이 Worker 앞에 있으면 두 가지를 확인합니다.
- 방문자 주소 알려 주기 — Worker 가 받는 주소(
*.workers.dev)와 방문자 주소가 다르면, 대기 후 돌아갈 주소가 틀어집니다. 가드 옵션에siteOrigin: "https://www.example.com"을 넣어 주세요. - 쿠키·요청 전달 — CDN 이
__spw_로 시작하는 쿠키와x-spillway-token헤더, 대기 대상 API 의 POST 요청을 Worker 까지 넘겨야 합니다. 빠지면 입장한 뒤에도 계속 대기 화면이나 429 가 나옵니다.
콘솔 [고객사 설정]의 허용 사이트에는 방문자가 보는 주소(https://www.example.com)를 넣습니다.
8운영하기
| 하고 싶은 것 | 콘솔 위치 | 반영 |
|---|---|---|
| 입장 속도 잠깐 올리기·내리기 | [대기 현황] → 대기실 선택 → 입장 속도 조절 | 즉시 (임시, [원래대로]로 복귀) |
| 지금 기다리는 사람만 모두 입장 | [대기 현황] → 대기자 일괄 입장 | 즉시 |
| 당분간 아무도 기다리지 않게 | [대기 현황] → 즉시 해제 (재개로 복귀) | 즉시 |
| 대기실 켜기·끄기 | [대기 현황] → 대기열 사용 스위치 | 즉시 (사이트 최대 10초) |
| 대상 주소·API 바꾸기 | [대기실] | 저장 즉시 (사이트 최대 10초) |
| 대기 화면 문구·색상 | [대기 화면] (모든 대기실 / 대기실별) | 저장 즉시, 기다리던 화면도 새로 고침 |
| 설정 되돌리기 | [변경 이력] → 이 버전으로 되돌리기 | 즉시 |
서명 키 교체
키가 유출됐거나 담당자가 바뀌었을 때, Spillway 담당자에게 교체를 요청합니다. 교체부터 사이트 반영까지는 대기열이 통과 모드가 되므로 한가한 시간에 진행하세요.
- 담당자가 콘솔에서 새 키로 교체
- [사이트 연동] → [서명 키 보기]로 새 키 확인
npx wrangler secret put SPILLWAY_TOKEN_SECRET로 넣고 배포
9문제 해결
| 증상 | 원인과 조치 |
|---|---|
| sdk.js 요청에 "Provisional headers are shown" | 사이트 CSP 가 막음 → 6. 보안 정책에 엔진 주소 추가 |
| 버튼이 계속 429 로 막힘 | ① 콘솔 대기실 id 와 data-spillway-room 값이 다름 ② 사이트의 서명 키가 콘솔의 키와 다름(운영·개발 키 혼동) ③ CDN 이 쿠키를 넘기지 않음 |
대기 화면에 invalid_return_url | [고객사 설정] 허용 사이트에 방문자 주소가 없음 |
| 입장한 뒤에도 다시 대기 화면 | 서명 키 불일치, 또는 CDN 이 __spw_ 쿠키를 넘기지 않음 |
| 규칙을 바꿨는데 그대로 | 가드가 규칙을 10초 캐시합니다. 잠시 후 다시 확인 |
| 엔진 장애 때 | 가드와 sdk.js 모두 대기 없이 통과시킵니다. 사이트는 그대로 동작합니다 |
10오픈 전 점검표
- 가드 v0.5.0 설치, Worker 맨 앞에
guardPage SPILLWAY_ENGINE_URL은 운영 엔진 주소,SPILLWAY_TOKEN_SECRET은 운영 콘솔의 키- 콘솔 허용 사이트에 방문자 주소 등록
- (버튼·이벤트) sdk.js 스크립트와
data-spillway-room, CSP 의 script-src·frame-src - (CDN 사용 시)
siteOrigin, 쿠키·헤더·POST 전달 - 콘솔에서 입장 속도를 아주 낮게 두고 직접 줄을 서 본 뒤, 즉시 해제로 입장되는지 확인
- 확인 후 입장 속도를 운영 값으로 되돌리기