Spillway 연동 가이드
사이트에 접속이 몰릴 때 서버가 감당할 수 있는 만큼만 들여보내고, 넘치는 방문자는 순서대로 줄 세우는 대기열을 붙이는 방법입니다. 사이트 코드에는 몇 줄만 넣고, 어느 페이지·버튼에 대기열을 걸지, 몇 명까지 들일지, 언제 시작할지는 관리 콘솔에서 바로 바꿉니다.
1준비물
Spillway 담당자에게 아래 네 가지를 받습니다. 관리 콘솔에서 직접 확인할 수 있는 것은 콘솔 위치를 함께 적었습니다.
| 항목 | 예시 | 어디서 |
|---|---|---|
| 고객사 id | acme-shop | 콘솔 [사이트 연동] → 연결 정보 |
| 엔진 주소 | https://queue.spillway.co.kr | 콘솔 [사이트 연동] → 연결 정보 |
| 서명 키 | 43자 문자열 (비밀 값) | 콘솔 [사이트 연동] → [서명 키 보기] |
| 콘솔 계정 | 이메일 + 임시 비밀번호 | 담당자가 발급 (첫 로그인 때 비밀번호 변경) |
현재 가드는 Cloudflare Workers 로 서빙되는 사이트를 지원합니다. 다른 환경(Nginx, Spring 등)은 담당자에게 문의해 주세요.
2대기 타입·입장 방식 고르기
대기실마다 대기 타입을 하나 고릅니다. 한 사이트에 두 타입의 대기실을 함께 둘 수 있습니다.
단일 페이지 사용 가능
정해진 주소에 들어올 때 줄을 세웁니다. 예: 오픈 이벤트 페이지, 메인 페이지. 사이트 코드는 가드만 있으면 됩니다.
버튼·이벤트 사용 가능
페이지는 자유롭게 보고, 버튼을 누를 때(구매·예약·전송) 줄을 세웁니다. 페이지에 스크립트 한 줄과 버튼 속성이 필요합니다.
구간(시작~종료) 준비 중
시작 주소부터 종료 주소까지 한 흐름(예: 주문서~결제)에 머무는 인원을 제한합니다.
입장 방식
대기실마다 몇 명을 어떻게 들일지 고릅니다. 새 대기실은 입장 인원 제한으로 시작합니다.
입장 인원 제한 기본
동시 이용 인원(예: 300명)을 넘을 때만 줄을 섭니다. 자리가 있으면 대기 화면 없이 바로 입장합니다. 입장한 사람은 입장 후 이용 시간(기본 10분) 동안 자리를 차지한 것으로 봅니다. 한꺼번에 몰리는 것을 막고 싶으면 분당 입장 상한(선택)을 함께 둡니다.
입장 속도 제한
모든 방문자가 대기 화면을 거쳐 분당 입장 인원만큼 일정하게 들어갑니다. 서버가 처리할 수 있는 속도를 정확히 알고 있을 때 알맞습니다.
3가드 설치 (공통)
가드는 사이트 Worker 맨 앞에서 요청을 검사하는 작은 라이브러리입니다. 두 대기 타입 모두 이 단계가 필요합니다.
① 설치
npm i github:chandarasoft/spillway-guard#v0.6.0
② Worker 의 fetch 를 가드로 감싸기
import { withSpillway } from "spillway-guard";
const SPILLWAY = {
tenant: "acme-shop", // 고객사 id
engineUrl: "https://queue.spillway.co.kr", // 엔진 주소 (또는 env.SPILLWAY_ENGINE_URL)
// siteOrigin: "https://www.example.com", // CDN 뒤에 있을 때 방문자가 보는 주소
};
export default {
// 줄을 서야 하면 대기 화면으로, 자리가 있으면 대기 화면 없이 바로 입장(응답에 입장 쿠키),
// 그 밖에는 그대로 통과 (엔진 장애 때도 통과)
fetch: (request, env, ctx) => withSpillway(request, env, SPILLWAY, (req) => handle(req, env, ctx)),
};
async function handle(request, env, ctx) {
// … 기존 처리
}어느 주소·API 에 대기열을 걸지, 입장 방식과 인원·속도, 예약 시작은 코드에 적지 않습니다. 가드가 엔진에서 대기실 규칙을 받아 오므로(10초 캐시), 바꿔도 사이트를 다시 배포할 필요가 없습니다. 이 코드는 콘솔 [사이트 연동]에서 고객사 id 가 채워진 채로 복사할 수 있습니다.
v0.5.0 의 guardPage 를 쓰고 있다면 그대로 동작합니다. 다만 입장 인원 제한 대기실에서 자리가 있을 때 같은 주소로 리다이렉트가 한 번 생기므로 withSpillway 로 바꾸는 것을 권합니다.
③ 설정 값 넣기
"vars": {
"SPILLWAY_ENGINE_URL": "https://queue.spillway.co.kr"
}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://queue.spillway.co.kr/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://queue.spillway.co.kr; frame-src https://queue.spillway.co.kr; …
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분 전 · 30분 전(기본) · 1시간 전.
- [대기 화면] → 화면 종류 [시작 전]·[종료]에서 문구를 바꾸고 미리보기로 확인합니다.
- 추첨 대상은 시작하는 순간 카운트다운 화면을 열어 둔 사람입니다. 창을 닫고 떠난 사람은 빠집니다. 일찍 온 사람이 유리하지 않으므로 새로 고침을 반복할 필요가 없습니다.
- 시작한 뒤에 온 사람은 추첨된 사람들 뒤에 순서대로 섭니다.
- 종료는 자동이 아니라 콘솔에서 누릅니다. 종료 뒤에 온 사람은 종료 안내를 보고, 이미 순번을 받은 사람은 계속 입장합니다. [다시 열기]로 되돌릴 수 있습니다.
- 예약한 시각을 기다리지 않고 [지금 시작]으로 바로 시작할 수도 있습니다.
9운영하기
| 하고 싶은 것 | 콘솔 위치 | 반영 |
|---|---|---|
| 지금 상황 보기 | [대기 현황] → 대기실 탭 (대기·이용 중 인원, 실시간 입장 흐름 그림) | 2초마다 갱신 |
| 동시 이용 인원·입장 속도 바꾸기 | [대기 현황] → 대기실 탭 → 조절 → [적용] | 즉시 (대기실 설정에 저장) |
| 지금 기다리는 사람만 모두 입장 | [대기 현황] → 대기자 일괄 입장 | 즉시 |
| 당분간 아무도 기다리지 않게 | [대기 현황] → 즉시 해제 (재개로 복귀) | 즉시 |
| 대기실 켜기·끄기 | [대기 현황] → 대기열 사용 스위치 | 즉시 (사이트 최대 10초) |
| 이벤트 지금 시작 · 종료 · 다시 열기 | [대기 현황] → 대기실 탭 → 이벤트 | 즉시 (시작 전 화면에도 바로 알림) |
| 대상 주소·API, 입장 방식, 시작 시각 바꾸기 | [대기실] | 저장 즉시 (사이트 최대 10초) |
| 대기 화면 문구·색상 (대기 중·시작 전·종료) | [대기 화면] (모든 대기실 / 대기실별) | 저장 즉시, 기다리던 화면도 새로 고침 |
| 설정 되돌리기 | [변경 이력] → 이 버전으로 되돌리기 | 즉시 |
서명 키 교체
키가 유출됐거나 담당자가 바뀌었을 때, Spillway 담당자에게 교체를 요청합니다. 교체부터 사이트 반영까지는 대기열이 통과 모드가 되므로 한가한 시간에 진행하세요.
- 담당자가 콘솔에서 새 키로 교체
- [사이트 연동] → [서명 키 보기]로 새 키 확인
npx wrangler secret put SPILLWAY_TOKEN_SECRET로 넣고 배포
10문제 해결
| 증상 | 원인과 조치 |
|---|---|
| sdk.js 요청에 "Provisional headers are shown" | 사이트 CSP 가 막음 → 6. 보안 정책에 엔진 주소 추가 |
| 버튼이 계속 429 로 막힘 | ① 콘솔 대기실 id 와 data-spillway-room 값이 다름 ② 사이트의 서명 키가 콘솔의 키와 다름(운영·개발 키 혼동) ③ CDN 이 쿠키를 넘기지 않음 |
대기 화면에 invalid_return_url | [고객사 설정] 허용 사이트에 방문자 주소가 없음 |
| 입장한 뒤에도 다시 대기 화면 | 서명 키 불일치, 또는 CDN 이 __spw_ 쿠키를 넘기지 않음 |
| 입장 인원 제한인데 자리가 있어도 대기 화면이 나옴 | 이미 기다리는 사람이 있으면 새로 온 사람도 줄 뒤에 섭니다(정상). 또는 분당 입장 상한에 걸렸는지, guardPage 대신 withSpillway 를 쓰는지 확인 |
| 예약 시작인데 원래 페이지가 그대로 보임 | 사전 대기 시작 전이라 정상입니다. 사전 대기 시각부터 카운트다운 화면이 보입니다 |
| 규칙을 바꿨는데 그대로 | 가드가 규칙을 10초 캐시합니다. 잠시 후 다시 확인 |
| 엔진 장애 때 | 가드와 sdk.js 모두 대기 없이 통과시킵니다. 사이트는 그대로 동작합니다 |
11오픈 전 점검표
- 가드 v0.6.0 설치, Worker 의 fetch 를
withSpillway로 감쌈 SPILLWAY_ENGINE_URL은 운영 엔진 주소,SPILLWAY_TOKEN_SECRET은 운영 콘솔의 키- 콘솔 허용 사이트에 방문자 주소 등록
- (버튼·이벤트) sdk.js 스크립트와
data-spillway-room, CSP 의 script-src·frame-src - (CDN 사용 시)
siteOrigin, 쿠키·헤더·POST 전달 - 콘솔에서 동시 이용 인원 1명(또는 분당 입장 1명)으로 두고, 창 두 개로 접속해 두 번째 창이 줄을 서는지, 즉시 해제로 입장되는지 확인
- (예약 시작) 시작 시각·사전 대기 시간, [대기 화면]의 시작 전·종료 미리보기
- 확인 후 동시 이용 인원·입장 속도를 운영 값으로 되돌리기