💡
게임
index.html에 아래 스크립트 태그 한 줄만 추가하면 끝입니다.
<script src="https://movigames.com/sdk/mssdk.js"></script>
SDK가
gameId(URL 파라미터 — 포털이 iframe 로드 시 자동으로 붙여줌)와
JWT 토큰(localStorage, 같은 도메인 공유)을 자동으로 읽어 API를 직접 호출합니다.
비로그인 유저는
localStorage로 자동 폴백됩니다.
세이브 함수
MSSDK.set(key, value)
키 하나를 저장합니다. 로컬(localStorage)에 즉시 기록되고, 서버 전송은 30초 쓰로틀로 지연됩니다.
⚠️
get() 또는 getAll()을 한 번도 호출하지 않고 set()/setMany()를 먼저 호출하면 기존 데이터를 못 보고 덮어쓸 수 있어 에러(alert + throw)가 발생합니다. 게임 시작 시 getAll()로 기존 세이브를 먼저 불러온 뒤 저장하세요.
파라미터
| 이름 | 타입 | 설명 |
| key | string | 저장 키 이름 |
| value | any | JSON 직렬화 가능한 값 (최대 1MB) |
반환값 (result)
{ ok: true, source: 'local' } // 비로그인 — 로컬에만 저장됨
{ ok: true, buffered: true } // 로그인 — 로컬 저장 완료, 서버 전송은 대기 중(쓰로틀)
예시
await MSSDK.set('gold', 100);
await MSSDK.set('items', ['sword', 'shield']);
MSSDK.get(key)
키 하나를 불러옵니다. 아직 서버로 전송되지 않은 값이 있으면 그 값을 우선 반환합니다.
파라미터
반환값 (result)
Promise<any | null> // 저장된 값 그대로, 저장된 적 없으면 null
예시
const gold = await MSSDK.get('gold'); // → 100
const items = await MSSDK.get('items'); // → ['sword', 'shield']
const none = await MSSDK.get('nope'); // → null (저장된 적 없음)
MSSDK.setMany(obj)
여러 키를 한 번에 저장합니다. 동작 방식은 set과 동일(로컬 즉시 기록 + 30초 쓰로틀).
파라미터
| 이름 | 타입 | 설명 |
| obj | object | { key1: value1, key2: value2, … } — 최대 50개 키 |
반환값 (result)
{ ok: true, source: 'local' } // 비로그인
{ ok: true, buffered: true } // 로그인, 서버 전송 대기 중
예시
await MSSDK.setMany({ gold: 100, level: 3, items: ['sword'] });
MSSDK.getAll()
저장된 모든 키-값을 한 번에 불러옵니다. 서버 데이터와 아직 전송되지 않은 값을 병합해 반환합니다.
반환값 (result)
Promise<object> // { key1: value1, key2: value2, … } — 저장된 게 없으면 빈 객체 {}
예시
const all = await MSSDK.getAll();
// → { gold: 100, level: 3, items: ['sword'] }
MSSDK.remove(key)
키 하나를 삭제합니다. 쓰로틀 없이 즉시 서버에 반영됩니다.
파라미터
반환값 (result)
{ ok: true } // 로그인 여부와 무관하게 동일
예시
await MSSDK.remove('gold');
MSSDK.removeAll()
이 게임에 저장된 세이브 데이터를 전부 삭제합니다. 쓰로틀 없이 즉시 반영됩니다.
반환값 (result)
{ ok: true }
예시
await MSSDK.removeAll();
MSSDK.isLoggedIn()
현재 로그인 여부를 동기적으로 확인합니다 (네트워크 요청 없음).
반환값 (result)
boolean
예시
if (MSSDK.isLoggedIn()) { /* 서버 저장 */ } else { /* localStorage 폴백 */ }
MSSDK.flush()
쓰로틀을 무시하고 대기 중인 변경사항을 즉시 서버로 전송합니다. 게임 종료 직전 등 확실한 저장이 필요할 때 사용합니다.
반환값 (result)
없음 (void) — 전송은 백그라운드에서 처리됩니다
예시
window.addEventListener('beforeunload', () => { MSSDK.flush(); });
광고 호출 함수
🚧
준비 중 — 함수 시그니처만 먼저 고정해뒀습니다. 지금 호출하면 광고 없이
{ shown: false }가 바로 반환됩니다. 실제 광고 네트워크 연동이 끝나면
같은 함수 이름으로 동작만 채워질 예정이라, 미리 연동해두셔도 코드를 다시 고칠 필요는 없습니다.
MSSDK.showInterstitialAd()
전면 광고를 요청합니다. (스테이지 전환 등 자연스러운 지점에서 호출)
반환값 (result)
{ shown: false, reason: 'not_implemented' } // 현재는 항상 이 값 — 광고 연동 전
예시
const result = await MSSDK.showInterstitialAd();
if (result.shown) { /* 광고 종료 후 이어서 진행 */ }
MSSDK.showRewardedAd()
보상형 광고를 요청합니다. (재화 지급 등 유저가 자발적으로 시청할 때 호출)
반환값 (result)
{ shown: false, rewarded: false, reason: 'not_implemented' } // 현재는 항상 이 값 — 광고 연동 전
예시
const result = await MSSDK.showRewardedAd();
if (result.rewarded) { /* 보상 지급 */ }
서버 저장 쓰로틀 (30초)
⏱️
set / setMany 호출은 localStorage에 즉시 기록(백업)되지만,
실제 서버 전송은 마지막 전송으로부터 30초 경과 후 한 번만 이루어집니다.
30초 이내의 중간 호출들은 내부 버퍼에 쌓이다가 타이머 만료 시 setMany로 묶여 한 번에 전송됩니다.
// 1초마다 호출해도 서버에는 30초마다 1번만 전송
setInterval(async () => {
await MSSDK.set('score', score); // → 30초 동안은 localStorage에만, 이후 서버 플러시
}, 1000);
// 게임 종료 직전 — 버퍼를 즉시 서버에 강제 플러시
window.addEventListener('beforeunload', () => {
MSSDK.flush(); // 쓰로틀 무시하고 즉시 전송
});
ℹ️
get / getAll은 버퍼에 미전송 값이 있으면 그 값을 우선 반환합니다 — 메모리 일관성 보장.
remove / removeAll은 쓰로틀 없이 즉시 서버에 반영됩니다.
전송 실패 시 payload가 버퍼로 복귀되어 다음 플러시 때 재시도됩니다.
비로그인 유저 처리 (localStorage 폴백)
💡
비로그인 유저의 세이브는 브라우저 localStorage에만 저장됩니다. 이후 로그인하면
로컬 저장 시각과 서버 저장 시각을 키별로 비교해 더 최신인 쪽만 자동으로 반영됩니다
(게임 쪽에서 따로 처리할 필요 없음).