# PlayDrop 게임의 클라우드 저장

sdk.me.appData와 sdk.me.updateAppData로 게스트와 로그인한 플레이어의 진행 상황을 저장하고 불러오세요. 쓰기, 미리 보기, 오프라인 플레이 규칙도 담았습니다.

Source: https://www.playdrop.ai/ko/create/learn/cloud-saves

클라우드 저장은 내 게임의 플레이어별 진행 상황을 PlayDrop에 보관하므로, 플레이어는 웹사이트에서든 앱에서든 이어서 플레이할 수 있습니다. 플레이어와 게임마다 JSON 객체 하나가 저장되며, 서버나 멀티플레이어 방은 필요하지 않습니다.

## 읽기와 쓰기

`init()` 후 `sdk.me.appData`는 저장된 스냅샷 `{ data, seq, ts_event, ts_arrival }`이며, 처음 저장하기 전에는 `null`입니다. 내 객체는 `data`에서 읽으세요. 쓸 때는 `updateAppData`로 객체 전체를 쓰세요. 이 함수는 저장된 스냅샷을 반환하고 `sdk.me.appData`를 업데이트합니다.

```js
const sdk = await playdrop.init();
let progress = { level: 1, coins: 0, ...(sdk.me.appData?.data ?? {}) };
let queue = Promise.resolve();

// Resolves with the saved snapshot; rejects when the save failed.
function save(changes) {
  progress = { ...progress, ...changes };
  const snapshot = { ...progress };
  const attempt = queue.then(() => sdk.me.updateAppData(snapshot));
  queue = attempt.catch(() => {}); // a failed save must not block the next one
  return attempt;
}

try {
  await save({ level: 2 });
  showSaved();
} catch (error) {
  showSaveError(); // progress stays in memory; the next save sends it again
}
```

- 쓸 때마다 저장된 객체 전체가 교체됩니다. 계속 필요한 필드는 모두 유지하세요.
- 위 예시처럼 쓰기를 순서대로 실행해 이전 저장이 최신 저장보다 늦게 반영되지 않게 하고, 실패한 뒤에도 대기열이 계속 이어지게 하세요.
- promise가 완료된 뒤에만 "저장됨"을 표시하세요. 메모리에서 `appData.data`만 바꾸면 아무것도 저장되지 않습니다.
- `appData`에는 `get`, `set`, `save` 메서드가 없습니다.

## 언제 저장할까요

매 프레임이 아니라 체크포인트, 레벨 종료, 구매 시점에 저장하세요. 미리 보기나 캡처 중에는 절대 저장하지 마세요. `sdk.host.phase`가 `play`일 때만 쓰세요. 저장 데이터는 작게 유지하고, `saveVersion: 2`처럼 직접 정한 필드로 버전을 붙여 나중 버전의 게임이 데이터를 이전할 수 있게 하세요.

## 게스트와 로그인한 플레이어

저장하기 전에 `sdk.me.isLoggedIn`을 확인할 필요는 없습니다. PlayDrop 게스트도 저장 데이터를 유지합니다. 세션이 전혀 없는 플레이어는 그 방문 동안만 메모리에 저장 데이터를 보관하므로, 쓰기가 완료되었다고 해서 클라우드에 저장되었다는 뜻은 아닙니다. `isLoggedIn`은 구매나 호스팅 멀티플레이어처럼 실제 계정이 필요한 기능에만 사용하세요.

## 오프라인

브라우저에서는 저장에 네트워크 연결이 필요하며 오프라인 대기열이 없습니다. 실패해도 플레이를 이어가고 다음 체크포인트에서 다시 시도하세요. 오프라인 플레이를 지원하는 PlayDrop 앱처럼 기기 데이터 지원을 알리는 호스트는 저장 데이터를 기기에 보관하고 온라인이 되면 동기화합니다.

## 저장으로 할 수 없는 것

저장 데이터는 한 플레이어와 한 게임에만 속하는 비공개 데이터입니다. 자체 API가 있고 PlayDrop에 표시되는 [순위표](https://www.playdrop.ai/ko/create/learn/leaderboards), [업적](https://www.playdrop.ai/ko/create/learn/achievements)과는 별개입니다. 경기나 월드처럼 플레이어끼리 공유하는 상태는 [게임 서버](https://www.playdrop.ai/ko/create/learn/game-servers)의 게임 MongoDB 컬렉션에 두세요.

## 테스트하기

저장 데이터는 업로드된 게임에 속합니다. 비공개 버전을 한 번 이상 업로드한 뒤, 업로드 결과의 `url`이나 [AI 앱에서 게시하기](https://www.playdrop.ai/ko/create/learn/mcp-publishing)에서 설명하는 로컬 Dev 프레임에서 테스트하세요.

## 관련 가이드

- [순위표](https://www.playdrop.ai/ko/create/learn/leaderboards): catalogue.json에 순위표를 선언하고, sdk.leaderboards로 점수를 제출하고, 상위 순위와 플레이어 주변 순위를 보여 주세요. 점수 유형, 제한, 업데이트 규칙도 담았습니다.
- [업적](https://www.playdrop.ai/ko/create/learn/achievements): catalogue.json에 아이콘이 있는 일반 업적과 누적 업적을 선언하고, sdk.achievements로 잠금 해제하고 진행 상황을 기록하세요.
- [실시간 게임 서버](https://www.playdrop.ai/ko/create/learn/game-servers): MongoDB 데이터베이스가 있는 호스팅 Colyseus 0.17 서버를 게임에 쓰고, SDK로 브라우저에서 연결하고, 플레이어 2명으로 테스트하고, 제한 사항을 알아보세요.
