본문 바로가기
tokenAppsPLAY & COLLECT

자주 묻는 질문

2026-09-18 추가: SDK 설치와 게임 전용 임베드는 별도 납품 항목입니다. 게임 전용 임베드 가이드에 따라 구현·배포한 주소를 등록하세요. SDK를 넣은 홈페이지도 플레이어 안에서는 스크롤이 생길 수 있습니다.

통합 과정에서 실제로 막히는 지점들을 모았습니다. 여기 없는 질문은 cs@tokenpost.kr 로 보내주세요 — 답변과 함께 이 문서에도 추가됩니다.

통합

SDK를 꼭 붙여야 게임을 올릴 수 있나요?

아닙니다. 등록·노출·플레이·플레이 시간 측정은 SDK 없이 전부 동작합니다. 측정은 플랫폼의 플레이어 페이지가 게임 바깥에서 수행하기 때문에 게임 쪽 코드가 전혀 필요 없습니다.

SDK가 여는 것은 그 다음 단계들입니다: 플레이 TAP(토큰앱스 포인트) 적립 연동, 계정 세이브, 보상형 광고, 이어하기 시트, 재화 판매. 이 중 필요한 것만 골라 붙이면 되고, 최소 통합은 스크립트 한 줄 + 함수 호출 두 개입니다. 시작하기의 "5분 통합" 절을 따라 하시면 됩니다.

게임이 TokenApps 밖(자체 사이트)에서 열리면 SDK가 오류를 내나요?

아닙니다. SDK는 부모 창(TokenApps 플레이어)이 있을 때만 동작하고, 없으면 조용히 대기 상태로 남습니다. ready()를 불러도, track()을 불러도 아무 일도 일어나지 않을 뿐 오류는 발생하지 않습니다.

따라서 같은 빌드를 자체 사이트와 TokenApps에 동시에 배포해도 됩니다. "TokenApps에서 열렸는지" 확인하는 분기 코드를 넣을 필요가 없습니다. 굳이 구분하고 싶다면 session 메시지 수신 여부로 알 수 있습니다 — 메시지가 왔다면 TokenApps 안입니다.

Unity / Godot / Cocos WebGL 빌드인데 v1.js를 포함하기 어렵습니다.

SDK 파일은 postMessage 규격을 감싼 편의 레이어일 뿐이라, 엔진 쪽에서 postMessage를 직접 다룰 수 있다면 SDK 없이 규격만 구현해도 완전히 동일하게 동작합니다. 모든 메시지는 다음 형식(envelope)을 따릅니다:

{ "__tokenapps": 1, "v": 1, "type": "ready", "payload": {} }

전체 메시지 표(양방향 12종)와 REST 규격은 규격서 §4~6에 있습니다. Unity라면 Application.ExternalCall 대신 jslib 플러그인에서 window.parent.postMessage(...)를 호출하고, window.addEventListener("message", ...) 로 응답을 받아 SendMessage로 게임 오브젝트에 전달하는 구조를 권장합니다.

테스트는 어디서 하나요?

제출 → 승인(Basic) 직후부터 실제 플레이 페이지 (tokenapps.io/app/<슬러그>/play)에서 테스트할 수 있습니다. Basic 단계는 직접 링크로 접근 가능하므로 팀 내부 QA에 그대로 쓰시면 됩니다. 승인 전에 통합을 먼저 검증하고 싶으시면 레퍼런스 게임의 소스가 전체 계약의 동작 예제입니다 — 같은 호출을 그대로 옮기시면 됩니다.

SDK는 npm으로 설치하나요?

아니요 — 스크립트 태그 한 줄이 공식 설치 방법입니다:

<script src="https://tokenapps.io/sdk/v1.js"></script>

빌드 도구·번들러·패키지 매니저가 전혀 필요 없고, v1 경로는 하위호환을 보장하며 항상 최신 v1.x가 배포됩니다(별도 업데이트 작업이 없습니다). 정적 HTML 한 장짜리 게임부터 Vite·React 프로젝트까지 같은 방법으로 동작합니다. 번들러 프로젝트에서는 window.TokenApps를 그대로 사용하시면 됩니다 — 타입이 필요하면 규격서의 TypeScript 타입 블록을 복사하세요.

저장소 packages/sdk에 v1.4 타입·로더가 있습니다. 2026-09-17 공개 npm 레지스트리 확인 결과 아직 공개되지 않았으므로 CDN 스크립트나 저장소의 로컬 패키지를 사용하세요.

AI 코딩 도구로 통합해도 되나요? (MCP)

권장합니다. Claude Code·Cursor 같은 AI 도구로 게임을 만들고 있다면, 문서를 복사해 붙여넣는 대신 TokenApps 문서 MCP 서버를 연결하세요:

claude mcp add --transport http tokenapps https://tokenapps.io/api/mcp

연결하면 AI가 list_docsread_doc으로 규격서·가이드·FAQ를 직접 읽고 검색(search_docs)할 수 있어, "TokenApps SDK 붙여줘" 한 문장으로 통합이 끝나는 경험에 가까워집니다. 읽기 전용이고 인증이 필요 없습니다.

MCP를 지원하지 않는 도구에는 /llms.txt(문서 색인)와 /llms-full.txt(전체 문서 원문)를 주소로 전달하면 됩니다.

TAP

session_complete를 보냈는데 status: "ignored"가 옵니다.

가장 흔한 원인은 45초 게이트입니다. 플랫폼은 플레이 시간을 자체 측정하고, 그날 실측 플레이가 45초 미만이면 session_complete 지급을 보류합니다. 게임을 로드하자마자 이벤트를 쏘는 부정 사용을 막기 위한 장치입니다.

게임 쪽에서 대응할 것은 없습니다. 지급이 하루 1회 멱등이라 이벤트를 여러 번 보내도 안전하고, 유저가 실제로 45초 이상 플레이한 뒤 다음 판이 끝날 때 자연스럽게 지급됩니다. 판이 끝나는 지점마다 한 번씩 보내는 것이 정석입니다.

그 외의 ignored: 화이트리스트에 없는 이벤트 이름을 보낸 경우입니다. 현재 지급 대상 이벤트는 session_complete 하나이며, 다른 이름은 측정용으로만 기록됩니다.

점수가 높으면 TAP을 더 주는 구조를 만들 수 있나요?

현재는 제공하지 않습니다. 성과(점수·승패·순위) 연동 보상은 사행성 규제(게임산업법) 와 맞닿는 영역이라, 법률 검토를 마치기 전까지는 지급을 "오늘 이 게임을 한 판 완주했다"는 세션 단위로만 운영합니다. submitScore()로 보낸 점수는 지금은 표시·랭킹용입니다. 환전·양도가 불가능한 폐쇄형 TAP의 성과 연동은 검토와 함께 단계적으로 열릴 수 있는 로드맵 항목입니다.

지금 당장 가능한 것도 있습니다:

  • 게임 내 재화는 점수 연동이 자유롭습니다. 게임 자체 화폐·아이템을 성과에 따라 주는 것은 게임의 설계 영역입니다 (플랫폼 TAP만 제한 대상).
  • 리더보드는 플랫폼이 제공하므로, 순위 경쟁 자체는 이미 동작합니다.

자세한 배경은 심사 정책 §4를 참고해주세요.

TAP 단가와 일일 상한은 얼마인가요?

서버 정책 값이라 문서에 고정 기재하지 않습니다(사업 판단에 따라 조정될 수 있습니다). 게임은 값을 알 필요 없이 points 응답만 처리하면 됩니다:

TokenApps.on("points", function (p) {
  // p.status: "awarded"(지급, p.delta·p.balance 포함) | "duplicate"(오늘 몫 완료)
  //           | "capped"(유저의 일일 상한 도달) | "ignored" | "signin_required"
});

cappedduplicate도 오류가 아니라 정상 응답입니다 — 조용히 넘어가거나 가벼운 안내 정도가 적절합니다.

펀딩은 무엇인가요? 내 게임도 캠페인을 열 수 있나요?

펀딩은 유저가 폐쇄형 TAP으로 게임을 응원하는 기능입니다. 캠페인이 목표를 달성하면 보상 풀 TAP이 기여도 순으로(많이, 먼저 참여한 순) 참여자에게 분배되고, 목표에 도달하지 못하면 참여 TAP이 전액 환급됩니다. 현금 결제나 환전 구간은 어디에도 없습니다.

게임 입장에서는 출시 전 수요 검증과 초기 팬 확보 수단입니다. 캠페인 개설은 현재 플랫폼이 게임을 선정해 진행합니다 — 열고 싶은 게임이 있다면 cs@tokenpost.kr로 알려주세요. 개발자 콘솔에서 직접 개설하는 셀프서비스는 로드맵에 있습니다.

저장

localStorage가 동작하지 않습니다.

외부 HTTPS 프레임은 자체 출처를 유지하지만 브라우저 설정이 저장소를 차단할 수 있습니다. localStorage·쿠키·IndexedDB 접근을 예외 처리하고 메모리 대체 경로를 유지하세요.

TokenApps.save() / load()가 이 환경의 표준 저장소입니다. 유저 계정에 저장되므로 기기를 바꿔도 이어지고, 게임당 1슬롯·직렬화 64KB까지 지원합니다. 게스트에게 저장이 제공되지 않는 것은 의도된 동작입니다. canSave()로 확인하고 조용히 건너뛰시면 됩니다. 예제는 SDK 가이드 §3에 있습니다.

세이브가 64KB를 넘으면 어떻게 되나요?

413 too_large로 거절되고 기존 세이브는 유지됩니다. 세이브는 진행 상태의 요약이지 전체 로그가 아닙니다 — 리플레이·상세 기록이 필요하면 게임 자체 서버에 두고, 세이브에는 조회 키만 남기는 구조를 권장합니다.

세이브 슬롯을 여러 개 쓸 수 있나요?

현재는 게임당 1슬롯입니다. 슬롯이 여러 개 필요하면 저장값 안에 직접 구조를 만들면 됩니다: save({ slots: { a: {...}, b: {...} } }). 저장 API의 data 필드로 감싸는 구조는 이런 확장을 위해 의도적으로 여유를 둔 설계입니다.

광고 · 이어하기 · 재화

requestRewardedAd()가 계속 unavailable로 옵니다.

대부분 정상 동작입니다. 다음 상황이 전부 unavailable 하나로 옵니다:

상황 비고
게스트(비로그인) 플레이어 보상 지급에 계정이 필요합니다
최근 3분 내에 이미 광고를 봄 전역 최소 간격
유저의 일일 시청 한도 도달 유저당·(유저, 게임)당 상한
유저의 일일 TAP 상한 도달 0 TAP 시청을 원천 차단하기 위한 선검사
앱이 Basic 단계 소프트런칭 중에는 수익화가 닫혀 있습니다
허용되지 않은 placement 현재 게임 장르는 revive, bonus_points

사유별로 다르게 대응할 필요는 없습니다 — 광고 없이 진행되는 경로 하나만 유지하시면 전부 커버됩니다. 이 원칙은 심사 요건이기도 합니다.

이어하기 시트와 광고 직접 호출, 뭘 써야 하나요?

게임오버 이어하기 용도라면 requestContinue()를 권장합니다. 플랫폼이 "TAP으로 이어하기 / 광고 보고 이어하기 / 그만하기" 3택 시트를 띄워주므로 플레이어의 선택지가 넓고, 게임 코드는 결과 분기 하나로 끝납니다. requestRewardedAd()는 그 외 지점(보너스 재화, 부활 외 혜택)에 쓰는 저수준 API입니다. 두 API를 같은 게임에서 함께 써도 됩니다.

재화(SKU)는 어떻게 등록하나요? 가격을 게임에서 정할 수는 없나요?

등록은 셀프서비스입니다. 내 게임에서 게임의 "상품 관리"를 열고 SKU(영문 소문자·숫자·-·_), 이름(한/영), 가격(TAP), 종류(consumable=반복 구매 / durable=1회 소장)를 직접 등록·수정할 수 있습니다. 가격 변경은 이후 구매부터 적용되고, 실제 판매는 Full 런칭부터 열립니다(등록은 언제든 미리 가능).

가격을 게임 쪽에서 정하는 것은 구조적으로 불가능합니다. 구매 관련 어떤 메시지에도 금액 필드가 없고, 결제 시트와 청구는 서버에 등록된 가격만 사용합니다. 게임 UI에 표시할 가격은 getProducts()로 받아 그리시면 서버와 항상 일치합니다.

구매를 게임 서버에서 검증하고 싶습니다.

클라이언트의 purchase_result를 그대로 믿지 않는 것이 맞습니다. 권장 패턴은 원스토어·구글플레이의 영수증 검증과 같은 역할을 합니다:

  1. 클라이언트가 session에서 받은 token을 게임 서버로 전송합니다.
  2. 게임 서버가 GET {api}/api/game/inventory를 그 토큰의 Bearer 인증으로 호출합니다.
  3. 응답의 보유 목록을 확인한 뒤 서버 권위로 지급합니다.

토큰은 해당 (유저, 게임) 쌍에만 유효하므로, 게임 서버가 얻는 권한도 딱 그만큼입니다. 규격서 §6.8-6.9 참조.

심사 · 노출

게임 화면이 TokenApps 안에서 하얗게 나옵니다.

두 가지를 순서대로 확인해주세요:

  1. 프레임 차단 헤더 — 응답에 X-Frame-Options: SAMEORIGIN/DENY 또는 CSP frame-ancestors 제한이 있으면 브라우저가 프레임 자체를 막습니다. 헤더를 제거하거나 tokenapps.io를 허용해주세요.
  2. 프레임 감지 코드 — 헤더가 없는데도 하얗게 나온다면, 코드가 window.top !== window 등을 검사해 렌더를 중단하는 경우가 많습니다. 서드파티 쿠키 의존(로그인 세션 필수 진입)도 같은 증상을 만듭니다.

제출 전에 승인 후 받게 될 주소 형태인 tokenapps.io/app/<슬러그>/play에서 직접 확인하는 것이 가장 빠릅니다. 화면이 6초 이상 비어 있으면 플레이어가 "새 탭에서 열기" 안내를 자동으로 띄우지만, 이는 응급 통로일 뿐 임베드 렌더가 심사 기준입니다.

승인됐는데 홈 추천·카테고리에 안 보입니다.

승인 직후는 Basic 단계입니다. 홈의 "새 게임" 구좌와 직접 링크로 노출되고, 플레이·측정·TAP은 전부 동작합니다. 플레이 지표(플레이어 수·평균 세션· 재방문율)가 쌓이면 운영팀이 Full로 승격하며, 그때부터 추천·카테고리 전면에 진열되고 광고·재화 수익화가 열립니다. 절차 전체는 심사 정책 §1에 있습니다.

수익 정산은 언제부터 가능한가요?

광고망 연동과 함께 열립니다. 정산 구조(수익 이벤트 기록 → 월 마감 → 은행 또는 USDC 지급)는 설계가 확정되어 있고, 수수료율·최소 지급액 등 조건은 연동 시점에 공지됩니다. 미리 논의가 필요하시면 cs@tokenpost.kr 로 연락해주세요.

SDK 버전은 어떻게 확인하나요?

TokenApps.version이 "1.4.0" 형식의 문자열을 반환합니다. 다만 분기가 필요할 때는 버전 비교보다 기능 감지를 권장합니다:

if (typeof TokenApps.requestPurchase === "function") { /* v1.3+ */ }

v1.x 안의 모든 변경은 하위호환이므로, 오늘 통합한 코드는 앞으로의 v1 업데이트에서 수정 없이 계속 동작합니다. 변경 이력은 릴리스 노트를 참고해주세요.