> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperx.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 공개 스토리지(CDN)

> Console에 올린 파일을 Unity 클라이언트에서 확인하고 다운로드합니다.

공개 스토리지는 패치 파일, 이미지, 밸런스 JSON, 공지 리소스처럼 모든 플레이어가 내려받아도 되는 파일을 배포하는 기능입니다. 파일 업로드와 교체는 Console에서 하고, 클라이언트는 SDK로 파일 정보와 다운로드 URL을 조회합니다.

## 사용 흐름

1. Console의 `Public Storage`에서 파일을 업로드합니다.
2. 필요하면 `tag`로 버전을 구분합니다.
3. Unity에서 파일 해시를 확인합니다.
4. 로컬에 없는 파일이거나 해시가 바뀐 파일만 다운로드합니다.

## 태그로 버전 관리

같은 `filename`에 여러 버전을 둘 수 있습니다.

| 예시                            | 의미        |
| ----------------------------- | --------- |
| `Items.json`                  | 기본 버전     |
| `Items.json` + tag `season-1` | 특정 시즌용 버전 |
| `Items.json` + tag `season-2` | 다음 시즌용 버전 |

`tag`를 지정하면 정확히 일치하는 버전을 조회합니다. `tag`를 생략하면 기본 파일을 먼저 찾고, 기본 파일이 없으면 같은 파일명 중 가장 최근 버전을 사용합니다.

## 파일 정보 확인

```cs theme={null}
var meta = await HyperX.Core.PublicStorage.GetMeta("Items.json");
Debug.Log($"{meta.Hash} / {meta.Size} bytes");
```

특정 태그를 확인하려면 `tag`를 전달합니다.

```cs theme={null}
var meta = await HyperX.Core.PublicStorage.GetMeta("Items.json", tag: "season-2");
```

`ObjectMeta`에는 파일 해시, MIME 타입, 크기, 업데이트 시각이 포함됩니다.

## 해시만 확인

파일이 바뀌었는지만 확인할 때는 `GetHash`가 가장 간단합니다.

```cs theme={null}
string hash = await HyperX.Core.PublicStorage.GetHash("Items.json");
```

## 파일 다운로드

메모리로 받기:

```cs theme={null}
var progress = HyperX.Core.PublicStorage.Get("Items.json");
byte[] bytes = await progress.File;
```

Unity 저장소에 받기:

```cs theme={null}
var progress = HyperX.Core.PublicStorage.Get(
    "Items.json",
    "content/Items.json",
    tag: "season-2"
);

await progress.File;
```

Unity에서는 저장 경로가 `Application.persistentDataPath` 아래로 해석됩니다.

## 해시 기반 캐시 예시

```cs theme={null}
using System.IO;
using UnityEngine;

public class HyperXStorageCache : MonoBehaviour
{
    async void Start()
    {
        string fileName = "Items.json";
        string savePath = "content/Items.json";

        string remoteHash = await HyperX.Core.PublicStorage.GetHash(fileName);
        string localHash = PlayerPrefs.GetString($"HX_HASH:{fileName}");

        if (remoteHash != localHash)
        {
            var progress = HyperX.Core.PublicStorage.Get(fileName, savePath);
            await progress.File;
            PlayerPrefs.SetString($"HX_HASH:{fileName}", remoteHash);
        }

        string fullPath = Path.Combine(Application.persistentDataPath, savePath);
        string json = File.ReadAllText(fullPath);
        Debug.Log(json);
    }
}
```
