[task] | extract_knowledge [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage 에러 코드 처리 ## 개념 설명 `DataStorage`를 통해 데이터를 불러오는 과정에서 네트워크 지연(`TimedOut`)이나 호출 횟수 한도 초과(`ResourceExhausted`) 등으로 인해 실패할 수 있습니다. 요청 함수의 반환 에러 코드를 확인하여 데이터를 정상적으로 불러오지 못한 상황을 감지하고, 이에 따른 예외 처리(예: 유저 추방)를 구현하는 것이 권장됩니다. 특히 필수 데이터 로드 실패 시 유저를 추방하는 것은 이후 플레이 불가 또는 복잡한 상태 불일치를 방지하기 위한 방법입니다. [original] | # 학습 과정 소개 DataStorage는 간단하게 데이터를 저장하고 불러올 수 있습니다. 그러나 DataStorage를 사용하며 다양한 문제가 발생할 수 있습니다. 이번 가이드에서는 권장하는 DataStorage 사용 방법 중 일부를 소개합니다. 크리에이터가 만드는 월드 특성에 따라 알맞은 해결 방법이 필요합니다. # DataStorage 에러 코드 처리 다양한 이유로 인해 데이터를 DataStorage로부터 불러오지 못하는 상황이 발생할 수 있습니다. 예를 들어 요청에 시간이 너무 오래 걸려 실패하거나(TimedOut), [chunk_id] | Guides:1073:0
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: DataStorage에서 데이터 불러오기 요청이 실패할 수 있는 원인은 무엇인가요? 답변: 크리에이터가 정상적으로 요청했음에도 원인이 불명확한 일시 장애가 발생했을 때 데이터 불러오기를 실패할 수 있습니다. 질문: 문서의 예시 코드에서 데이터 불러오기에 실패했을 때 재시도 전 대기 시간은 얼마인가요? 답변: 예시 코드의 주석에는 '2초 뒤에 재시도'라고 설명되어 있으나, 실제 코드 내 `wait(1)` 함수 호출로 인해 1초 동안 기다린 후 재시도합니다. 질문: `ResourceExhausted: 1000005` 에러 코 [original] | 크리에이터는 정상적으로 요청했지만 원인이 불명확한 일시 장애가 발생해 데이터 불러오기를 실패할 수 있습니다. 이런 상황을 대비해 데이터 불러오기 요청을 여러 번 시도할 수 있습니다. 아래 예시 코드는 데이터 불러오기에 실패하면 2초 뒤에 재시도합니다. 그 이후 일정 횟수 이상 실패하면 유저를 월드에서 추방합니다. 더불어 과도한 요청으로 인한 에러 코드 ResourceExhausted: 1000005가 발생하면, 재시도하지 않고 유저를 추방합니다. ```lua Property: [Sync] integer meso = 0 [Syn [chunk_id] | Guides:1073:1
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 월드에 필수적이지 않은 데이터 로드 실패 시, 저장 자체를 차단하는 패턴입니다. ### 핵심 동작 규칙 1. **상태 관리**: `[Sync] boolean initialized` 프로퍼티로 로드 성공 여부를 추적합니다. 2. **로드 로직**: `_DataStorageService:GetUserDataStorage` 및 `GetAndWait` 호출 시 `nil` 또는 에러 코드(0 아님)가 반환되면 `false`를 반환하고 초기화를 중단합니다. 3. **저장 차단**: `Save` 메서드에서 `self.initialized == [original] | 월드에 필수적인 데이터가 아닌 경우 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식도 고려할 수 있습니다. 아래의 예제는 Component에서 요청 성공 여부를 Property에 저장하고, Logic을 이용해 데이터를 저장하지 않도록 구현합니다. ```lua Property: [Sync] boolean initialized = false -- 이 프로퍼티를 사용해 저장 막기. [Sync] integer meso = 0 Method: [server only] void OnBeginPlay() { if [chunk_id] | Guides:1073:2
[task] | extract_knowledge [title] | 메이플스토리 월드 루아 문법 확장 [category] | Guides [rephrased] | # 비트 연산자 (Bitwise Operators) ## 1. 개념 설명 mLua(Lua 5.3 기반)에서는 정수 값을 이진수(2진수) 단위로 조작하기 위해 비트 연산자를 제공합니다. 주로 상태 플래그(Flag) 관리, 권한 검사, 또는 성능 최적화가 필요한 데이터 압축 시 사용됩니다. * **비트 AND (`&`)**: 두 값의 동일한 위치 비트를 비교합니다. 두 값 모두 `1`인 경우에만 결과 비트가 `1`이 되고, 그 외에는 `0`이 됩니다. * **비트 OR (`|`)**: 두 값의 동일한 위치 비트를 비교합니다 [original] | 비트 AND 연산자(Bitwise AND operator) `&`는 두 개의 값을 비교하여 같은 위치의 비트가 모두 1이면 결과로 1을 반환하고, 그렇지 않으면 0을 반환합니다. 반면, 비트 OR 연산자(Bitwise OR operator) `|`는 두 개의 값을 비교하여 같은 위치의 비트 중 하나라도 1이면 결과로 1을 반환하고, 그렇지 않으면 0을 반환합니다. 예를 들어 봅시다. ```lua local a = 10 -- 이진수 1010 local b = 7 -- 이진수 0111 local result = a & b -- 비트 [chunk_id] | Guides:1071:2
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 제시된 문서 `[Guides] Effective MSW 효과적으로 DataStorage 사용하기` 에서 추출한 핵심 사실은 다음과 같습니다. 1. 월드에 필수적인 데이터가 아닐 경우, 데이터를 불러오는 데 실패했을 때 데이터를 저장하지 않는 방식을 고려할 수 있습니다. 2. `Property` 블록에는 `[Sync]` 속성을 가진 `boolean initialized` 변수(초기값 `false`)와 `[Sync]` 속성을 가진 `integer meso` 변수(초기값 `0`)를 선언하여 요청 성공 여부를 추적하고 데이터를 관리합 [original] | 월드에 필수적인 데이터가 아닌 경우 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식도 고려할 수 있습니다. 아래의 예제는 Component에서 요청 성공 여부를 Property에 저장하고, Logic을 이용해 데이터를 저장하지 않도록 구현합니다. ```lua Property: [Sync] boolean initialized = false -- 이 프로퍼티를 사용해 저장 막기. [Sync] integer meso = 0 Method: [server only] void OnBeginPlay() { if [chunk_id] | Guides:1073:2
[task] | extract_knowledge [title] | 메이플스토리 월드 루아 문법 확장 [category] | Guides [rephrased] | # 메이플스토리 월드 mLua 확장 문법: 루프 제어 및 복합 할당 연산자 메이플스토리 월드의 스크립팅 언어 mLua는 표준 Lua 5.3 문법을 기반으로 하되, 다른 프로그래밍 언어에서 자주 사용되는 편의 문법을 확장하여 지원합니다. 본 절에서는 `continue` 키워드와 복합 할당 연산자(Compound assignment operators)에 초점을 맞춰 개념, 사용법, 예제, 주의사항을 설명합니다. ## 1. Continue 키워드 ### 개념 `continue`는 현재 루프(iteration)의 나머지 명령어를 건너 [original] | # 학습 과정 소개 메이플스토리 월드에서는 루아에서 기본적으로 지원하지 않지만 다른 프로그래밍 언어에서 유용하게 사용되는 문법을 확장하여 지원합니다. 본 과정에서는 메이플스토리 월드에서 지원하는 루아 확장 문법 및 사용 예시를 소개합니다. # Continue **continue**는 해당 루프 사이클에 남아 있는 나머지 명령어를 건너뛰고 다음 단계의 루프를 수행하도록 하는 키워드입니다. ```lua local oddNumbers = {} for i = 1, 10 do if i % 2 == 0 then co [chunk_id] | Guides:1071:0
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | **DataStorage 사용 가이드 (상점 구매 로직 예제)** 클라이언트 요청을 서버에서 처리할 때, 사용자 데이터(`UserDataComponent`)가 초기화되었는지 확인하여 무결성을 보장합니다. `initialized` 프로퍼티가 `false`인 경우(로드 실패 등) 구매 처리를 중단해야 합니다. **핵심 동작 규칙** * **초기화 확인**: `userEntity.UserDataComponent.initialized` 값을 검증해야 합니다. * **실패 처리**: 초기화되지 않은 경우 `log` 출력 후 즉시 [original] | for i, id in pairs(event.items) do table.insert(self.items, id) end } ``` Initialized 프로퍼티에 따라 상점 구매 로직 진행 여부를 결정하는 Logic 스크립트 예제입니다. ```lua Method: [server] void RequestBuyItemFromClient(string userId, integer buyItemId) { local userEntity = _UserService:GetUserEntityByUserId(u [chunk_id] | Guides:1073:5
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | ## DataStorage: 연관 데이터 무결성 관리 연관된 Key(예: `Item`, `Currency`) 중 하나만 로드/저장 실패하면 데이터 불일치(예: 결제는 되지만 아이템 미보유)가 발생합니다. 이를 방지하기 위해 **모든 연관 데이터 로드 성공 여부를 검증**하고, 하나라도 실패하면 **전체 저장/기능을 차단**하는 로직을 구현해야 합니다. ### 핵심 규칙 1. **원자성 보장**: 연관된 데이터는 모두 로드 성공 시에만 `initialized` 플래그를 `true`로 설정합니다. 2. **실패 시 조기 종료** [original] | 크리에이터는 월드를 만들 때 일반적으로 다수의 Key를 사용해 데이터를 저장합니다. 이렇게 저장한 데이터끼리 연관이 있다면 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 연관된 데이터 중 하나를 저장하지 못하면 문제가 발생할 수 있습니다. 아래 그림은 연관된 두 값 중 하나의 데이터를 정상적으로 불러오지 못했을 때의 상황입니다. Item 데이터 값을 DataStorage로부터 불러오지 못해서 서버에 Item 1, 2, 3 없습니다. 불러온 데이터가 없기 때문에 Item 4를 유저가 구매했더라도 정상적으로 저장을 하면 [chunk_id] | Guides:1073:3
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | ```lua -- 문서에 명시된 핵심 사실 및 API 사용 규칙 목록 ``` 1. 크리에이터는 월드 내에서 데이터를 저장할 때 일반적으로 다수의 Key를 사용하여 데이터를 관리하며, 이러한 저장된 데이터들 간에 연관성이 존재할 경우 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 2. 연관된 데이터 중 하나를 정상적으로 불러오지 못하면, 이전에 쌓인 데이터가 사라지고 실패하지 않은 데이터만 저장되는 등의 데이터 무결성 문제가 발생할 수 있으므로, 연관된 모든 데이터의 불러오기 성공 여부를 확인한 뒤 저장 및 기능 사용을 [original] | 크리에이터는 월드를 만들 때 일반적으로 다수의 Key를 사용해 데이터를 저장합니다. 이렇게 저장한 데이터끼리 연관이 있다면 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 연관된 데이터 중 하나를 저장하지 못하면 문제가 발생할 수 있습니다. 아래 그림은 연관된 두 값 중 하나의 데이터를 정상적으로 불러오지 못했을 때의 상황입니다. Item 데이터 값을 DataStorage로부터 불러오지 못해서 서버에 Item 1, 2, 3 없습니다. 불러온 데이터가 없기 때문에 Item 4를 유저가 구매했더라도 정상적으로 저장을 하면 [chunk_id] | Guides:1073:3
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 제공된 문서 단편에는 `Initialized` 프로퍼티를 활용한 상점 구매 로직 예제와 데이터 저장 이벤트 핸들러가 포함되어 있습니다. 원문에 명시된 정보만 기반으로 핵심 사실을 정리하면 다음과 같습니다. 1. `RequestBuyItemFromClient` 메서드는 `[server]` 실행 공간에서 실행되며, 매개변수로 `string` 타입의 `userId`와 `integer` 타입의 `buyItemId`를 받습니다. 2. `RequestBuyItemFromClient` 메서드 내부에서는 `_UserService:GetUserE [original] | for i, id in pairs(event.items) do table.insert(self.items, id) end } ``` Initialized 프로퍼티에 따라 상점 구매 로직 진행 여부를 결정하는 Logic 스크립트 예제입니다. ```lua Method: [server] void RequestBuyItemFromClient(string userId, integer buyItemId) { local userEntity = _UserService:GetUserEntityByUserId(u [chunk_id] | Guides:1073:5
[task] | wikipedia [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | ## 효과적인 DataStorage 사용: 로드 실패 시 저장 방지 전략 메이플스토리 월드(MapleStory Worlds) 개발 환경에서 `DataStorage`를 활용할 때, 월드의 핵심 기능이 아닌 부차적인 데이터(예: 메소 보유량 등)의 로드 실패를 처리하는 방법 중 하나는 해당 데이터를 저장하지 않는 것입니다. 이는 데이터 무결성을 유지하고, 불완전 상태의 데이터가 저장되는 것을 방지하는 데 도움이 됩니다. 아래 구현 예제는 컴포넌트(`Component`)에서 데이터 로드 성공 여부를 프로퍼티(`Property`)로 관 [original] | 월드에 필수적인 데이터가 아닌 경우 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식도 고려할 수 있습니다. 아래의 예제는 Component에서 요청 성공 여부를 Property에 저장하고, Logic을 이용해 데이터를 저장하지 않도록 구현합니다. ```lua Property: [Sync] boolean initialized = false -- 이 프로퍼티를 사용해 저장 막기. [Sync] integer meso = 0 Method: [server only] void OnBeginPlay() { if [chunk_id] | Guides:1073:2
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: 연관된 데이터 중 하나를 저장하지 못했을 때 발생할 수 있는 문제를 피하기 위해 권장되는 접근 방식은 무엇인가요? 답변: 연관된 모든 데이터의 불러오기 성공 여부를 확인한 뒤, 성공한 경우에만 아이템 구매 기능을 허용하고 데이터를 저장하는 것을 권장합니다. 질문: 아래 코드에서 `initialized` 프로퍼티의 타입과 동기화 속성은 무엇인가요? ```lua [Sync] boolean initialized = false ``` 답변: `initialized` 프로퍼티의 타입은 `boolean`이며, 동기화 속성은 `[Syn [original] | 크리에이터는 월드를 만들 때 일반적으로 다수의 Key를 사용해 데이터를 저장합니다. 이렇게 저장한 데이터끼리 연관이 있다면 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 연관된 데이터 중 하나를 저장하지 못하면 문제가 발생할 수 있습니다. 아래 그림은 연관된 두 값 중 하나의 데이터를 정상적으로 불러오지 못했을 때의 상황입니다. Item 데이터 값을 DataStorage로부터 불러오지 못해서 서버에 Item 1, 2, 3 없습니다. 불러온 데이터가 없기 때문에 Item 4를 유저가 구매했더라도 정상적으로 저장을 하면 [chunk_id] | Guides:1073:3
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: 문서에서 제안하는 "데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식"의 핵심 목적은 무엇인가요? 답변: 월드에 필수적인 데이터가 아닌 경우, 데이터를 불러오는 데 실패했을 때 데이터를 저장하지 않도록 하여 문제를 방지하는 것입니다. 질문: 아래 코드는 무엇을 구현하고 있나요? ```lua if self:LoadMesoData() == false then return end self.initialized = true ``` 답변: 데이터 로딩이 성공했을 때만 `initialized` 프로퍼티를 `true` [original] | 월드에 필수적인 데이터가 아닌 경우 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식도 고려할 수 있습니다. 아래의 예제는 Component에서 요청 성공 여부를 Property에 저장하고, Logic을 이용해 데이터를 저장하지 않도록 구현합니다. ```lua Property: [Sync] boolean initialized = false -- 이 프로퍼티를 사용해 저장 막기. [Sync] integer meso = 0 Method: [server only] void OnBeginPlay() { if [chunk_id] | Guides:1073:2
[task] | extract_knowledge [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage 요청 실패 시 저장 방지 패턴 ## 개념 설명 월드에 필수적인 데이터가 아닌 경우, `DataStorage`에서 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식을 고려할 수 있습니다. 이 패턴은 컴포넌트에서 요청 성공 여부를 `Property`에 저장하고, Logic을 이용해 저장 여부를 제어함으로써, 초기화되지 않은 상태로 데이터를 덮어쓰는 것을 방지합니다. ## API 사용법 * `_DataStorageService:GetUserDataStorage(userId)`: 플레이어의 `us [original] | 월드에 필수적인 데이터가 아닌 경우 데이터를 불러오는 데 실패했다면 데이터를 저장하지 않는 방식도 고려할 수 있습니다. 아래의 예제는 Component에서 요청 성공 여부를 Property에 저장하고, Logic을 이용해 데이터를 저장하지 않도록 구현합니다. ```lua Property: [Sync] boolean initialized = false -- 이 프로퍼티를 사용해 저장 막기. [Sync] integer meso = 0 Method: [server only] void OnBeginPlay() { if [chunk_id] | Guides:1073:2
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 제공된 문서 조각을 바탕으로 추출한 핵심 사실 목록입니다. ```lua 1. `LoadItems` 메서드는 `[server only]` 실행 공간에서 동작하며, `_DataStorageService:GetUserDataStorage(self.Entity.PlayerComponent.UserId)`를 호출하여 사용자 데이터 스토리지 객체를 획득하고, 객체가 nil이 아닌 경우 `userDataStorage:GetAndWait("Items")`를 호출하여 에러 코드와 아이템 문자열을 반환받습니다. 2. `LoadItems` 메서드에서 [original] | if _UtilLogic:IsNilorEmptyString(currencyString) == false then local currency = _HttpService:JSONDecode(currencyString) if currency.meso ~= nil then self.meso = currency.meso end if currency.cash ~= nil then self.cash = currency.cash [chunk_id] | Guides:1073:4
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | **핵심 정보: DataStorage 사용 패턴 (mLua)** **1. 데이터 로드 (Load)** * **서비스**: `_DataStorageService:GetUserDataStorage(UserId)` * **동작**: `GetAndWait(Key)` 호출 후 에러 코드 확인. * **주의**: `errorCode ~= 0` 이면 실패 처리. 문자열은 `_HttpService:JSONDecode` 로 파싱하여 Property에 저장. * **예시 (Currency/Items 공통 로직)**: ```lua [s [original] | if _UtilLogic:IsNilorEmptyString(currencyString) == false then local currency = _HttpService:JSONDecode(currencyString) if currency.meso ~= nil then self.meso = currency.meso end if currency.cash ~= nil then self.cash = currency.cash [chunk_id] | Guides:1073:4
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 제시된 문서 내용에만 기반하여 핵심 사실을 추출한 목록입니다. 1. DataStorage에는 사용량 제한이 존재하며, Credit을 소모하는 DataStorage 관련 함수를 과도하게 자주 호출하면 문제가 발생할 수 있습니다. 2. DataStorage에서 Key를 사용하는 것은 Credit을 소모하므로, Key의 수가 증가하면 데이터 저장 및 불러오기 시 Credit 사용량이 비례하여 증가합니다. 3. Credit 효율화를 위해 연관된 데이터를 하나의 String으로 묶고 단일 Key로 저장하는 방식을 권장하며, 이는 데이터 관 [original] | # DataStorage 사용량 제한과 문자열 DataStorage는 사용량 제한이 있습니다. 제한으로 인해 Credit을 사용하는 DataStorage 류의 함수들을 너무 자주 호출하면 문제가 발생할 수 있습니다. 사용량 제한의 자세한 내용은 [DataStorage 사용량 제한 알아보기](/docs/?postId=1044), [DataStorage 사용량 제한 활용하기](/docs/?postId=1045)를 참고하세요. #### 하나의 String으로 저장 Key를 사용하면 Credit을 사용합니다. 아래 예시처럼 많은 Ke [chunk_id] | Guides:1073:6
[task] | wikipedia [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | **효과적인 DataStorage 사용법: Initialized 프로퍼티를 통한 초기화 상태 확인** 메이플스토리 월드(MapleStory Worlds)의 `DataStorage` 컴포넌트를 사용할 때, 서버 로직이 데이터 로드 완료 여부를 확인하지 않고 즉시 실행되면 오류가 발생할 수 있습니다. 이를 방지하기 위해 `DataStorage` 컴포넌트의 `initialized` 프로퍼티를 활용하여 데이터가 정상적으로 로드되었는지를 확인하는 것이 필수적입니다. `DataStorage` 컴포넌트는 사용자 데이터의 로드 및 저장 상태를 [original] | for i, id in pairs(event.items) do table.insert(self.items, id) end } ``` Initialized 프로퍼티에 따라 상점 구매 로직 진행 여부를 결정하는 Logic 스크립트 예제입니다. ```lua Method: [server] void RequestBuyItemFromClient(string userId, integer buyItemId) { local userEntity = _UserService:GetUserEntityByUserId(u [chunk_id] | Guides:1073:5
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: `_DataStorageService:GetUserDataStorage` 메서드 호출 시 파라미터로 전달해야 하는 값은 무엇인가요? 답변: `self.Entity.PlayerComponent.UserId` 값을 전달해야 합니다. 질문: `LoadItems` 메서드에서 `userDataStorage`가 `nil`인 경우 반환되는 값은 무엇인가요? 답변: `false`를 반환합니다. 질문: `SaveData` 메서드에서 `self.initialized`가 `false`일 때 어떤 동작이 수행되나요? 답변: `"info is [original] | if _UtilLogic:IsNilorEmptyString(currencyString) == false then local currency = _HttpService:JSONDecode(currencyString) if currency.meso ~= nil then self.meso = currency.meso end if currency.cash ~= nil then self.cash = currency.cash [chunk_id] | Guides:1073:4
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage 효율적 사용: 문자열 변환 DataStorage는 사용량 제한이 있어, Credit을 소모하는 함수를 과도하게 호출하면 문제가 발생합니다. Key 개수가 증가할수록 Credit 소모가 급증하므로, 연관된 데이터를 **하나의 String으로 묶어 단일 Key로 저장**하는 방식을 권장합니다. ## 변환 방법 ### 1. JSON 변환 (권장) `_HttpService:JSONEncode()` / `_HttpService:JSONDecode()` * **특징**: Table ↔ JSON String 변 [original] | # DataStorage 사용량 제한과 문자열 DataStorage는 사용량 제한이 있습니다. 제한으로 인해 Credit을 사용하는 DataStorage 류의 함수들을 너무 자주 호출하면 문제가 발생할 수 있습니다. 사용량 제한의 자세한 내용은 [DataStorage 사용량 제한 알아보기](/docs/?postId=1044), [DataStorage 사용량 제한 활용하기](/docs/?postId=1045)를 참고하세요. #### 하나의 String으로 저장 Key를 사용하면 Credit을 사용합니다. 아래 예시처럼 많은 Ke [chunk_id] | Guides:1073:6
[task] | wikipedia [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage의 연관 데이터 무결성 관리 메이플스토리 월드(MapleStory Worlds)에서 크리에이터가 월드를 개발할 때, `_DataStorageService`를 통해 데이터를 저장하고 로드하는 과정에서 데이터 무결성(Integrity)을 유지하는 것은 중요한 고려 사항입니다. 일반적으로 크리에이터는 다양한 `Key`를 사용하여 데이터를 저장합니다. 이때 저장된 데이터들이 서로 기능적으로 연관되어 있다면, 일부 데이터의 저장 또는 로드 실패로 인해 발생할 수 있는 상태 불일치를 방지하기 위한 전략이 필요합니다. [original] | 크리에이터는 월드를 만들 때 일반적으로 다수의 Key를 사용해 데이터를 저장합니다. 이렇게 저장한 데이터끼리 연관이 있다면 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 연관된 데이터 중 하나를 저장하지 못하면 문제가 발생할 수 있습니다. 아래 그림은 연관된 두 값 중 하나의 데이터를 정상적으로 불러오지 못했을 때의 상황입니다. Item 데이터 값을 DataStorage로부터 불러오지 못해서 서버에 Item 1, 2, 3 없습니다. 불러온 데이터가 없기 때문에 Item 4를 유저가 구매했더라도 정상적으로 저장을 하면 [chunk_id] | Guides:1073:3
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: `Initialized` 프로퍼티가 `false`인 경우 상점 구매 로직은 어떻게 처리되는가요? 답변: `userDataComponent.initialized`가 `false`일 경우, "userDataComponent not initialized" 로그를 출력하고 함수를 반환하여 상점 구매를 진행하지 않습니다. 질문: 다음 코드 조각에서 `_UserService:GetUserEntityByUserId(userId)` 함수의 역할은 무엇인가요? ```lua local userEntity = _UserService:GetUs [original] | for i, id in pairs(event.items) do table.insert(self.items, id) end } ``` Initialized 프로퍼티에 따라 상점 구매 로직 진행 여부를 결정하는 Logic 스크립트 예제입니다. ```lua Method: [server] void RequestBuyItemFromClient(string userId, integer buyItemId) { local userEntity = _UserService:GetUserEntityByUserId(u [chunk_id] | Guides:1073:5
[task] | extract_knowledge [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage를 활용한 연관 데이터 무결성 보장 ## 1. 개념 설명 월드 개발 시 `DataStorage`를 사용하여 다수의 Key로 데이터를 저장하는 경우가 일반적입니다. 이때 서로 연관성이 있는 데이터(예: 화폐와 아이템)가 존재한다면, 데이터의 무결성을 유지하기 위한 로직이 필요합니다. 연관된 데이터 중 일부만 정상적으로 로드되지 않는 상태(예: 아이템 데이터 로드 실패, 화폐 데이터 로드 성공)가 발생하면, 서버에서 데이터 저장이 부분적으로만 이루어질 수 있습니다. 이 경우 유저가 화폐를 지출했지만 아이템은 [original] | 크리에이터는 월드를 만들 때 일반적으로 다수의 Key를 사용해 데이터를 저장합니다. 이렇게 저장한 데이터끼리 연관이 있다면 관련 기능 차단 또는 데이터 저장 차단을 고려해야 합니다. 연관된 데이터 중 하나를 저장하지 못하면 문제가 발생할 수 있습니다. 아래 그림은 연관된 두 값 중 하나의 데이터를 정상적으로 불러오지 못했을 때의 상황입니다. Item 데이터 값을 DataStorage로부터 불러오지 못해서 서버에 Item 1, 2, 3 없습니다. 불러온 데이터가 없기 때문에 Item 4를 유저가 구매했더라도 정상적으로 저장을 하면 [chunk_id] | Guides:1073:3
[task] | wikipedia [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage 사용량 제한과 문자열 처리 전략 DataStorage에는 사용량 제한이 존재하며, 이 제한으로 인해 Credit을 소모하는 DataStorage 관련 함수를 과도하게 호출하면 문제가 발생할 수 있습니다. 사용량 제한에 대한 구체적인 사항은 'DataStorage 사용량 제한 알아보기' 및 'DataStorage 사용량 제한 활용하기' 문서를 참고해야 합니다. ## 하나의 String으로 데이터 묶기 DataStorage에서 Key를 사용하는 것 자체가 Credit 소모를 유발합니다. 따라서 Key의 수 [original] | # DataStorage 사용량 제한과 문자열 DataStorage는 사용량 제한이 있습니다. 제한으로 인해 Credit을 사용하는 DataStorage 류의 함수들을 너무 자주 호출하면 문제가 발생할 수 있습니다. 사용량 제한의 자세한 내용은 [DataStorage 사용량 제한 알아보기](/docs/?postId=1044), [DataStorage 사용량 제한 활용하기](/docs/?postId=1045)를 참고하세요. #### 하나의 String으로 저장 Key를 사용하면 Credit을 사용합니다. 아래 예시처럼 많은 Ke [chunk_id] | Guides:1073:6
[task] | extract_knowledge [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage 초기화 상태 확인 및 로직 제어 ## 1. 개념 설명 메이플스토리 월드에서 서버 측 사용자 데이터는 `UserDataComponent`를 통해 관리됩니다. 클라이언트가 서버와 연결된 직후, 해당 사용자의 `UserDataComponent`는 아직 서버에서 데이터를 로드(Load)하지 않은 상태일 수 있습니다. 이때 `initialized` 프로퍼티는 해당 사용자의 데이터가 정상적으로 로드되었는지 여부를 나타내는 플래그로 작용합니다. 서버 측에서 사용자 데이터를 수정하거나 읽기 전에 `initialized [original] | for i, id in pairs(event.items) do table.insert(self.items, id) end } ``` Initialized 프로퍼티에 따라 상점 구매 로직 진행 여부를 결정하는 Logic 스크립트 예제입니다. ```lua Method: [server] void RequestBuyItemFromClient(string userId, integer buyItemId) { local userEntity = _UserService:GetUserEntityByUserId(u [chunk_id] | Guides:1073:5
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | `DataStorage`는 저장 요청 빈도에 따라 Credit 소모가 발생하므로, 값 변경 시마다 저장하지 말고 아래 3가지 상황에서만 저장하도록 설계하세요. 1. **유저 접속 종료 시**: 세션이 끝날 때 데이터를 저장합니다. 2. **일정 시간 주기 저장**: 서버 오류로 저장 실패를 방지하기 위해 주기적으로 저장합니다. 주기가 짧을수록 안정성은 올라가지만 Credit 소모가 증가하므로 적정 주기를 설정해야 합니다. 3. **예외 상황 발생 시**: 반드시 즉시 갱신이 필요한 특수한 값이 있을 때만 예외적으로 저장합니다. [original] | 사용량 제한이 걸린 DataStorage에 데이터를 자주 저장하게 하면 Credit이 부족할 수 있습니다. 그러므로 값이 변경될 때마다 데이터를 저장할 필요가 없는 값들은 Property를 사용해 특정 상황일 때만 저장해 Credit 소모량을 줄일 수 있습니다. 주로 아래 3가지 상황에서 저장하는 것을 권장합니다. 1. **유저 접속 종료 시 저장**: 유저가 접속을 종료하면 데이터를 DataStorage에 저장합니다. 2. **일정 시간마다 저장**: 유저의 갱신된 정보는 주기적으로 저장해야 합니다. 서버에 문제가 생겨 저장에 [chunk_id] | Guides:1073:8
[task] | distill [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage: 직접 String 형식 활용 사전 정의된 String 형식 함수 대신 직접 문자열을 생성·저장하여 데이터 길이를 줄일 수 있습니다. ## 핵심 API 및 조작 * **문자열 분할/합치기**: `_UtilLogic:Split(str, delimiter)`와 `..` 연산자 사용. * **Table 변환**: `table.concat` 활용 가능. * **공백/Nil 체크**: `_UtilLogic:IsNilorEmptyString(str)` ## 코드 예제 메소(meso)와 캐시(cash)를 [original] | 크리에이터는 사전 정의된 String 형식을 따르는 함수들을 사용하는 대신 직접 string을 만들어 사용할 수 있습니다. 직접 만들 경우 데이터를 더 짧은 문자열로 저장할 수 있습니다. 아래의 예제와 같이 `_UtilLogic:Split()`과 `문자열 합치기(..)`를 사용해 String을 문자열로 나누고, 합칠 수 있습니다. Table<v> 데이터는 table.concat을 사용할 수 있습니다. ```lua Property: [None] integer meso = 0 [None] integer cash = 0 Method [chunk_id] | Guides:1073:7
[task] | extract_knowledge [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | # DataStorage의 재시도(Retry) 및 에러 처리 전략 ## 1. 개념 설명 `_DataStorageService`를 통해 유저 데이터를 불러올 때, 일시적인 네트워크 장애나 서버 내부 오류로 인해 요청이 실패할 수 있습니다. 이러한 비정상적인 실패를 방지하기 위해, 데이터 로딩 로직은 **재시도(Retry)** 메커니즘을 포함해야 합니다. 재시도 로직은 다음과 같은 두 가지 케이스를 구분하여 처리해야 합니다. 1. **일시 장애(Transient Error):** 원인이 불명확한 일시적인 실패. 일정 시간(예: [original] | 크리에이터는 정상적으로 요청했지만 원인이 불명확한 일시 장애가 발생해 데이터 불러오기를 실패할 수 있습니다. 이런 상황을 대비해 데이터 불러오기 요청을 여러 번 시도할 수 있습니다. 아래 예시 코드는 데이터 불러오기에 실패하면 2초 뒤에 재시도합니다. 그 이후 일정 횟수 이상 실패하면 유저를 월드에서 추방합니다. 더불어 과도한 요청으로 인한 에러 코드 ResourceExhausted: 1000005가 발생하면, 재시도하지 않고 유저를 추방합니다. ```lua Property: [Sync] integer meso = 0 [Syn [chunk_id] | Guides:1073:1
[task] | diverse_qa [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 질문: DataStorage에서 Credit을 효율적으로 사용하기 위해 권장되는 저장 방식은 무엇인가요? 답변: 연관 있는 데이터들을 하나로 모아 하나의 String으로 묶고, 하나의 Key를 사용하여 저장하는 방식을 권장합니다. 질문: `_HttpService:JSONEncode()`와 `_HttpService:JSONDecode()` 함수의 주요 용도는 무엇인가요? 답변: Table과 Json String 간의 변환을 수행하여 데이터를 하나의 String으로 저장하거나 불러오기 위한 용도로 사용됩니다. 질문: `_UtilLo [original] | # DataStorage 사용량 제한과 문자열 DataStorage는 사용량 제한이 있습니다. 제한으로 인해 Credit을 사용하는 DataStorage 류의 함수들을 너무 자주 호출하면 문제가 발생할 수 있습니다. 사용량 제한의 자세한 내용은 [DataStorage 사용량 제한 알아보기](/docs/?postId=1044), [DataStorage 사용량 제한 활용하기](/docs/?postId=1045)를 참고하세요. #### 하나의 String으로 저장 Key를 사용하면 Credit을 사용합니다. 아래 예시처럼 많은 Ke [chunk_id] | Guides:1073:6
[task] | knowledge_list [title] | 효과적으로 DataStorage 사용하기 [category] | Guides [rephrased] | 1. 크리에이터는 사전 정의된 String 형식을 따르는 함수 대신 직접 문자열을 생성하여 DataStorage에 저장할 수 있으며, 이를 통해 데이터를 더 짧은 문자열로 저장할 수 있습니다. 2. `_UtilLogic:Split()` 메서드는 문자열을 지정된 구분자로 나누어 Table 형태로 반환하며, `문자열 합치기(..)` 연산자를 사용하여 개별 문자열을 하나의 문자열로 결합할 수 있습니다. 3. `Table<v>` 타입의 데이터를 문자열로 변환하여 저장할 경우 `table.concat` 함수를 사용할 수 있습니다. 4. `_ [original] | 크리에이터는 사전 정의된 String 형식을 따르는 함수들을 사용하는 대신 직접 string을 만들어 사용할 수 있습니다. 직접 만들 경우 데이터를 더 짧은 문자열로 저장할 수 있습니다. 아래의 예제와 같이 `_UtilLogic:Split()`과 `문자열 합치기(..)`를 사용해 String을 문자열로 나누고, 합칠 수 있습니다. Table<v> 데이터는 table.concat을 사용할 수 있습니다. ```lua Property: [None] integer meso = 0 [None] integer cash = 0 Method [chunk_id] | Guides:1073:7