게임을 만들다 보면 돈, 레벨, 인벤토리처럼 플레이어가 나갔다가 다시 들어와도 남아 있어야 하는 데이터가 생깁니다. 이때 사용하는 대표 기능이 DataStoreService입니다. Roblox 공식 문서도 DataStore를 세션 사이에 유지돼야 하는 진행도와 인벤토리 같은 데이터를 저장하는 용도로 설명합니다. 중요한 점은 ‘값을 저장하는 코드 한 줄’보다 서버에서 안전하게 읽고, 실패를 처리하고, 덮어쓰기를 피하는 구조입니다.
1. DataStore는 서버 Script에서 다룹니다
지속 데이터는 클라이언트 LocalScript가 직접 저장하도록 만들면 안 됩니다. 공식 문서에서도 DataStore 접근은 서버 측 Script에서 하도록 안내합니다. 클라이언트는 “구매 버튼을 눌렀다” 같은 요청을 서버에 보내고, 실제 돈 차감과 저장은 서버가 검증한 뒤 처리하는 구조가 기본입니다.
2. 플레이어마다 DataStore를 새로 만들지 않습니다
PlayerData 같은 고정된 저장소 하나를 만들고, UserId를 포함한 키로 각 플레이어 데이터를 구분하는 방식이 관리하기 쉽습니다. Roblox의 모범 사례도 많은 저장소를 만드는 것보다 적은 수의 저장소와 예측 가능한 키 구조를 권장합니다.
3. 저장 데이터는 한 덩어리의 프로필처럼 생각합니다
코인, 레벨, 장비를 각각 무작정 여러 키로 나누면 저장 요청이 많아지고 서로 다른 시점의 값이 섞일 수 있습니다. 관련된 데이터가 크지 않다면 하나의 테이블로 묶어 관리하는 편이 이해하기 쉽습니다. 다만 데이터 크기와 갱신 빈도가 커지면 목적에 따라 분리할 수 있습니다.
4. GetAsync와 SetAsync만 연결하고 끝내지 않습니다
네트워크나 서비스 상태 때문에 요청은 실패할 수 있습니다. pcall 등으로 오류를 처리하고, 실패했는데 기본값으로 덮어써버리는 상황을 막아야 합니다. 특히 로드 실패를 ‘신규 유저’로 착각해 빈 데이터를 저장하면 기존 진행도가 사라지는 문제가 생길 수 있습니다.
5. 동시에 값이 바뀌는 데이터는 업데이트 방식을 신중하게 고릅니다
같은 키가 여러 서버나 흐름에서 수정될 수 있다면 단순히 마지막 값을 덮어쓰는 구조는 충돌에 약할 수 있습니다. 데이터의 성격에 맞는 갱신 방법을 선택하고, 구매나 보상처럼 중요한 변화는 서버에서 한 번만 적용되도록 설계하세요.
6. Studio 테스트는 실제 운영 데이터와 분리합니다
Roblox 문서는 Studio에서 API 서비스 접근을 켜면 라이브 게임과 같은 데이터 저장소에 접근할 수 있으므로 테스트용 별도 버전을 쓰는 것을 권장합니다. 개발 중 실수로 운영 유저 데이터를 덮어쓰는 사고를 피하려면 테스트 환경을 분리하는 것이 좋습니다.
7. 저장 성공보다 복구 가능한 구조가 중요합니다
플레이어가 나갈 때만 한 번 저장하는 구조는 갑작스러운 종료에 약합니다. 중요한 데이터라면 변경 시점과 주기적 저장, 종료 시 저장을 조합하고, 저장 실패 로그를 남겨 원인을 추적할 수 있게 만드는 편이 좋습니다.
초보가 기억할 기준
DataStore는 ‘클라이언트가 요청하고 서버가 검증한 값을 서버에서 저장한다’가 출발점입니다. 로드 실패와 저장 실패를 정상 상황처럼 처리하고, 테스트 데이터와 운영 데이터를 분리하면 초반에 가장 흔한 데이터 초기화 사고를 크게 줄일 수 있습니다.
로그를 남겨야 저장 사고를 찾을 수 있습니다
저장이 실패했을 때 단순히 “저장 실패”만 출력하지 말고 어떤 플레이어의 어떤 단계에서 실패했는지 구분할 수 있는 로그를 남기세요. 다만 실제 개인정보나 민감한 값을 그대로 로그에 기록할 필요는 없습니다. 로드 시작·로드 성공·저장 요청·저장 성공 정도의 상태만 명확해도 운영 중 특정 시점의 데이터 문제를 추적하기 훨씬 쉬워집니다.
