Combos에서 TikTok 연동 게임 만들기
Gift Arena를 만들어 봅니다. 스트리머가 보스와 싸우고 시청자는 에너지, 회복, 공격 선물로 돕는 게임입니다. 전체 프로젝트, 로컬 선물 테스트, Combos 게시 방법, 실제 TikTok 연동에 필요한 등록 절차를 제공합니다. Combos SDK 1.1.0 기준입니다.
현재 실제 TikTok 상호작용을 활성화할 수 있는 절차는 제공되지 않습니다. 로컬 개발, 선물 시뮬레이션, Combos 게시는 진행할 수 있지만 게시만으로 실제 선물을 받을 수는 없습니다. 뒤의 연동 자료와 실제 LIVE 검수는 향후 플랫폼이 연동을 개방할 때를 위한 준비이며, 지금 신청을 완료할 수 있는 절차가 아닙니다.
1. 선물을 게임 효과로 선언하기
연결 코드보다 규칙을 먼저 정합니다. 플레이어의 초기 체력은 70, 에너지는 40, 보스 체력은 100입니다. 공격은 에너지 10을 소모해 피해 10을 주고, 살아남은 보스는 피해 8로 반격합니다. 시청자는 세 가지 효과로 돕습니다.
| 게임 내 선물 | 고정 instruction | count = "1" | count = "3" |
|---|---|---|---|
| 배터리 | gift_battery | 에너지 +20 | 에너지 +60 |
| 회복 | gift_heal | 체력 +15 | 체력 +45 |
| 섬광 | gift_flash | 보스 체력 −10 | 보스 체력 −30 |
// rules.js — this game's contract
export const GIFT_CATALOG = Object.freeze({
gift_battery: { target: 'energy', perCount: 20, max: 100 },
gift_heal: { target: 'hp', perCount: 15, max: 100 },
gift_flash: { target: 'bossHp', perCount: -10, max: 100 },
});이 선언은 게임 코드 자체에 들어갑니다. SDK 등록 호출이나 TikTok 선물 목록이 아닙니다. 배터리·회복·섬광은 예제의 효과 이름이며 실제 TikTok 선물 이름이나 ID가 아닙니다. 장미나 특정 가격이 자동으로 연결된다고 가정하지 마세요.
이 게임은 1–1000의 정수 수량만 허용하고, 체력·에너지는 최대 100, 보스 체력은 최소 0으로 제한합니다. 선물은 턴을 소모하지 않습니다. 상한에 도달해 수치가 증가하지 않아도 성공으로 처리합니다. 승패가 결정된 뒤의 새 명령은 false를 반환하며 새 라운드부터 다시 받습니다. 이는 플랫폼 제한이 아닌 예제 규칙입니다. 자신의 게임에서도 연속 선물, 재사용 대기시간, 라운드 전환, 고비용 효과를 설계하고 같은 규칙을 매핑 담당자에게 전달하세요.
2. 게임과 플랫폼의 역할 이해하기
시청자 → TikTok 선물 매핑 → Combos → SDK onCommand → 게임 효과 → 불리언 결과 → Combos → TikTok ACK.
| 담당 | 역할 |
|---|---|
| 게임 | 지원 명령 선언, 효과 실행·저장, 중복 제거, 실제 결과 반환 |
| Combos 호스트와 SDK | 로그인·실행 연결, 세션 갱신, 전송, 하트비트, 재연결, 결과 전달 |
| Combos / TikTok 연동 담당자 | 게임 진입점·허용 계정 등록, 실행 경로, 실제 선물과 명령의 매핑 |
매핑 결과가 instruction: "gift_flash", count: "3"이면 보스 체력을 30 줄입니다. count는 매핑된 명령 수량이며 코인 가격이나 선물 개수와 반드시 같지는 않습니다. 콤보의 수량 변환도 등록할 때 확인하세요. 게임에서 launchData 해석, TikTok 요청 서명, 별도 WebSocket, webhook을 구현할 필요는 없습니다.
3. 수신 명령 계약 구현하기
type TTLiveCommand = {
messageId: string;
instruction: string;
count: string;
timestamp: string;
};| 필드 | 처리 방식 |
|---|---|
messageId | 불투명한 중복 제거 키. 같은 메시지의 효과를 두 번 실행하지 않음 |
instruction | 선언한 문자열과 정확히 일치시킴. 미지원 명령은 거부 |
count | 10진수 정수 문자열. 검증하고 안전한 범위로 제한한 뒤 Number로 변환 |
timestamp | 원본 명령의 시간 문자열. 신원, 중복 제거 키, 엄격한 순서 보장이 아님 |
공개 명령에는 시청자 ID, 닉네임, 실제 선물 ID가 없습니다. API가 제공하지 않는 필드로 시청자별 순위를 만들 수는 없습니다.
효과 저장이 확정되면 true, 명확한 거부는 false, 결과를 확인할 수 없으면 예외를 반환합니다. 저장 실패처럼 결과가 불명확하면 ACK되지 않고 재전송될 수 있습니다. 모든 오류를 성공으로 바꾸거나, 일부 효과가 적용됐는지 모르는 상태에서 실패로 단정하지 마세요.
SDK는 현재 문서 안에서 미확인 결과를 재전송합니다. 새로고침 후의 중복은 게임도 처리해야 합니다. 예제는 게임 상태와 메시지 결과를 하나의 IndexedDB 트랜잭션에 저장하고 커밋 후 불리언을 반환합니다. 중복은 기존 결과만 반환합니다. 새 라운드에서도 처리 기록을 보존하며 LIVE 저장은 Combos 계정·게임별로, 연습과 별도로 분리합니다.
연결 상태 읽기
getTTLiveClient()는 게임 문서마다 하나의 클라이언트를 반환합니다. getLiveStatus()로 조회하고, onStatusChange()는 현재 상태를 즉시 알린 뒤 변경을 알립니다. state, reason, action, confirmedAtMs를 포함합니다. 마지막 필드는 시작·하트비트가 확인된 밀리초 시각이며 0은 알 수 없음을 뜻합니다.
connecting: 연결 시작 중.connected: 상호작용 세션 확인됨.recovering: SDK의 재연결을 기다림.unknown: 현재 확인 불가. 방송 종료를 의미하지 않습니다.ended: 상호작용 세션 종료.action의wait,none,relaunch_game을 따릅니다.relaunch_game이면 LIVE Studio에서 이 게임을 다시 열도록 안내하며, 연결 문제만으로 방송을 재시작하라고 하지 않습니다.
4. 완성된 데모 실행하기
준비와 실행
ZIP을 풀고 최신 브라우저와 로컬 정적 서버용 Python 3를 준비합니다. Node나 npm은 필요 없습니다. tiktok-arena 폴더 구조를 유지합니다.
cd tiktok-arena
python3 -m http.server 8080 --bind 127.0.0.1http://127.0.0.1:8080/에서 연습 시작을 누릅니다. 모듈은 HTTP로 불러와야 하므로 index.html을 더블 클릭하지 마세요. 온라인 데모는 설치 없이 사용할 수 있습니다. 게임도 사이트와 같은 10개 언어를 지원합니다.
| 파일 | 역할 |
|---|---|
rules.js | 선물 선언, 전투 규칙, 수량 검증, 중복 제거 |
storage.js | 게임 상태와 처리 기록의 원자적 저장 |
connection.js | SDK 기능 확인, 로그인, 연결, 취소 |
game.js | LIVE와 연습의 공통 처리기 및 화면 |
index.html, style.css, draw.js, i18n.js | 레이아웃, 캔버스, 10개 언어 UI |
재현 가능한 세 가지 데모
첫 두 행은 각각 새 라운드에서 시작합니다. 세 번째는 초기화 없이 두 번째에 이어서 진행합니다. 초기 체력 70, 에너지 40, 보스 체력 100입니다. 선물 버튼은 새 메시지를 만들며 마지막 메시지 재전송은 같은 ID를 사용합니다.
| 데모 | 동작 | 예상 결과 |
|---|---|---|
| 단일 선물 | 수량 1, 배터리·회복·섬광 순서로 클릭 | 에너지 60, 체력 85, 보스 체력 90. 모두 true |
| 연속 선물과 중복 | 수량 3으로 섬광, 이어서 재전송 | 두 번 모두 보스 체력 70. 두 번째는 true, duplicate: true |
| 복구와 거부 | 새로고침, 연습 시작, 재전송 후 알 수 없는 명령 | 보스 체력 70 유지. 미지원 명령은 false, 상태 불변 |
수량 0, 1.5, 1001, 9007199254740993도 효과 없이 false가 나와야 합니다. 새 라운드에서 섬광 ×10으로 이긴 뒤 보내는 새 선물은 다음 라운드까지 거부됩니다. 공격과 충전으로 일반 전투도 해보세요. 마지막 수신 패널에 입력·결과·최종 수치가 표시됩니다. 로컬 합성 명령으로, 선물 구매나 TikTok ACK 전송은 하지 않습니다.
5. 같은 게임을 Combos에서 연결하기
게시할 때 connection.js와 game.js를 유지합니다. 호스트가 window.combos를 주입하므로 별도 npm SDK나 중복 SDK 스크립트는 필요 없습니다. Combos LIVE 연결 버튼은 다음을 수행합니다.
init()으로getTTLiveSession기능과 클라이언트 getter를 확인합니다. 기능 이름 자체는 직접 호출하는 공개 메서드가 아닙니다.- 버튼 동작에서
checkSession(), 필요하면login()을 실행합니다. 취소 시 멈추고 성공 시 원래 동작을 계속합니다. getUserInfo()로 저장 영역을 분리합니다. ID는 인증 정보나 서버 권한 증명이 아닙니다.- 상태 구독 후
getTTLiveClient().connect({ onCommand })에 연습과 같은 처리기를 전달합니다. - 재시도 대기 중에도 연결 해제 / 취소가 작동합니다. 취소·페이지 이탈 시 구독을 해제하고
disconnect()를 호출합니다.
아래 핵심 로직은 다운로드에 포함되어 있고 전체 버전은 화면도 갱신합니다. store.update()는 storage.js의 트랜잭션이며 SDK API가 아닙니다.
import { executeCommand } from './rules.js';
// `store` is the account/game-scoped store opened by prepareStore().
function commandHandler(store) {
return async (command) => {
const { result } = await store.update((saved) =>
executeCommand(saved, command),
);
return result; // State + receipt committed; no catch-and-return-false.
};
}재시도 중 connect()는 계속 대기할 수 있습니다. Promise가 끝났다는 사실만으로 실제 선물 효과를 입증할 수 없습니다. LIVE 모드에서는 모의 버튼을 숨기며 등록된 세션에서 효과와 실행 결과를 함께 확인해야 합니다.
6. Combos에 게시하기
공식 Combos CLI 를 설치합니다. 데모에서 PNG 표지 저장을 누르고 cover.png를 tiktok-arena 폴더 옆에 둡니다. 그 상위 폴더에서 실행합니다.
combos --version
combos account login
combos post create --dir ./tiktok-arena --title 'Gift Arena' --cover ./cover.png --platform pc --screen-orientation landscape --allow-recommend=false
combos post get게시할 계정으로 브라우저 로그인을 완료합니다. 반환된 공유 링크를 열고 Combos 플레이어 안에서 확인하세요. 생성된 combos.json 연결 파일을 보존하고, 같은 디렉터리에서 동일한 게시물을 업데이트합니다.
combos post update --dir ./tiktok-arena --platform pcPC 가로 화면 정적 게임입니다. 업로드 폴더의 최상위에 index.html과 모든 상대 경로 리소스가 있어야 합니다. 게시는 TT를 자동 활성화하지 않습니다. 일반 공유 링크는 연습을 할 수 있지만 등록된 LIVE Studio 실행 맥락 없이 실제 세션을 만들어내지는 못합니다. 자세한 절차는 H5 게시를 참고하세요.
7. 향후 연동에 필요한 자료 준비하기
현재 실제 TikTok 상호작용의 활성화 진입점이나 확정된 신청 절차는 없습니다. 게임·계정 등록과 실제 선물 매핑은 플랫폼의 연동 안내를 기다려야 합니다. SDK와 CLI는 공개 셀프서비스 등록 API를 제공하지 않습니다. 다음은 향후 연동을 위한 준비 자료이며 현재 접수 중인 신청이 아닙니다.
| 자료 | 필수 내용 |
|---|---|
| 게임 | 게시된 공유 URL, 연결된 Post / 프로젝트 ID, 게임 이름, PC 가로 화면 |
| 테스트 계정 | 지정된 연동 채널로 테스트·스트리머 계정 전달. 비밀번호·세션 토큰 제외 |
| 효과 명세 | 세 명령, 수량당 효과, 1–1000 범위, 상한, 라운드 종료 후 동작 |
| 매핑 요청 | 허용된 실제 TikTok 선물과 명령의 대응, 수량·콤보 환산, 기대 효과 |
| 검수 계획 | 단일 선물, 콤보, 재전송·복구, 세션 종료 테스트 |
테스트 전에 정확하게 등록된 실행 진입점, 게임·계정 자격, 선물 매핑 완료를 담당자에게 확인받으세요. 실제 선물 ID·이름·가격은 설정된 목록에서 가져옵니다. 섬광 ×3으로 합의했다면 다음을 수신해야 합니다.
{
"instruction": "gift_flash",
"count": "3"
}TikTok 비밀키, CAS 토큰, 직접 만든 launchData를 게임에 넣지 마세요. 플랫폼이 처리합니다. 등록 전에는 게시된 Combos 게임과 작동하는 시뮬레이터가 완성된 것이며 실제 TikTok 검수는 아직 남아 있습니다.
8. 활성화가 제공된 후 실제 LIVE 검수하기
플랫폼이 활성화 절차를 제공하고 게임 진입점, 허용 계정, 선물 매핑을 확인한 뒤에만 아래 실제 검수를 진행할 수 있습니다. 지금은 위의 로컬 시뮬레이션과 Combos 게시 확인을 완료하세요. 이 확인은 실제 LIVE 검수를 대신하지 않습니다.
- 허용된 계정으로 TikTok LIVE Studio의 등록된 진입점에서 실행합니다. 게임 안에서 연결하고
connected를 확인합니다. - 테스트 참여자의 동의하에 설정된 테스트 상호작용을 한 번 실행합니다.
messageId, 명령·수량, 전후 수치, 반환 결과를 기록하고 담당자가 해당 ACK 수신을 확인하게 합니다. 인증 정보나 시청자 개인정보는 기록하지 않습니다. - 합의된 콤보 수량으로 반복해 수량 × 효과, 상한, 중복 적용 방지를 로컬 데모와 비교합니다.
- 잠시 연결을 끊었다 복구해 같은 명령이 재실행되지 않는지 봅니다. 호스트가 지원하는 실행 흐름 안에서 새로고침해 상태·기록 복구를 확인하고, 재실행을 요구하면 따릅니다.
- 종료 후
ended/relaunch_game, 연결 중 취소, 게임 이탈을 확인합니다. 이전 명령이 추가 효과를 내면 안 됩니다.
브라우저 저장은 같은 브라우저·출처·계정·게임 안에서만 복구합니다. 기기 간 복구나 신뢰할 수 있는 보상 시스템은 제공하지 않습니다. LIVE 중 데이터를 지우지 마세요. 10,000개 기록에 도달하면 기존 결과를 지우지 않고 새 명령 수신을 멈춥니다. 영구 보상이나 실제 운영 규모에는 자체 신뢰할 수 있는 백엔드에서 효과와 처리 기록을 함께 커밋하고 확정 결과를 기준으로 보존 정책을 정하세요.
문제 해결
| 증상 | 확인할 사항 |
|---|---|
unsupported_host | 지원되는 Combos 플레이어, init() 기능, SDK 제공 여부 |
login_cancelled / missing_profile | 올바른 계정으로 로그인 후 재연결 |
tt_not_launched, ended, relaunch_game | 등록·계정 자격 확인 후 LIVE Studio에서 등록 게임 다시 열기 |
| 연결됐지만 효과 없음 | 선물 매핑, 정확한 명령·수량, 라운드 상태. 담당자에게 메시지 ID 추적 요청 |
false | 미지원 명령, 잘못된 수량, 종료된 라운드 등 명확한 거부 |
invalid_save, receipt_capacity, storage_blocked, operation_failed | LIVE 테스트를 멈추고 로컬 저장 가능 여부와 콘솔 확인. 기록을 보존하고 원인 해결 후 재개. 불명확한 결과를 성공 ACK로 바꾸지 않기 |