DataStoreService는 플레이어의 인벤토리 아이템이나 스킬 포인트와 같이 세션 간에 지속되어야 하는 데이터를 저장할 수 있게 해줍니다. 데이터 저장소는 게임마다 일관되므로, 게임의 어떤 장소에서도 동일한 데이터에 접근하고 변경할 수 있으며, 다른 서버의 장소에서도 가능합니다.
데이터 저장소에 세부적인 권한 제어를 추가하고 Studio 또는 Roblox 서버 외부에서 접근하려면 데이터 저장소를 위한 Open Cloud API를 사용할 수 있습니다.
Creator Hub를 통해 게임의 모든 데이터 저장소를 보고 모니터링하려면 데이터 저장소 관리자를 사용하세요.
임시 데이터로 자주 업데이트하거나 접근해야 하는 데이터는 메모리 저장소를 사용하세요.
Studio 접근 활성화
기본적으로 Studio에서 테스트된 게임은 데이터 저장소에 접근할 수 없으므로, 먼저 이를 활성화해야 합니다. Studio에서 데이터 저장소에 접근하는 것은 클라이언트 애플리케이션과 동일한 데이터 저장소에 접근하기 때문에 라이브 게임에 위험할 수 있습니다. 프로덕션 데이터를 덮어쓰지 않도록 라이브 게임에 대해 이 설정을 활성화하지 마세요. 대신, 게임의 별도 테스트 버전에 대해 활성화하세요.
게시된 게임에서 Studio 접근을 활성화하려면:
- Studio의 파일 ⟩ 경험 설정 창을 엽니다.
- 보안으로 이동합니다.
- API 서비스에 대한 Studio 접근 활성화 토글을 활성화합니다.
- 저장을 클릭합니다.
데이터 저장소 접근
게임 내에서 데이터 저장소에 접근하려면:
- 서버 측 Script에 DataStoreService를 추가합니다.
- GetDataStore() 함수를 사용하고 사용하려는 데이터 저장소의 이름을 지정합니다. 데이터 저장소가 존재하지 않으면, Studio는 게임 데이터를 처음 저장할 때 하나를 생성합니다.
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")데이터 생성
데이터 저장소는 본질적으로 Luau 테이블과 유사한 사전입니다. 각 값은 고유한 키로 인덱싱되며, 예를 들어 사용자의 고유한 Player.UserId 또는 게임 프로모션을 위한 명명된 문자열이 될 수 있습니다.
| 사용자 데이터 키 | 값 |
|---|---|
| 31250608 | 50 |
| 351675979 | 20 |
| 505306092 | 78000 |
| 프로모션 데이터 키 | 값 |
| ActiveSpecialEvent | SummerParty2 |
| ActivePromoCode | BONUS123 |
| CanAccessPartyPlace | true |
새 항목을 생성하려면 SetAsync()를 호출하고 키 이름과 값을 전달합니다.
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, errorMessage = pcall(function()
gameStore:SetAsync("User_1234", 50)
end)
if not success then
print(errorMessage)
end데이터 업데이트
데이터 저장소에 저장된 값을 변경하려면 UpdateAsync()를 호출하고 항목의 키 이름과 항목을 업데이트하는 방법을 정의하는 콜백 함수를 전달합니다. 이 콜백은 현재 값을 받아들이고 정의한 논리에 따라 새로운 값을 반환합니다. 콜백이 nil을 반환하면 쓰기 작업이 취소되고 값이 업데이트되지 않습니다.
local DataStoreService = game:GetService("DataStoreService")
local nicknameStore = DataStoreService:GetDataStore("Nicknames")
local function makeNameUpper(currentName)
local nameUpper = string.upper(currentName)
return nameUpper
end
local success, updatedName = pcall(function()
return nicknameStore:UpdateAsync("User_1234", makeNameUpper)
end)
if success then
print("대문자 이름:", updatedName)
end설정 vs 업데이트
특정 키를 빠르게 업데이트하려면 설정을 사용하세요. SetAsync() 함수는:
- 두 서버가 동시에 동일한 키를 설정하려고 할 경우 데이터 불일치를 초래할 수 있습니다.
- 쓰기 한도에만 카운트됩니다.
다중 서버 시도를 처리하려면 업데이트를 사용하세요. UpdateAsync() 함수는:
- 변경하기 전에 마지막으로 업데이트된 서버에서 현재 키 값을 읽습니다.
- 쓰기 전에 읽기 때문에 느립니다.
- 읽기 및 쓰기 한도 모두에 카운트됩니다.
데이터 읽기
데이터 저장소 항목의 값을 읽으려면 GetAsync()를 호출하고 항목의 키 이름을 전달합니다.
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, currentGame = pcall(function()
return gameStore:GetAsync("User_1234")
end)
if success then
print(currentGame)
end데이터 증가
데이터 저장소에서 정수를 증가시키려면 IncrementAsync()를 호출하고 항목의 키 이름과 값을 변경할 양을 전달합니다. IncrementAsync()는 UpdateAsync()를 호출하고 정수를 수동으로 증가시키는 것을 피할 수 있게 해주는 편리한 함수입니다.
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, newGame = pcall(function()
return gameStore:IncrementAsync("Player_1234", 1)
end)
if success then
print(newGame)
end데이터 제거
항목을 제거하고 키와 연결된 값을 반환하려면 RemoveAsync()를 호출합니다.
local DataStoreService = game:GetService("DataStoreService")
local nicknameStore = DataStoreService:GetDataStore("Nicknames")
local success, removedValue = pcall(function()
return nicknameStore:RemoveAsync("User_1234")
end)
if success then
print(removedValue)
end메타데이터
키와 관련된 두 가지 유형의 메타데이터가 있습니다:
- 서비스 정의: 가장 최근 업데이트 시간 및 생성 시간과 같은 기본 읽기 전용 메타데이터입니다. 모든 객체는 서비스 정의 메타데이터를 가집니다.
메타데이터를 관리하려면 SetAsync(), UpdateAsync(), GetAsync(), IncrementAsync(), 및 RemoveAsync() 함수에서 확장합니다.
SetAsync()는 선택적 세 번째 및 네 번째 인수를 허용합니다:
UserIds의 테이블입니다. 이는 콘텐츠 저작권 및 지적 재산 추적 및 제거에 도움이 될 수 있습니다.
사용자 정의 메타데이터를 정의할 수 있는 DataStoreSetOptions 객체입니다. SetMetadata() 함수를 사용하여 정의합니다.
local DataStoreService = game:GetService("DataStoreService")local gameStore = DataStoreService:GetDataStore("PlayerGame")local setOptions = Instance.new("DataStoreSetOptions")setOptions:SetMetadata({["GameElement"] = "Fire"})local success, errorMessage = pcall(function()gameStore:SetAsync("User_1234", 50, {1234}, setOptions)end)if not success thenprint(errorMessage)end
GetAsync(), IncrementAsync(), 및 RemoveAsync()는 DataStoreKeyInfo 객체에서 두 번째 값을 반환합니다. 이 두 번째 값은 서비스 정의 속성과 사용자 정의 메타데이터를 가져오는 함수가 포함되어 있습니다.
- Version 속성은 키의 버전을 가져옵니다.
- CreatedTime 속성은 키가 생성된 시간을 epoch 이후 밀리초로 포맷하여 가져옵니다.
- UpdatedTime 속성은 키가 마지막으로 업데이트된 시간을 epoch 이후 밀리초로 포맷하여 가져옵니다.
local DataStoreService = game:GetService("DataStoreService")local gameStore = DataStoreService:GetDataStore("PlayerGame")local success, currentGame, keyInfo = pcall(function()return gameStore:GetAsync("User_1234")end)if success thenprint(currentGame)print(keyInfo.Version)print(keyInfo.CreatedTime)print(keyInfo.UpdatedTime)print(keyInfo:GetUserIds())print(keyInfo:GetMetadata())endUpdateAsync()의 콜백 함수는 현재 키 상태를 설명하는 DataStoreKeyInfo 객체에서 추가 매개변수를 받습니다. 수정된 값, UserIds와 연결된 키, 및 키의 메타데이터를 반환합니다.
local DataStoreService = game:GetService("DataStoreService")local nicknameStore = DataStoreService:GetDataStore("Nicknames")local function makeNameUpper(currentName, keyInfo)local nameUpper = string.upper(currentName)local userIDs = keyInfo:GetUserIds()local metadata = keyInfo:GetMetadata()return nameUpper, userIDs, metadataendlocal success, updatedName, keyInfo = pcall(function()return nicknameStore:UpdateAsync("User_1234", makeNameUpper)end)if success thenprint(updatedName)print(keyInfo.Version)print(keyInfo.CreatedTime)print(keyInfo.UpdatedTime)print(keyInfo:GetUserIds())print(keyInfo:GetMetadata())end
메타데이터 정의 시 한도에 대한 내용은 메타데이터 한도를 참조하세요.
정렬된 데이터 저장소
기본적으로 데이터 저장소는 내용을 정렬하지 않습니다. 지속적인 리더보드 통계와 같이 정렬된 방식으로 데이터를 가져와야 하는 경우 GetOrderedDataStore()를 호출하세요.
local DataStoreService = game:GetService("DataStoreService")
local characterAgeStore = DataStoreService:GetOrderedDataStore("CharacterAges")정렬된 데이터 저장소는 기본 데이터 저장소와 동일한 기본 기능을 지원하며, 고유한 GetSortedAsync() 함수도 지원합니다. 이 함수는 특정 정렬 순서, 페이지 크기 및 최소/최대 값을 기반으로 여러 정렬된 키를 검색합니다.
다음 예제는 캐릭터 데이터를 세 개의 항목으로 구성된 페이지로 정렬하고, 각 페이지를 반복하여 각 캐릭터의 이름과 나이를 출력합니다.
local DataStoreService = game:GetService("DataStoreService")
local characterAgeStore = DataStoreService:GetOrderedDataStore("CharacterAges")
-- 정렬된 데이터 저장소를 채웁니다.
local characters = {
Mars = 19,
Janus = 20,
Diana = 18,
Venus = 25,
Neptune = 62
}
for char, age in characters do
local success, errorMessage = pcall(function()
characterAgeStore:SetAsync(char, age)
end)
if not success then
print(errorMessage)
end
end
-- 내림차순으로 세 개의 항목으로 페이지를 정렬합니다.
local success, pages = pcall(function()
return characterAgeStore:GetSortedAsync(false, 3)
end)
if success then
while true do
-- 현재(첫 번째) 페이지를 가져옵니다.
local entries = pages:GetCurrentPage()
-- 페이지의 모든 키-값 쌍을 반복합니다.
for _, entry in entries do
print(entry.key .. " : " .. tostring(entry.value))
end
-- 마지막 페이지에 도달했는지 확인합니다.
if pages.IsFinished then
break
else
print("----------")
-- 다음 페이지로 진행합니다.
pages:AdvanceToNextPageAsync()
end
end
end여러 항목 읽기
단일 요청으로 여러 정렬된 데이터 저장소 항목을 읽으려면 BatchGetAsync()를 호출하고 키 배열을 전달합니다. 이는 GetAsync()로 항목을 하나씩 읽는 배치 대응 함수입니다.
BatchGetAsync()는 요청한 각 키를 value 필드가 있는 테이블에 매핑하는 사전을 반환합니다. 존재하지 않는 키는 사전에서 생략되므로, 값을 읽기 전에 키가 존재하는지 확인하세요.
요청하는 각 키는 하나의 읽기 요청으로 카운트되므로, N개의 키에 대한 단일 호출은 정렬된 데이터 저장소 읽기 한도에 대해 N개의 요청으로 카운트됩니다.
다음 예제는 단일 요청으로 세 개의 플레이어 점수를 읽고, 키를 반복하여 존재하는 각 점수를 출력합니다.
local DataStoreService = game:GetService("DataStoreService")
local playerScores = DataStoreService:GetOrderedDataStore("PlayerScores")
local keys = {"Player_123", "Player_456", "Player_789"}
local success, results = pcall(function()
return playerScores:BatchGetAsync(keys)
end)
if success then
for _, key in keys do
local entry = results[key]
if entry then
print(key .. " : " .. tostring(entry.value))
else
print(key .. "는 저장된 항목이 없습니다.")
end
end
end