SAZU Studio 문서
프롬프트 작성만으로 운세 풀이를 빠르게 완성합니다.
정확한 사주 데이터 + 검증된 풀이 엔진은 SAZU 가 호스팅 합니다. Studio 빌더에서 프롬프트로 톤·형식만 정하면 끝 — 완성된 운세 풀이를 호출 한 번으로 받습니다.
🗺️ 전체 구조 — 풀이는 저희가, 서비스는 회원님이
처음 운세 서비스를 만드시는 분을 위한 전체 그림입니다. 여섯 조각이 어떤 순서로 이어지고 그중 무엇을 SAZU 가 맡는지를 먼저 보시면 아래 문서가 쉬워집니다.
SAZU API 서비스를 이용해서 회원님의 운세 제품을 만들려면 명리 계산 결과를 받은 뒤 준비된 프롬프트로 다시 AI 호출을 구현하는 것까지 회원님이 직접 하셔야 하는 번거로움이 있습니다. 이 경우 AI 구독도 별도로 하셔야 하며, 낮은 등급의 구독 Tier 는 처리 용량의 한계가 있습니다. 하지만 SAZU Studio 는 그 부분까지 자체 개발된 빌더와 넉넉한 AI 처리 용량을 이용해서 여러 호출도 빠르게 처리하여 완성된 풀이를 제공합니다.
모든 풀이에는 환각 방지 8원칙이 빌더 코어로 늘 적용되어, 명리계산 결과에 없는 내용을 AI 가 마음대로 지어내는 것을 최대한 막습니다. 또한 제3국 언어로 오염되는 문장을 자체적으로 검증하여 최대한 한글화 또는 선택하신 언어로 최종 운세 풀이를 제공하고 있기 때문에 신뢰도가 높습니다. 회원님은 어조·형식·홍보 문구에만 집중하시면 됩니다.
각 단계 자세히
SAZU Studio 에 가입하시고 마이페이지 › API 키에서 새 키를 발급합니다.
빌더에서 운세 종류를 선택하고 페르소나(어조)·작성 방식·출력 형식을 라디오로 선택해 레시피를 완성합니다. 첫 프롬프트가 승인되면 실시간 미리보기로 결과를 확인합니다.
저장한 레시피는 SAZU 가 자동으로 검토하고, 승인된 버전만 API 에 반영됩니다. 운세 생성 목적을 벗어난 지시는 이 단계에서 걸러집니다.
회원님 서비스에서 고객의 생년월일시·성별을 입력받습니다. 궁합 운이라면 상대의 생년월일도 함께 받습니다.
3번(승인된 레시피) + 4번(고객 사주) 를 API 한 번으로 보내면, SAZU 가 사주를 계산하고 레시피대로 AI 풀이를 작성해 완성된 문장을 돌려드립니다. AI 키·모델은 따로 준비하실 필요가 없습니다.
장문은 응답까지 시간이 걸립니다. 결제 직후 여러 건을 만드신다면 아래 「대량 처리 설계」의 작업 API 를 쓰세요.
응답으로 받은 풀이 문장(data.text)을 그대로 화면에 표시하시면 됩니다.
API 키는 반드시 서버에서만 사용하세요 — 브라우저 코드에 넣으면 키가 그대로 노출됩니다.
1단계🚀 빠르게 시작하기
설명서를 정독하지 않아도 됩니다. 가입 → 키 발급 → 빌더에서 바로 만들기 — 이 순서로 곧장 시작하시길 권합니다. 막히는 부분이 생기면 그때 아래 문서를 펼쳐 보세요.
- 가입 + API 키 발급 — 브랜드 이름(예: 우아한 사주운세) 입력 후, 마이페이지 › API 키 › 새 키 발급
- 빌더에서 만들기 — 마이페이지 › 빌더에서 운세를 고르고 라디오 몇 번으로 레시피 완성. 변경사항 검토를 통과해 승인되면 실시간 미리보기로 샘플 사주 풀이를 확인합니다
- 연동 — 저장 시 자동 검토를 통과하면 승인됨. 빌더 ⑦단계 바이브 코딩 프롬프트를 AI 툴(Claude · Codex · Gemini)에 붙여넣어 화면까지 완성하거나,
POST /api/v1/render로 직접 호출
💡 첫 프롬프트가 승인되면 실시간 미리보기로 샘플 사주 풀이를 확인하고, 마음에 들면 ⑦단계 프롬프트를 AI 코딩 도구에 붙여넣어 서비스를 완성하세요.
2단계🧩 핵심 개념
- 풀이 종류 — 운세 아홉 가지에 재물운·건강운·명리 식단을 더해 12종 (아래 풀이 종류 표 참조)
- 크레딧 — 호출 1회당 차감되는 단위. 풀이별 1~3 크레딧이 기본이고, 레시피 분량을 장문으로 두면 2 크레딧이 더해집니다 (위 표의 크레딧 차감 열 참조)
- 플랜 — 월 포함 크레딧 수만 다름. 레시피 분량 한도는 플랜과 무관 (풀이별 고정)
- 페르소나 — 풀이 어조 프리셋 9종 (따뜻한 · 시크한 · MZ · 전통 · 코믹 · 신비로운 · 시적인 · 차분·이성적 · 단호·직설)
- 레시피 — 빌더에서 위→아래로 라디오를 선택해 운세를 정의 (분석 방법 · 페르소나 · 작성 방식 · 출력 형식). 코드·변수 불필요, 항목마다 직접 입력도 가능
- 검토 · 승인 — 저장한 레시피는 자동 검토를 통과해 승인된 뒤에만 API 에 반영
- 환각 방지 8원칙 — 없는 사실 생성·규칙 우회를 막는 빌더 코어. 모든 호출에 불변 적용되며 끄거나 수정할 수 없음
3단계✍️ 운세 레시피 빌더
빌더는 위에서 아래로 내려오며 라디오를 선택하면 레시피가 완성됩니다. ⑤ 변경사항 검토로 승인한 뒤, ⑥·⑦에서 연동 방식과 바이브 코딩 프롬프트까지 받아 화면을 완성합니다.
- 사주 데이터 — 생년월일시로 SAZU 엔진이 자동 계산해 풀이에 주입 (입력 불필요)
- ① 풀이 종류 · 분석 방법 — 작성할 풀이를 고르고, 사주 계산 결과를 어떻게 분석해 화면에 표시할지 시스템 기본 분석 또는 직접지정을 선택. 원국 데이터 사용을 켜면 연주·월주·일주·시주의 원국 값을 「일주의 12운성」처럼 불러 쓸 수 있고, 응답에도
data.chart로 함께 옵니다 (API 호출 참고) - ② 페르소나(어조) — 풀이 전체 분위기를 9종 중 선택
- ③ 작성 방식 — 화자 역할 · 화법 · 분량 · 독자 호칭 (각 항목 직접 입력 가능 — 예: 호칭을 “회원님”·“○○님”으로)
- ④ 출력 형식 — 형식(줄글·불릿·번호 섹션·표 혼합) · 배치(총평→세부 등) · 직접 지정 문장(홍보 문구·링크)
- ⑤ 변경사항 검토 + 실시간 미리보기 — 자동 검토 통과 시 승인됨 → API 반영. 승인 후 실시간 미리보기로 결과를 확인
- ⑥ 연동 방식 · 기술 환경 — 기존 프로젝트에 이식 또는 새 프로젝트, 기술 환경(정적 HTML · Next.js/React · Node.js · Python) 선택. 이 선택이 아래 ⑦ 예제에 반영됨
- ⑦ 연동 안내(바이브 코딩 프롬프트) — 완성 레시피 + ⑥ 설정이 녹아든 프롬프트를 AI 툴(Claude · Codex · Gemini)에 붙여넣으면 화면까지 자동 구현. 서버 호출용 코드 예제도 함께 제공
대부분 라디오 선택만으로 완성됩니다. 더 세밀하게 조정하려면 ①의 직접 지정 이나 ③·④의 직접 입력 칸에 일반인이 이해할 말로 적으면 됩니다 — 실제 사주 계산 결과는 SAZU 가 자동으로 넣어 줍니다.
예시 — ① 직접 지정 (분석 방법)
오늘 하루의 전반 기운을 따뜻하게 풀어 주세요.
- 일 · 애정 · 금전 · 건강 흐름을 각각 2~3문장으로
- 좋은 점은 격려하고, 조심할 점은 부드럽게 짚어 주세요
- 어려운 명리 용어는 쉬운 말로 바꿔서 설명해 주세요예시 — ④ 직접 지정 (출력 형식)
- 첫 줄에 오늘의 한 줄 요약 (이모지 1개)
- 마지막에 "오늘의 행운 키워드: ○○" 한 줄
- 끝에 "더 자세한 풀이는 OurApp 에서 👉" 안내 추가💡 첫 프롬프트가 승인되면 실시간 미리보기로 샘플 사주의 실제 풀이를 확인합니다.
(실시간 미리보기는 무료 크레딧부터 차감, 프롬프트로 AI 연산 실행).
⚠️ 작성 시 주의사항
- 작성 지침 + 출력 형식의 합계 글자 수가 운세별 한도를 넘지 않아야 합니다 (빌더에서 실시간 확인).
- 환각 방지 8원칙과 운세 범위(오늘/이번 달/올해 등)는 빌더 코어로 고정하여 최대한 AI 환각을 예방합니다 — 어조·용어·형식·호칭·맺음말만 자유롭게 설정합니다.
- 운세 생성 목적 외 다른 의도(시스템 우회·자원 접근 등)는 자동 검토 후 차단되며 모니터링 대상이 될 수 있습니다.
4단계🔌 API 호출 및 화면에 결과 출력
엔드포인트 · POST https://www.sazu.app/api/v1/render
인증 · 헤더 X-API-Key: 발급받은_키 (server-to-server, 키는 외부 노출 금지)
재시도 안전 · 선택 헤더 X-Request-Id (8~128자, 영문·숫자·_.:-)
이 값을 넣고 같은 값으로 다시 호출하면 풀이를 새로 만들지 않고 처음 결과를 그대로 돌려드립니다(24시간). 크레딧도 한 번만 차감됩니다. 네트워크 오류나 타임아웃으로 재시도하는 구성이라면 반드시 넣어 주세요 — 없으면 재시도할 때마다 다른 풀이가 새로 만들어집니다. 풀이 종류마다 다른 값을 쓰세요(예: order-1042-life). 같은 값을 다른 운세에 쓰면 409 IDEMPOTENCY_KEY_REUSED 가 납니다.
요청 본문
servicestring · 풀이 종류 id — 아래 12종 중 하나 (id·이름 대응은 위 풀이 종류 표 참조)birth.birthYearnumber · 1900~2100birth.birthMonthnumber · 1~12birth.birthDaynumber · 1~31birth.birthHournumber|null · 0~23 · 모르면 null 또는 생략 (둘은 같은 뜻입니다)birth.isFemalebooleanbirth.isLunarboolean · 선택 (음력 여부)birth.birthCitystring · 선택birth.birthMinutenumber|null · 0~59 · 선택 (생략하거나 null 이면 0) — 시주 경계에 걸린 분은 이 값으로 기둥이 달라집니다birth.trueSolarTimeboolean · 선택 (생략 시 false) — 진태양시(경도차·균시차) 적용 여부. 기본값은 한국 관습입니다
관계 대상 partners (궁합·연애 운 전용 — 궁합은 필수, 연애는 선택)
궁합·연애 운은 두 사람 이상을 놓고 보는 풀이입니다. 상대는 최대 3명까지이며, 인원수와 무관하게 차감 크레딧은 1건입니다.
- 궁합 운은 상대가 필수입니다 — 상대가 없으면 교차 판정이 통째로 사라져 풀이가 성립하지 않습니다. 빼고 부르면
400 PARTNERS_REQUIRED가 납니다. - 연애 운은 상대 없이도 부를 수 있습니다 — 담기는 재료가 전부 본인 것이라, 상대를 보내지 않으면 관계 판정 없이 본인 연애 흐름만 풀이합니다.
- 상대를 받지 않는 운세에 보내거나 상한을 넘기면
400 PARTNERS_NOT_SUPPORTED가 납니다.
partners[].birthYear외 생년월일 필드는birth와 규칙이 같습니다partners[].labelstring · 20자 이하 · 선택 — 풀이에서 이 상대를 부르는 이름. 생략하면 A·B·C
{
"service": "compatibility",
"birth": { "birthYear": 1990, "birthMonth": 5, "birthDay": 15, "birthHour": 10, "isFemale": false },
"partners": [
{ "birthYear": 1992, "birthMonth": 7, "birthDay": 24, "birthHour": 9, "isFemale": true, "label": "지현" },
{ "birthYear": 1988, "birthMonth": 1, "birthDay": 3, "birthHour": null, "isFemale": true, "label": "수아" }
]
}레시피에서는 「상대 이름」·「교차 합형충파해」·「오행 상보」 를 지목해 지침을 쓸 수 있습니다 — 빌더의 어휘 목록에서 눌러 넣으세요.
선택 — 상황 정보 context
이용자의 처지를 함께 보내면 그 맥락으로 좁혀 풀이합니다. 보내지 않아도 호출은 정상 동작합니다.
context.occupationstring · 60자 이하 (직업·직군)context.maritalStatus"single" | "partnered" | "married" | "divorced" | "widowed"context.targetYearnumber · 1900~2100 — 연간 운세의 기준 연도. 세운·월운을 이 해 기준으로 계산합니다context.targetMonthstring · "YYYY-MM" — 월간 상세운세의 기준 월. 생략하면 이번 달로 계산합니다context.concernstring · 300자 이하 (고민 주제 — 고민 맞춤분석에서 사용)
{
"service": "yearly",
"birth": { "birthYear": 1990, "birthMonth": 5, "birthDay": 15, "birthHour": 10, "isFemale": false },
"context": {
"occupation": "백엔드 개발자",
"maritalStatus": "married",
"targetYear": 2027
}
}선택 — 장문 생성 방식 longformStrategy
레시피 분량을 장문으로 저장한 운세에서만 동작합니다. 분량과 구조 중 무엇을 우선할지 고르는 값입니다. 기본값 "chapters" 는 목차를 먼저 잡아 장별로 생성한 뒤 병합합니다 — 2만자 분량이 안정적이지만 엔진이 만든 목차가 출력 구조가 됩니다."single" 은 한 번에 생성해 분량이 짧아질 수 있는 대신 레시피에 지정하신 출력 구조를 그대로 지킵니다.소제목·섹션 구성을 직접 정해 두셨다면 "single" 을 쓰세요. 어느 쪽이든 차감 크레딧은 동일합니다. 장문은 응답까지 평균 1분, 최대 5분이 걸립니다. 호출 측 타임아웃을 300초 이상으로 잡아 주세요. 평균값은 보장치가 아니며, 동시 요청이 몰리면 대기가 붙습니다.
service 가능 값 (12종)
["today","daily","monthly","yearly","consult","compatibility","love","decade","life","money","health","food"]응답 (200)
{
"success": true,
"data": {
"text": "오늘 당신의 기운은 ...", // 완성된 풀이 (그대로 화면에 출력)
"service": "today"
},
"meta": { "version": 3, "tier": "slim" }
}✅ data.text 를 받아서 화면에 보여줄 컴포넌트에 적용합니다.
원국 데이터 사용 (선택)
원국은 운세마다 필요한 만큼만 줄여 풀이에 씁니다. 빌더 ①의 원국 데이터 사용을 켜고 승인받은 레시피는 연주·월주·일주·시주의 천간·지지, 십성, 12운성, 납음, 지장간과 기둥별 신살이 전부 실립니다. 레시피에서 「일주의 12운성」·「월주의 십성」처럼 이름으로 불러 원하는 자리에 배치하시면 됩니다. 프롬프트 만들기에서 배치 방식을 고르시면 출발점이 되는 문장까지 만들어 드립니다.
같은 값이 응답의 data.chart 로도 옵니다. 필드 이름은 SAZU API 의 명식 조회 응답과 같습니다. 추가 크레딧은 차감되지 않습니다. 싣는 데이터가 늘어 응답이 조금 느려질 수 있으니 필요한 레시피에만 켜세요. 켜지 않은 레시피의 응답은 지금과 같습니다.
{
"success": true,
"data": {
"text": "…",
"service": "life",
"chart": {
"fourPillars": {
"year": {
"full": "임자",
"sky": "임",
"earth": "자",
"skyElement": "수",
"earthElement": "수",
"sippiSeong": "식신",
"earthSippiSeong": "상관",
"twelveStage": "사",
"naeeum": "상자목",
"jiJangGan": {
"residue": { "stem": "임", "days": 10 },
"middle": null,
"main": { "stem": "계", "days": 20 }
}
},
"month": { … },
"day": { … },
"hour": { … } // 태어난 시간을 모르면 null
},
"sinsal": {
"angels": [{ "name": "천덕귀인", "pillars": ["시간"] }],
"devils": [{ "name": "괴강살", "pillars": ["일주"] }],
"twelve": [{ "name": "장성살", "pillars": ["년지"] }],
"byPillar": {
"year": { "twelve": "장성살", "angels": [], "devils": [] },
"month": { … }, "day": { … }, "hour": { … }
}
}
}
},
"meta": { "version": 3, "tier": "standard" }
}연동 예제
# 현재 사용중인 AI 도구 Claude, Codex, Gemini 등에 그대로 붙여넣으세요 👇
[목표]
이미 운영 중인 내 프로젝트에 '내 서비스'의 "오늘의 운세" 기능을 새 기능으로 추가해줘. 기존 폴더 구조·상태관리·디자인 토큰/컴포넌트 컨벤션을 그대로 따르고, 빌드·패키지 설정 변경은 최소화해서 새 페이지 또는 모달로 붙여줘.
사용자가 생년월일시를 입력하면 완성된 "오늘의 운세" 풀이를 화면에 보여주는 기능이다.
[기술 환경]
기술 환경: Next.js(App Router)·TypeScript. 시스템 구성: app/api/fortune/route.ts 백엔드 라우트에서 API 키를 보관하고 SAZU 를 호출한다. 클라이언트 컴포넌트의 입력 폼이 그 라우트를 부른다.
[보안 — 가장 중요]
- API 키는 코드에 하드코딩하지 말고 서버 환경변수 SAZU_STUDIO_KEY 로만 읽는다. .env.example 에는 빈 자리표시자(SAZU_STUDIO_KEY=)만 두고 실제 값은 넣지 않는다.
- 키는 브라우저·클라이언트 코드·git 저장소에 절대 노출 금지.
- 호출은 반드시 내 백엔드를 경유한다: 프론트 폼 → 내 백엔드 라우트 → SAZU. 프론트에서 SAZU 를 직접 부르지 않는다.
[API]
- Node/TypeScript 프로젝트면 공식 SDK 를 우선 사용: npm install @sazuapp/studio →
new SazuStudio({ apiKey }) 후 studio.render({ service, birth }). 아래 raw HTTP 는 SDK 를
못 쓰는 환경(다른 언어 등)용이다.
- POST https://www.sazu.app/api/v1/render
- 헤더: X-API-Key: <내 키>, Content-Type: application/json
- 본문: { "service": "today",
"birth": { "birthYear": 1990, "birthMonth": 5, "birthDay": 15,
"birthHour": 10, // 0~23, 모르면 null
"isFemale": false, // 여성이면 true
"isLunar": false } } // 음력이면 true (기본 false)
- 성공: { "success": true, "data": { "text": "완성된 풀이" } } → data.text 를 화면에 표시
- 실패: { "success": false, "error", "message" } — HTTP 401(키 오류) · 402(크레딧 소진/구독 필요) · 429(과다 요청) · 400(입력 오류)
각 error 를 사용자에게 친절한 안내로 처리(특히 402 는 "잠시 후 다시" 또는 안내 문구).
[입력 폼 & 검증]
- 연(1900~2100)·월(1~12)·일(1~31) 필수, 시(0~23)는 모르면 비워서 null, 성별, 양/음력 선택.
- 미래 날짜·범위 밖 값은 막고, 검증 통과 시에만 호출.
[결과 표시]
- data.text 는 줄바꿈·마크다운(굵게·목록·표 등)이 포함될 수 있으니 그에 맞게 렌더한다(마크다운 렌더 또는 최소한 줄바꿈 유지).
- '내 서비스' 브랜드·페이지 스타일에 맞게 감싸고, 모바일에서도 잘 보이게 반응형으로.
- 로딩 상태·에러 메시지·빈 결과를 모두 안전하게 처리.
[비용]
- 호출 한 번마다 크레딧이 차감된다. 같은 입력으로 불필요하게 반복 호출하지 말고, 필요하면 결과를 저장/캐시해줘.
[마무리]
- 개발 중에는 console.log 로 오류를 확인하고, 프로덕션에서는 삭제해.
- 폼 제출 → 풀이 표시까지 실제로 동작하는지 확인해줘.🗂️ 풀이 종류
| 풀이 | id | 크레딧 (기본) | 크레딧 (장문) | 레시피 분량 한도 |
|---|---|---|---|---|
| 오늘의 운세 | today | 1 크레딧 | 미지원 | 2,400자 |
| 일일 운세 | daily | 2 크레딧 | 미지원 | 6,000자 |
| 월 상세운세 | monthly | 2 크레딧 | 미지원 | 10,000자 |
| 고민 맞춤분석 | consult | 2 크레딧 | 미지원 | 12,000자 |
| 재물운 | money | 2 크레딧 | 미지원 | 12,000자 |
| 건강운 | health | 2 크레딧 | 미지원 | 12,000자 |
| 명리 식단 | food | 2 크레딧 | 미지원 | 12,000자 |
| 관계운 | compatibility | 3 크레딧 | 5 크레딧 | 18,000자 |
| 대운 | decade | 3 크레딧 | 5 크레딧 | 21,000자 |
| 연간 운세 | yearly | 3 크레딧 | 5 크레딧 | 24,000자 |
| 연애 운 | love | 3 크레딧 | 5 크레딧 | 24,000자 |
| 인생흐름 | life | 3 크레딧 | 5 크레딧 | 24,000자 |
분량 한도는 작성 지침 + 출력 형식을 합친 글자 수이며 풀이별로 고정입니다 — 긴 풀이일수록 큽니다 (플랜과 무관). 장문은 2만자 이상으로 생성되며 연간·관계운·연애·대운·인생흐름에서만 선택할 수 있습니다.
💳 요금 · 크레딧
호출 1회당 풀이 종류에 따라 1~3 크레딧이 차감됩니다 (위 풀이 종류 표 참조). 여기에 레시피 분량을 장문으로 두면 2 크레딧이 더해집니다 — 풀이 종류가 기본을 정하고 분량이 가산분을 얹는 구조입니다. 플랜의 포함 크레딧을 쓰고, 초과분은 미리 충전한 선결제 크레딧에서 차감됩니다. 크레딧은 풀이를 만들기 전에 차감되고, 풀이가 만들어지지 않으면 자동으로 돌아옵니다.
| 플랜 | 월정액 | 포함 | 크레딧당 | 장문 보장 | 동시 상한 |
|---|---|---|---|---|---|
| Starter | ₩49,000 | 500 크레딧 | ₩98/크레딧 | 1건/분 | 2건 |
| Growth | ₩149,000 | 2,000 크레딧 | ₩75/크레딧 | 3건/분 | 4건 |
| Scale | ₩260,000 | 4,000 크레딧 | ₩65/크레딧 | 6건/분 | 8건 |
| Enterprise | 협의 | 맞춤 | 협의 | 협의 | 협의 |
초과 크레딧당 500원 (전 플랜 동일). 플랜은 마이페이지 › 결제에서 변경.
⏱️ 처리량 · 동시 호출
기본 분량 호출은 동시 개수 제한이 없습니다. 장문 레시피만 처리량을 플랜별로 나눕니다 — 장문 1건은 내부적으로 여러 단계를 거쳐 생성되므로 일반 호출보다 훨씬 큰 처리량을 씁니다.
보장하는 것 · 보장하지 않는 것
| ✅ 보장 | 플랜별 분당 최소 처리 건수(위 요금 표의 장문 보장 열) · 월 포함 크레딧 |
| ❌ 비보장 | 개별 요청의 응답 시간 · 순간 동시 처리 건수 · 대기 없는 즉시 시작 |
보장치는 하한이고, 동시 상한 열은 여유가 있을 때 허용하는 버스트입니다. 평소에는 상한까지 나가고, 몰릴 때도 보장치 아래로는 내려가지 않습니다.
한도를 넘겨 도착한 요청은 거절되지 않고 순서를 기다립니다. 필요한 만큼 한꺼번에 호출하셔도 되고, 몇 개씩 나눠 보낼지 직접 맞추실 필요가 없습니다. 최대 90초를 기다려도 자리가 나지 않을 때만 429 LONGFORM_BUSY 로 응답하며, 이때는 Retry-After(30초) 후 같은 요청을 그대로 다시 보내시면 됩니다.
보장 건수로 소요 시간을 계산하실 수 있습니다. 예를 들어 Scale 플랜에서 20명이 동시에 결제하고 1인당 장문 4건이면 80건 ÷ 6건/분 = 최대 14분입니다. 최종 이용자 안내 문구는 이 값에 여유를 더해 정하시면 됩니다.
🧵 대량 처리 설계
왜 대부분의 운세 서비스가 “결제 후 N분 이내 발송” 방식인가
AI 장문 풀이는 1건에 1분 안팎이 걸립니다. SAZU 만의 제약이 아니라 AI 생성 서비스 공통의 구조입니다. 결제 응답에서 결과를 기다리면 20명만 몰려도 마지막 이용자는 20분을 기다리게 되고, 그 전에 브라우저·서버 타임아웃이 먼저 발생합니다. 그래서 실제 서비스들은 결제와 생성을 분리합니다 — 결제 즉시 “생성 중”으로 응답하고, 뒤에서 순서대로 만들어 완료되면 알립니다.
방법 1 — 작업 API (권장): 큐를 만들지 않아도 됩니다
POST /api/v1/render/jobs 로 제출하면 즉시 접수증(202)을 받고, 생성은 SAZU 쪽 큐가 순서대로 처리합니다. 플랜 가중치가 반영된 공정 큐라 다른 고객사의 대량 제출에 밀리지 않으며, 응답의 estimatedSeconds 로 최종 이용자에게 “약 N분 내 발송”을 안내할 수 있습니다. 크레딧은 제출 시점에 차감되고 처리에 실패하면 자동 환불됩니다. 결과 수령은 폴링 또는 콜백 중 선택합니다.
🤖 AI 에게 그대로 시키기 — 아래를 복사해 쓰시는 AI 도구에 붙여넣으면 연동 전체를 만들어 줍니다
# 현재 사용중인 AI 도구(Claude · Codex · Cursor · Gemini 등)에 그대로 붙여넣으세요 👇
[목표]
결제 후 SAZU Studio "작업 API" 로 운세 풀이를 비동기 생성하도록 만들어줘.
큐·워커는 만들지 않는다 — 제출만 하면 SAZU 쪽 큐가 순서대로 처리한다.
기존 폴더 구조·상태관리·디자인 컨벤션을 그대로 따르고, 이미 결제 로직이 있으면 그 뒤에 붙여줘.
[만들 것 — 3개]
1) 제출: 결제 성공 시점에 주문의 풀이 건마다 아래 제출 API 를 호출하고, 응답의 jobId 와
estimatedSeconds 를 주문 레코드에 저장한다(같은 X-Request-Id 재제출로 기존 작업이 200 으로 돌아오면 estimatedSeconds 는 없다).
X-Request-Id 헤더에 "주문번호-풀이종류"(예: order-1042-life)를 넣는다 —
같은 값으로 다시 제출해도 새 작업이 생기지 않고 크레딧도 다시 차감되지 않는다(멱등).
2) 수신: 콜백(권장) 또는 폴링 중 하나를 고른다.
- 콜백: 제출 본문에 callbackUrl 을 넣으면 완료·실패 시 그 URL 로 결과가 POST 된다.
서명 검증(아래) 필수. 결과는 완료 후 24시간만 보관되므로 받은 즉시 내 DB 에 저장한다.
- 폴링: 조회 API 를 10초 이상 간격으로 부른다. done 이면 result.text 를 저장한다.
3) 상태 화면: 주문의 작업이 전부 done 이면 결과를 보여주고, 아니면
"생성 중 · 약 N분" 을 보여준다. N = 제출 응답의 estimatedSeconds 를 분으로 올림.
[SAZU 작업 API]
- Node/TypeScript 프로젝트면 공식 SDK 를 우선 사용한다: npm install @sazuapp/studio →
studio.jobs.submit(입력, { requestId }) / studio.jobs.wait(jobId) / verifyStudioCallback(검증).
아래 raw HTTP 명세는 SDK 를 못 쓰는 환경(다른 언어 등)용이다.
- 제출: POST https://www.sazu.app/api/v1/render/jobs
헤더: X-API-Key: <내 키>, Content-Type: application/json, X-Request-Id: <주문번호-종류>
본문: { "service": "life",
"birth": { "birthYear": 1990, "birthMonth": 5, "birthDay": 15,
"birthHour": 10, "isFemale": false, "isLunar": false },
"callbackUrl": "https://내도메인/webhooks/sazu" } // 콜백을 쓸 때만
202 응답: { "data": { "jobId", "status": "queued", "position",
"estimatedSeconds", "creditsReserved", "callbackSecret" } }
callbackSecret 은 콜백을 처음 쓸 때 발급되는 계정 고정값 — 환경변수 SAZU_CALLBACK_SECRET 로 저장.
- 조회: GET https://www.sazu.app/api/v1/render/jobs/{jobId} (헤더: X-API-Key)
data.status: queued | running | done | failed | expired
done → data.result.text 가 완성 풀이.
failed → 크레딧은 자동 환불됨. data.error.message 를 관리자용 실패 목록에 남긴다.
- 콜백 검증: 요청 헤더 X-SAZU-Timestamp 와 X-SAZU-Signature 를 읽고,
기대값 = HMAC_SHA256(SAZU_CALLBACK_SECRET, timestamp + "." + 원문바디) 의 hex.
crypto.timingSafeEqual 로 비교해 불일치면 401. 통과하면
body { jobId, status, result 또는 error } 를 처리하고 200 을 돌려준다.
주의: 검증은 반드시 "파싱 전 원문 바디"로 한다 — JSON.parse 후 재직렬화하면 서명이 어긋난다.
[에러 규칙 — 정확히 지킬 것]
- 제출 402 (구독·크레딧): 재시도해도 같다. 제출을 멈추고 관리자에게 알린다.
- 제출 429 QUEUE_FULL: 내 대기 작업이 200건을 넘었다. 60초 뒤 같은 X-Request-Id 로 재제출.
- 제출 503 METERING_UNAVAILABLE: 크레딧 미차감. 잠시 뒤 같은 X-Request-Id 로 재제출(안전).
- 처리 failed: SAZU 가 이미 재시도까지 마치고 확정한 것 + 크레딧 자동 환불.
다시 시도하려면 새 X-Request-Id 로 제출한다(같은 id 는 실패한 기존 작업을 그대로 돌려준다).
[보안]
- API 키와 SAZU_CALLBACK_SECRET 은 서버 환경변수로만 읽는다. 코드·클라이언트·git 노출 금지.
- 제출·조회는 반드시 서버에서만 한다. 브라우저에서 SAZU 를 직접 부르지 않는다.
[이용자 안내]
- 결제 완료 화면에 "풀이는 약 N분 내에 준비되며 완료되면 알려드립니다" 를 표시한다
(N = estimatedSeconds 올림 + 여유).
- 실패한 작업은 관리자가 볼 수 있게 목록으로 남긴다.
[마무리]
- 결제 → 제출 → (콜백 또는 폴링) → 저장 → 화면 표시까지 실제로 동작하는지 확인해줘.공식 SDK 로 연동 (Node/TypeScript — 권장)
// 공식 SDK 사용 시 — npm install @sazuapp/studio (Node 18+ · 서버 전용)
import { SazuStudio, verifyStudioCallback } from '@sazuapp/studio'
const studio = new SazuStudio({ apiKey: process.env.SAZU_STUDIO_KEY! })
// 1) 제출 — requestId(멱등키)에 주문번호를 넣으면 재제출해도 이중 차감 없음
const job = await studio.jobs.submit(
{ service: 'life', birth, callbackUrl: 'https://내도메인/webhooks/sazu' },
{ requestId: 'order-1042-life' },
)
// job: { jobId, estimatedSeconds, creditsReserved, callbackSecret? }
// 2-a) 폴링으로 받기 (기본 10초 간격 · 15분 타임아웃)
const done = await studio.jobs.wait(job.jobId)
console.log(done.result.text)
// 2-b) 웹훅으로 받기 — 수신 라우트에서 서명 검증 (파싱 전 원문 바디 사용)
const ok = verifyStudioCallback({
secret: process.env.SAZU_CALLBACK_SECRET!,
timestamp: req.headers.get('x-sazu-timestamp'),
signature: req.headers.get('x-sazu-signature'),
rawBody: await req.text(),
})
// 실패(failed)는 StudioError 로 throw 되고 크레딧은 자동 환불됩니다.HTTP 로 직접 연동 (다른 언어) — 제출 · 수신 · 콜백 검증
# 1) 제출 — 즉시 202 로 접수증을 받습니다
curl -X POST https://www.sazu.app/api/v1/render/jobs \
-H "X-API-Key: sazu_live_..." \
-H "Content-Type: application/json" \
-H "X-Request-Id: order-20260827-0001-life" \
-d '{
"service": "life",
"birth": { "birthYear": 1990, "birthMonth": 3, "birthDay": 15, "birthHour": 10, "isFemale": true },
"callbackUrl": "https://api.example.com/webhooks/sazu"
}'
# 응답 (202)
{
"success": true,
"data": {
"jobId": "8f3c...",
"status": "queued",
"position": 3,
"estimatedSeconds": 61, # "약 N분 내 발송" 안내문의 근거
"creditsReserved": 5, # 제출 시점에 차감 — 실패하면 자동 환불
"callbackSecret": "sazu_whsec_..." # callbackUrl 을 쓰면 서명 검증용 (테넌트당 1개)
}
}# 2-a) 폴링 — 콜백 없이 받는 경우 (10초 이상 간격 권장)
curl https://www.sazu.app/api/v1/render/jobs/8f3c... -H "X-API-Key: sazu_live_..."
# queued → { "status": "queued", "position": 2, "estimatedSeconds": 61 }
# running → { "status": "running" }
# done → { "status": "done", "result": { "text": "...", "meta": { ... } } }
# failed → { "status": "failed", "error": { "code": "...", "message": "..." }, "creditsRefunded": true }
# 결과는 완료 후 24시간 보관됩니다 — 받은 즉시 저장하세요.// 2-b) 콜백 — 완료·실패 시 등록한 URL 로 POST 됩니다 (실패 시 최대 5회 재시도)
// 서명 검증: X-SAZU-Signature == HMAC_SHA256(callbackSecret, timestamp + "." + rawBody)
import { createHmac, timingSafeEqual } from 'node:crypto'
app.post('/webhooks/sazu', (req, res) => {
const timestamp = req.header('X-SAZU-Timestamp')
const signature = req.header('X-SAZU-Signature')
const expected = createHmac('sha256', process.env.SAZU_CALLBACK_SECRET)
.update(timestamp + '.' + req.rawBody).digest('hex')
if (!timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) return res.status(401).end()
const { jobId, status, result, error } = req.body
// status 'done' 이면 result.text 저장, 'failed' 면 error 기록 (크레딧은 이미 환불됨)
res.status(200).end()
})X-Request-Id에 「주문번호-풀이종류」(예:order-1042-life)를 넣으면 재제출이 새 작업·이중 차감을 만들지 않습니다. 작업 API 는 이 값만으로 중복을 가르므로, 한 주문에 풀이가 여러 건이면 건마다 값을 달리해야 합니다 — 같은 값을 다시 보내면 새 작업 대신 기존 작업이200(duplicated: true)으로 돌아옵니다.- 동기 API(
/api/v1/render)는 그대로 유지됩니다 — 즉답이 필요한 단건 일반 운세용입니다. - 완료 결과는 24시간 보관 후 삭제됩니다. 수령 즉시 저장하세요.
방법 2 — 자체 큐: 직접 만드실 경우 표 하나와 워커 하나면 됩니다
- 결제가 완료되면 주문만 저장하고 화면은 바로 “생성 중”으로 넘깁니다. 이 시점에 SAZU 를 호출하지 않습니다.
- 백그라운드 작업이
pending건을 꺼내 호출하고 결과를 저장합니다. 동시 실행 수는 플랜의 동시 상한까지 두시면 됩니다. - 화면은 주문 상태를 폴링하거나(2~5초 간격) 완료 시 알림·메일을 보냅니다.
🤖 AI 에게 그대로 시키기 — 아래를 복사해 쓰시는 AI 도구에 붙여넣으면 위 3가지를 만들어 줍니다
# 현재 사용중인 AI 도구(Claude · Codex · Cursor · Gemini 등)에 그대로 붙여넣으세요 👇
# (참고: 큐를 직접 만들지 않아도 되는 SAZU 작업 API 방식이 따로 있다 — 그쪽을 쓰기로 했다면
# 이 프롬프트 대신 "방법 1 — 작업 API" 의 프롬프트를 쓸 것)
[목표]
결제 후 SAZU Studio 로 운세 풀이를 생성하는 부분을, 결제 응답에서 기다리지 않는
비동기 작업 큐 방식으로 만들어줘. 기존 폴더 구조·상태관리·디자인 컨벤션을 그대로 따르고,
이미 결제 로직이 있으면 그 뒤에 붙여줘.
[왜 큐가 필요한가 — 이 제약을 전제로 설계할 것]
- 장문 풀이 1건은 평균 1분, 최대 5분이 걸린다. 결제 응답에서 기다리면 타임아웃이 난다.
- 결제 1건이 풀이 여러 건(예: 4건)을 만들면 그만큼 배로 걸린다.
- SAZU 는 계정 단위 동시 처리 한도가 있고, 넘으면 HTTP 429 를 준다.
[만들 것 — 3개]
1) 작업 테이블: 주문 1건당 풀이 N행. 컬럼은
id, order_id, service, birth(jsonb), status(pending|processing|done|failed),
attempts, result_text, error, created_at.
(status, created_at) 인덱스. 결제 성공 시점에 pending 행들을 INSERT 한다.
2) 워커: pending 을 꺼내 SAZU 를 호출하고 결과를 저장한다. cron(1분) 또는 큐 트리거로 반복.
3) 상태 화면: 주문의 작업들이 다 done 이면 결과를 보여주고, 아니면 "생성 중"을 보여준다.
2~5초 간격 폴링 또는 완료 시 알림/메일.
[SAZU API]
- POST https://www.sazu.app/api/v1/render
- 헤더: X-API-Key: <내 키>, Content-Type: application/json
- 본문: { "service": "life", "birth": { "birthYear": 1990, "birthMonth": 5, "birthDay": 15,
"birthHour": 10, "isFemale": false, "isLunar": false } }
- 성공: { "success": true, "data": { "text": "완성된 풀이" } }
- 타임아웃은 300초 이상으로 잡을 것 (AbortSignal.timeout(300000)).
[동시 실행 · 재시도 규칙 — 정확히 지킬 것]
- 워커의 동시 실행 수는 상수 CONCURRENCY 로 두고 내 플랜의 '동시 상한' 값을 넣는다.
- 꺼낼 때 status 를 먼저 'processing' 으로 UPDATE 하고 호출한다.
(중복 호출은 크레딧이 두 번 차감된다 — 반드시 막을 것)
- HTTP 429: 크레딧 미차감. Retry-After 헤더 초만큼 기다렸다가 status 를 'pending' 으로
되돌린다. 실패로 세지 않는다.
- HTTP 5xx: 일시 장애. attempts 를 올리고 pending 으로 되돌린다. 3회 넘으면 'failed'.
- HTTP 4xx(400/401/402/409/422): 재시도해도 같다. 즉시 'failed' + error 저장.
[보안]
- API 키는 서버 환경변수 SAZU_STUDIO_KEY 로만 읽는다. 코드·클라이언트·git 에 절대 노출 금지.
- 호출은 반드시 서버(워커)에서만 한다. 브라우저에서 SAZU 를 직접 부르지 않는다.
[이용자 안내]
- 결제 완료 화면에 "풀이는 30분 이내에 준비되며 완료되면 알려드립니다" 를 표시한다.
- 실패한 작업은 관리자가 볼 수 있게 목록으로 남긴다.
[마무리]
- 결제 → 작업 생성 → 워커 처리 → 화면 표시까지 실제로 동작하는지 확인해줘.직접 만드실 경우 — 테이블과 워커
-- 주문 1건당 풀이 N건. 상태로 진행을 추적한다.
create table reading_jobs (
id uuid primary key default gen_random_uuid(),
order_id text not null, -- 결제 건
service text not null, -- 'life' | 'love' | 'decade' | ...
birth jsonb not null,
status text not null default 'pending', -- pending | processing | done | failed
attempts int not null default 0,
result_text text,
error text,
created_at timestamptz default now()
);
create index on reading_jobs (status, created_at);// 워커 — cron(1분)이나 큐 트리거로 반복 실행
const CONCURRENCY = 8 // 플랜의 '동시 상한'
async function runOnce(job) {
const res = await fetch('https://www.sazu.app/api/v1/render', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.SAZU_API_KEY },
body: JSON.stringify({ service: job.service, birth: job.birth }),
signal: AbortSignal.timeout(300_000), // 장문 최대 5분
})
if (res.status === 429) {
// 한도 대기 초과. 크레딧은 차감되지 않았다 — 그대로 다시 큐에 둔다.
const wait = Number(res.headers.get('Retry-After') ?? 30)
return { retryAfterSeconds: wait }
}
const body = await res.json()
if (!res.ok) {
// 5xx 는 일시 장애라 재시도, 4xx 는 고쳐야 풀린다.
return res.status >= 500 ? { retryAfterSeconds: 10 } : { failed: body.error }
}
return { text: body.data.text }
}
// 1) status='pending' 을 CONCURRENCY 만큼 꺼내 'processing' 으로 먼저 바꾼다(중복 호출 방지)
// 2) runOnce 를 병렬 실행한다
// 3) text 면 'done', failed 면 'failed', retryAfterSeconds 면 'pending' 으로 되돌린다재시도 규칙
429—Retry-After초만큼 기다린 뒤 같은 요청을 그대로 재시도합니다. 크레딧은 차감되지 않았습니다.502— 이번 호출을 완성하지 못했습니다. 몇 초 뒤 재시도하고, 3회 연속 실패하면 실패로 확정해 사람이 보게 하세요.4xx(400·401·402·409·422) — 재시도해도 같은 결과입니다. 즉시 실패 처리하고 원인을 고치세요.- 같은 주문을 두 번 호출하지 않도록 상태를
processing으로 먼저 바꾸고 호출하세요 — 중복 호출은 크레딧이 두 번 차감됩니다.
최종 이용자 안내 문구 예시
“결제가 완료되었습니다. 풀이는 30분 이내에 준비되며, 완료되면 알려드립니다.” — 위 처리량 계산값(최대 14분)에 여유를 더한 값입니다. 실제 피크 트래픽에 맞춰 정하세요.
⚠️ 에러 코드
| HTTP | error | 원인 · 해결 |
|---|---|---|
| 401 | UNAUTHORIZED | API 키 없음/오류 → X-API-Key 헤더 확인 |
| 400 | INVALID_INPUT | birth 필드 누락·범위 초과, context 에 없는 키를 보냄 |
| 400 | BAD_JSON | 요청 본문이 JSON 이 아님 |
| 400 | UNSUPPORTED_SERVICE | service 값이 운세 목록에 없음 |
| 400 | PARTNERS_NOT_SUPPORTED | 상대를 받지 않는 운세에 partners 를 보냄, 또는 그 운세의 상대 상한(3명) 초과 → 궁합·연애 운에서만 사용 |
| 400 | PARTNERS_REQUIRED | 궁합 운을 상대 없이 호출 → partners 에 1명 이상 필요(연애 운은 상대 없이도 호출 가능) |
| 400 | PROMPT_TOO_LONG | 레시피가 운세별 분량 한도(글자 수) 초과 |
| 402 | SUBSCRIPTION_REQUIRED | 구독 전 API 호출 → Studio 플랜 구독 필요(API 는 구독자 전용 · 첫 프롬프트 승인 시 지급되는 무료 크레딧은 운세 서비스 준비를 위한 프롬프트 최적화와 서비스 이용 학습용으로 대시보드 샘플 미리보기에서 사용) |
| 402 | CREDITS_EXHAUSTED | 이번 주기 포함 크레딧 소진 + 선결제 크레딧 부족 → 대시보드에서 선결제 크레딧 충전 또는 플랜 상향 |
| 409 | NO_APPROVED_PROMPT | 아직 승인된 프롬프트 없음 → 빌더에서 저장·검토 |
| 409 | IDEMPOTENCY_KEY_REUSED | 같은 X-Request-Id 를 다른 운세에 재사용 → 풀이 종류마다 다른 값을 쓴다(예: 주문번호-종류) |
| 409 | IDEMPOTENCY_KEY_EXPIRED | 그 X-Request-Id 의 결과 보관 기간(24시간) 경과 → 새 값으로 호출 |
| 422 | PROMPT_BLOCKED | 프롬프트가 정책에 부합하지 않음 → 빌더에서 수정 후 다시 저장 |
| 403 | ORIGIN_NOT_ALLOWED | 허용 도메인에 없는 곳에서 호출 → 대시보드에서 허용 도메인 확인 |
| 429 | RATE_LIMITED | 요청 과다 → Retry-After 초 후 재시도 |
| 429 | LONGFORM_BUSY | 장문 동시 생성 한도에 걸림 → Retry-After 헤더(초) 후 재시도하거나 작업 API 로 제출 |
| 429 | QUEUE_FULL | 대기 작업이 테넌트 상한(200건) 초과 → 앞선 작업 처리 후 재제출 |
| 404 | NOT_FOUND | 작업 ID 없음 또는 다른 키의 작업 → jobId 확인 |
| 503 | METERING_UNAVAILABLE | 사용량 기록 일시 실패(크레딧 미차감) → 잠시 후 재시도 |
| 502 | SAZU_UPSTREAM | 사주 계산을 완료하지 못함 → 잠시 후 재시도(크레딧 미청구) |
| 502 | LLM_UPSTREAM | 풀이를 완성하지 못함 → 잠시 후 재시도, 반복되면 프롬프트의 분량·출력 형식 지시를 줄인다(크레딧 미청구 · 작업은 예약분 환불) |
| 422 | OUTPUT_BLOCKED | 풀이 결과가 안전 검사를 통과하지 못해 반환하지 않음 → 프롬프트를 점검한 뒤 재시도(크레딧 미차감) |
| 500 | INTERNAL | 서버 오류 → 잠시 후 재시도, 지속되면 문의 |
모든 에러 응답 형태: { "success": false, "error": "코드", "message": "설명" }
❓ FAQ
Q. 코딩을 전혀 몰라도 되나요?
빌더로 프롬프트만 만들면 풀이 품질을 확인할 수 있습니다. 실제 서비스 연동(API 호출)에만 약간의 개발이 필요합니다.
Q. AI 키나 모델을 따로 준비해야 하나요?
아니요, AI 모델 구독은 이미 SAZU Studio 서비스에 포함되어 있습니다. 프롬프트만 정의하시면 됩니다.
Q. 키가 여러 개 필요한가요?
회전·환경 분리·유출 격리를 위해 최대 3개까지. 모두 같은 빌더·크레딧을 공유합니다.
Q. 키를 여러 개 만들면 동시 호출 한도가 늘어나나요?
아니요. 크레딧과 마찬가지로 동시 한도도 계정 단위라 키를 나눠도 같은 한도를 나눠 쓰게 됩니다. 한도를 넓히려면 플랜을 올리시면 됩니다(동시 호출 참조).
Q. 풀이에 우리 브랜드 안내를 넣을 수 있나요?
네. ④ 출력 형식의 직접 지정 칸에 홍보 문구·링크를 자유롭게 넣으면 풀이 끝에 그대로 반영됩니다(화이트라벨).
Q. 프롬프트를 저장했는데 호출이 안돼요.
검토 통과 전이면
NO_APPROVED_PROMPT가 납니다. 마이페이지 빌더에서 상태가 승인됨인지 확인하세요.Q. 오류 발생 시 어떻게 해야 하나요?
개발 중인 화면에서 브라우저 개발자 도구(F12) → Network 탭 → 붉은색으로 표시된 요청 클릭 → Headers · Response 화면을 캡처해 사용 중인 AI(Cursor·Claude 등)에 보여주고 수정을 요청하세요.
📋 더 빠른 방법: Response 의
error코드와message를 그대로 AI 에 붙여넣으면 원인을 거의 즉답으로 찾아 줍니다. 코드별 의미는 에러 코드 표를 참고하세요.Q. 여러 상품을 하나의 API 키로 운영할 수 있나요?
네. API 키는 계정을 인증하는 수단이며 풀이 종류를 가리키지 않습니다. 발급받은 키 하나로 지원되는 풀이 종류 전부를 호출할 수 있습니다. 상품마다 별도 키를 만드실 필요는 없습니다.
Q. 레시피를 여러 개 저장했을 때 호출 시 어떻게 구분하나요?
호출 본문의
service값이 레시피 선택자입니다. 레시피마다 별도 ID 가 발급되지는 않고, (계정 × 풀이 종류) 단위로 저장된 최신 승인 버전이 다음 호출부터 자동 적용됩니다.Q. 재회운·취업운처럼 전용 풀이 종류가 없는 상품은 어떻게 만드나요?
고민 맞춤분석(consult) 레시피 위에 상황 정보의
context.concern값으로 주제를 지정해 운영하시면 됩니다. 레시피 하나로 상품마다 다른 주제를 돌릴 수 있습니다. 다만 이 종류는 레시피가 하나뿐이라 상품마다 지침을 완전히 분리하기는 어렵습니다.