Spillway 연동 가이드

사이트에 접속이 몰릴 때 방문자를 순서대로 줄 세워, 서버가 감당할 수 있는 속도로만 들여보내는 대기열을 붙이는 방법입니다. 사이트 코드에는 몇 줄만 넣고, 어느 페이지·버튼에 대기열을 걸지와 입장 속도는 관리 콘솔에서 바로 바꿉니다.

가드 v0.5.0대기 타입: 단일 페이지 · 버튼·이벤트Cloudflare Workers 사이트

1준비물

Spillway 담당자에게 아래 네 가지를 받습니다. 관리 콘솔에서 직접 확인할 수 있는 것은 콘솔 위치를 함께 적었습니다.

항목예시어디서
고객사 idacme-shop콘솔 [사이트 연동] → 연결 정보
엔진 주소https://spillway-engine.example.workers.dev콘솔 [사이트 연동] → 연결 정보
서명 키43자 문자열 (비밀 값)콘솔 [사이트 연동] → [서명 키 보기]
콘솔 계정이메일 + 임시 비밀번호담당자가 발급 (첫 로그인 때 비밀번호 변경)
서명 키는 비밀 값입니다. 코드나 저장소에 그대로 넣지 말고 Worker 의 secret 으로만 넣어 주세요. 키가 있으면 입장권을 만들 수 있습니다.

현재 가드는 Cloudflare Workers 로 서빙되는 사이트를 지원합니다. 다른 환경(Nginx, Spring 등)은 담당자에게 문의해 주세요.

2대기 타입 고르기

대기실마다 대기 타입을 하나 고릅니다. 한 사이트에 두 타입의 대기실을 함께 둘 수 있습니다.

단일 페이지 사용 가능

정해진 주소에 들어올 때 줄을 세웁니다. 예: 오픈 이벤트 페이지, 메인 페이지. 사이트 코드는 가드만 있으면 됩니다.

버튼·이벤트 사용 가능

페이지는 자유롭게 보고, 버튼을 누를 때(구매·예약·전송) 줄을 세웁니다. 페이지에 스크립트 한 줄과 버튼 속성이 필요합니다.

구간(시작~종료) 준비 중

시작 주소부터 종료 주소까지 한 흐름(예: 주문서~결제)에 머무는 인원을 제한합니다.

3가드 설치 (공통)

가드는 사이트 Worker 맨 앞에서 요청을 검사하는 작은 라이브러리입니다. 두 대기 타입 모두 이 단계가 필요합니다.

① 설치

터미널
npm i github:chandarasoft/spillway-guard#v0.5.0

② Worker 코드 맨 앞에 추가

src/index.ts
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초 캐시), 규칙을 바꿔도 사이트를 다시 배포할 필요가 없습니다.

③ 설정 값 넣기

wrangler.jsonc
"vars": {
  "SPILLWAY_ENGINE_URL": "https://spillway-engine.example.workers.dev"
}
터미널 — 서명 키는 secret 으로
npx wrangler secret put SPILLWAY_TOKEN_SECRET
안전 원칙: 엔진에 연결할 수 없거나 설정이 빠지면 가드는 그냥 통과시킵니다(fail-open). 대기열 때문에 사이트가 막히는 일은 없습니다. CSS·JS·이미지 같은 정적 파일과 검색엔진 봇도 자동으로 통과합니다.

4단일 페이지

콘솔 설정

  1. [대기실] → [새 대기실] → 대기 타입 단일 페이지
  2. 대기 대상 경로에 줄을 세울 주소를 넣습니다. * 는 그 아래 모든 주소입니다.
    예: /, /event/* · 제외: /event/notice
  3. [주소 확인] 칸에 실제 주소를 넣어 줄을 서는지 바로 확인합니다.
  4. 입장 제어에서 초당 입장 인원을 정하고 저장합니다. 저장 즉시 반영됩니다.

방문자가 겪는 흐름

대기 대상 주소 접속→대기 화면 (앞에 N명, 예상 시간)→차례가 되면 자동 이동→정해진 시간 동안 자유 이용

사이트 코드는 3단계(가드)만으로 끝입니다. 대기 화면의 문구·색상·로고는 콘솔 [대기 화면]에서 바꾸고 미리보기로 확인합니다.

5버튼·이벤트

콘솔 설정

  1. [대기실] → [새 대기실] → 대기 타입 버튼·이벤트, 대기실 id 예: checkout
  2. 대기 대상 API 에 막을 요청을 넣습니다. 예: POST /api/orders (메서드 없이 /api/vote/* 는 모든 메서드)
  3. [API 확인] 칸에서 POST /api/orders 를 넣어 막히는지 확인하고 저장합니다.

페이지에 넣을 코드

HTML — 페이지에 한 번
<script src="https://spillway-engine.example.workers.dev/sdk.js"
        data-tenant="acme-shop" defer></script>
HTML — 버튼에 속성 하나
<form action="/api/orders" method="post">
  <button type="submit" data-spillway-room="checkout">구매하기</button>
</form>

버튼을 누르면 줄을 서야 할 때만 페이지 위에 대기 창이 뜹니다. 차례가 되면 창이 닫히고 원래 동작(폼 전송, 클릭 처리)이 그대로 이어집니다. 한가할 때는 창이 뜨지 않고 바로 진행됩니다. 입력해 둔 내용은 그대로 남습니다.

코드로 제어할 때 (선택)

JavaScript
// 입장권을 헤더에 붙여 호출. 입장권이 만료돼 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분) — 그동안은 다시 눌러도 바로 처리
서버 쪽은 3단계의 가드가 막아 줍니다. 대기 대상 API 를 입장권 없이 직접 호출하면 429 {"spillway":"queued"} 를 돌려줍니다. 입장권은 헤더나 쿠키(__spw_{고객사}_{대기실})에서 읽습니다.

6보안 정책(CSP)

사이트가 Content-Security-Policy 를 쓰고 있다면 버튼·이벤트 타입에 엔진 주소를 허용해야 합니다. 빠지면 브라우저가 sdk.js 를 막습니다 (개발자 도구에 "Provisional headers are shown" 만 보임).

public/_headers (예)
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 담당자에게 교체를 요청합니다. 교체부터 사이트 반영까지는 대기열이 통과 모드가 되므로 한가한 시간에 진행하세요.

  1. 담당자가 콘솔에서 새 키로 교체
  2. [사이트 연동] → [서명 키 보기]로 새 키 확인
  3. 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 전달
  • 콘솔에서 입장 속도를 아주 낮게 두고 직접 줄을 서 본 뒤, 즉시 해제로 입장되는지 확인
  • 확인 후 입장 속도를 운영 값으로 되돌리기