> For the complete documentation index, see [llms.txt](https://docs.overdare.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.overdare.com/korean/development/api-reference/classes/ordereddatastore.md).

# OrderedDataStore

OrderedDataStore : `GlobalDataStore`

## Overview

OrderedDataStore는 정수 값만 저장할 수 있는 영구 데이터 저장소로, 저장된 값을 기준으로 정렬해 조회하는 기능을 제공합니다. 리더보드나 랭킹처럼 점수 순서가 필요한 데이터를 다룰 때 사용합니다.

DataStoreService:GetOrderedDataStore() 메서드를 통해서만 가져올 수 있으며, Instance.new()로 생성할 수 없습니다.

이 객체는 서버 환경에서만 사용할 수 있으며, 클라이언트에서 접근하면 오류가 발생합니다.

GlobalDataStore로부터 상속한 GetAsync, SetAsync, IncrementAsync, UpdateAsync, RemoveAsync를 사용할 수 있으며, DataStore와 비교해 다음과 같은 차이가 있습니다.

**DataStore와의 차이**

* 값은 **정수만** 저장할 수 있습니다. 소수, string, bool, table, NaN, Inf를 저장하면 오류가 발생하며 기존 값은 유지됩니다.
* -(2^53 - 1) \~ 2^53 - 1 범위의 정수만 정확하게 저장하고 불러올 수 있습니다. 저장된 값을 스크립트에서 정확하게 표현할 수 없으면 불러오기가 실패합니다.
* 버전 기록과 메타데이터를 지원하지 않습니다. 값을 덮어쓰거나 삭제하면 이전 값을 복구할 수 없습니다.
* GetAsync의 두 번째 반환값(DataStoreKeyInfo)은 항상 nil입니다. 키가 없으면 nil, nil을 반환합니다.
* SetAsync와 IncrementAsync에 UserIds나 옵션 인자를 전달하면 오류가 발생합니다. SetAsync는 nil을 반환합니다.
* SetAsync에 nil 값을 전달하면 오류가 발생합니다. 키를 삭제하려면 RemoveAsync를 사용해야 합니다.
* UpdateAsync의 콜백은 현재 값 하나만 인자로 받고, 새 정수 값을 그대로 반환합니다. 저장되면 갱신된 값과 nil을, 콜백이 nil을 반환해 취소되면 nil, nil을 반환합니다.
* GetAsync에 DataStoreGetOptions를 전달해도 캐시를 사용하지 않습니다. 모든 불러오기는 호출할 때마다 새로 요청됩니다.
* 이름이 같은 DataStore와는 서로 다른 저장 공간을 사용합니다.

**주의사항**

* UpdateAsync의 콜백은 여러 서버가 같은 키를 동시에 갱신하면 최신 값으로 다시 실행되며, 실행 횟수는 보장되지 않습니다. 콜백 안에서 외부 동작을 수행하지 않아야 합니다.
* UpdateAsync의 콜백 안에서 대기 함수를 호출하면 콜백이 중단되어 값이 저장되지 않습니다. 이때 호출은 오류 없이 nil, nil을 반환하고 출력 창에 오류 로그만 남으므로, pcall로는 실패를 확인할 수 없습니다.
* 저장 호출이 실패해도 값이 저장되지 않았다는 보장은 없습니다. 실패한 IncrementAsync를 그대로 재시도하면 값이 두 번 더해질 수 있습니다.
* 다른 서버에서 저장한 직후에는 잠시 동안 이전 값이 조회될 수 있습니다.
* 서버가 종료되는 중에는 새 요청이 즉시 실패하며, 대기 중이던 요청은 같은 키마다 마지막 요청 하나만 처리됩니다.

## Properties

## Methods

### GetSortedAsync

저장된 항목을 값 기준으로 정렬해 페이지 단위로 순회할 수 있는 DataStorePages 객체를 반환합니다.

정렬 방향은 ascending으로, 한 페이지의 최대 항목 수는 pagesize로 지정하며, minValue와 maxValue로 조회할 값의 범위를 제한할 수 있습니다.

이 메서드는 결과를 받을 때까지 호출한 스크립트를 일시 중단(yield)합니다.

**주의사항**

* 같은 값을 가진 항목끼리의 순서는 보장되지 않습니다.
* 반환된 결과는 조회 시점의 고정된 사본이 아닙니다. 다음 페이지를 불러오기 전에 항목이 추가되거나 삭제되면 그 변경이 반영되어, 같은 항목이 두 번 나오거나 누락될 수 있습니다.
* 캐시를 사용하지 않으므로 호출할 때마다 새로 요청됩니다.
* 이 메서드와 AdvanceToNextPageAsync는 요청 한도가 가장 좁습니다. 한도를 넘으면 대기하지 않고 즉시 실패하므로, 조회 결과를 보관해 나눠 사용하는 것이 좋습니다.

#### Parameters

| `boolean` ascending | <p>정렬 방향입니다.</p><ul><li>true이면 낮은 값부터 오름차순으로 정렬합니다.</li><li>false이면 높은 값부터 내림차순으로 정렬합니다.</li><li>생략하거나 nil을 전달하면 오류가 발생합니다.</li></ul>     |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `number` pagesize   | <p>한 페이지에 담을 최대 항목 수입니다.</p><ul><li>1 \~ 100 사이의 값을 지정해야 하며, 범위를 벗어나면 오류가 발생합니다.</li><li>기본값이 없으므로 생략하거나 nil을 전달하면 오류가 발생합니다.</li></ul>   |
| `number` minValue   | <p>(선택 사항) 조회할 값의 최솟값입니다.</p><ul><li>이 값보다 작은 항목은 결과에서 제외되며, 경계값은 포함됩니다.</li><li>정수만 지정할 수 있으며, 문자열 등 정수가 아닌 값을 전달하면 오류가 발생합니다.</li></ul> |
| `number` maxValue   | <p>(선택 사항) 조회할 값의 최댓값입니다.</p><ul><li>이 값보다 큰 항목은 결과에서 제외되며, 경계값은 포함됩니다.</li><li>정수만 지정할 수 있으며, minValue보다 작으면 오류가 발생합니다.</li></ul>        |

#### Return

| `DataStorePages` | <p>정렬된 항목을 페이지 단위로 담은 DataStorePages 객체입니다.</p><ul><li>GetCurrentPage()는 key(string)와 value(number) 필드를 가진 테이블의 배열을 반환합니다.</li><li>조건에 맞는 항목이 없으면 GetCurrentPage()는 빈 테이블을 반환하고 IsFinished는 true입니다.</li></ul> |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Code Samples

```lua
local DataStoreService = game:GetService("DataStoreService")
local LeaderboardStore = DataStoreService:GetOrderedDataStore("KillLeaderboard")

local success, errorMessageOrPages = pcall(function()
    return LeaderboardStore:GetSortedAsync(false, 10)
end)

if not success then
    print("errorMessage : ", errorMessageOrPages)
else
    local pages = errorMessageOrPages

    while true do
        for _, entry in ipairs(pages:GetCurrentPage()) do
            print("UserId : ", entry.key, " / Score : ", entry.value)
        end

        if pages.IsFinished then
            break
        end

        local advanceSuccess, errorMessage = pcall(function()
            pages:AdvanceToNextPageAsync()
        end)

        if not advanceSuccess then
            print("errorMessage : ", errorMessage)
            break
        end
    end
end
```

```lua
local DataStoreService = game:GetService("DataStoreService")
local LeaderboardStore = DataStoreService:GetOrderedDataStore("KillLeaderboard")

local success, errorMessageOrPages = pcall(function()
    return LeaderboardStore:GetSortedAsync(true, 50, 1000, 5000)
end)
```

## Events

## See also

{% content-ref url="/pages/LBBPet4iHQBSYAPFmfBF" %}
[커스텀 리더보드](/korean/manual/script-manual/advanced-gameplay-systems/ordereddatastore.md)
{% endcontent-ref %}
