

지원 종료 공지: 2026 AWS 년 5월 20일에에 대한 지원이 종료됩니다 AWS SimSpace Weaver. 2026년 5월 20일 이후에는 SimSpace Weaver 콘솔 또는 SimSpace Weaver 리소스에 더 이상 액세스할 수 없습니다. 자세한 내용은 [AWS SimSpace Weaver 지원 종료를 참조하세요](https://docs.aws.amazon.com/simspaceweaver/latest/userguide/simspaceweaver-end-of-support.html).

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 엔터티에 필드 데이터 쓰기 및 읽기
<a name="working-with_app-sdk_ent_readwrite"></a>

모든 엔터티 데이터 필드는 blob 유형입니다. 엔터티에 최대 1,024바이트의 데이터를 쓸 수 있습니다. Blob 크기가 클수록 성능이 저하되므로 blob을 최대한 작게 유지하는 것이 좋습니다. Blob에 쓸 때 포인터 SimSpace Weaver 를 데이터 및 길이에 전달합니다. Blob에서 읽을 때 SimSpace Weaver 는 포인터 및 읽을 길이를 제공합니다. 앱이 `Commit()`을 호출하기 전에 모든 읽기가 완료되어야 합니다. 읽기 호출에서 반환된 포인터는 앱이 `Commit()`을 호출할 때 무효화됩니다.

**중요**  
`Commit()` 이후에 캐시된 blob 포인터에서의 읽기는 지원되지 않으므로 시뮬레이션이 실패할 수 있습니다.
읽기 호출에서 반환된 blob 포인터에서의 쓰기는 지원되지 않으므로 시뮬레이션이 실패할 수 있습니다.

**Topics**
+ [

# 엔터티의 필드 데이터 저장
](working-with_app-sdk_ent_readwrite_store.md)
+ [

# 엔터티의 필드 데이터 불러오기
](working-with_app-sdk_ent_readwrite_load.md)
+ [

# 제거된 엔터티의 필드 데이터 로드
](working-with_app-sdk_ent_readwrite_load-removed.md)

# 엔터티의 필드 데이터 저장
<a name="working-with_app-sdk_ent_readwrite_store"></a>

다음 예제는 앱이 소유한 엔터티의 필드 데이터를 저장(상태 패브릭에 쓰기)하는 방법을 보여줍니다. 해당 예제에는 다음 함수가 사용됩니다.

```
AWS_WEAVERRUNTIME_API Result<void> StoreEntityField(
    Transaction& txn,
    const Entity& entity,
    TypeId keyTypeId,
    FieldIndex index,
    std::int8_t* src,
    std::size_t length) noexcept;
```

`Api::TypeId keyTypeId` 파라미터는 전달된 데이터의 데이터 유형을 나타냅니다.

`Api::TypeId keyTypeId` 파라미터는 `Api::BuiltinTypeId`에서 해당 `Api::TypeId`를 수신해야 합니다. 적절한 변환이 없는 경우 `Api::BuiltinTypeId::Dynamic`을 사용할 수 있습니다.

복잡한 데이터 유형의 경우 `Api::BuiltInTypeId::Dynamic`을 사용합니다.

**참고**  
`FieldIndex index` 값은 0보다 커야 합니다. 0 값은 인덱스 키용으로 예약되어 있습니다(`StoreEntityIndexKey()` 참조).

**Example 프리미티브 데이터 유형을 사용한 예제**  

```
namespace
{
    constexpr Api::FieldIndex k_isTrueFieldId { /* value */ 1 };
}

Result<void> SetEntityFields(
    Api::Entity& entity, 
    Transaction& transaction)
{
    bool value = true;
    
    auto* src = reinterpret_cast<std::int8_t*>(value);
    size_t length = sizeof(*value);
    
    WEAVERRUNTIME_TRY(Api::StoreEntityField(
        transaction,
        entity,
        Api::BuiltinTypeIdToTypeId(
            Aws::WeaverRuntime::Api::BuiltinTypeId::Bool),
        k_isTrueFieldId,
        src,
        length));
}
```

**Example struct를 사용한 데이터 보관 예제**  

```
namespace
{
    constexpr Api::FieldIndex k_dataFieldId { /* value */ 1 };
}

struct Data
{
    bool boolData;
    float floatData;
};

Result<void> SetEntityFields(
    Api::Entity& entity, 
    Transaction& transaction)
{
    Data data = { /* boolData */ false, /* floatData */ -25.93 };
    
    auto* src = reinterpret_cast<std::int8_t*>(data);
    size_t length = sizeof(*data);
    
    WEAVERRUNTIME_TRY(Api::StoreEntityField(
        transaction,
        entity,
        Api::BuiltinTypeIdToTypeId(
            Aws::WeaverRuntime::Api::BuiltinTypeId::Dynamic),
        k_dataFieldId,
        src,
        length));
}
```

# 엔터티의 필드 데이터 불러오기
<a name="working-with_app-sdk_ent_readwrite_load"></a>

다음 예제는 엔터티의 필드 데이터를 로드(상태 패브릭에서 읽기)하는 방법을 보여줍니다. 해당 예제에는 다음 함수가 사용됩니다.

```
Result<std::size_t> LoadEntityField(
    Transaction& txn,
    const Entity& entity,
    TypeId keyTypeId,
    FieldIndex index,
    std::int8_t** dest) noexcept;
```

`Api::TypeId keyTypeId` 파라미터는 `Api::BuiltinTypeId`에서 해당 `Api::TypeId`를 수신해야 합니다. 적절한 변환이 없는 경우 `Api::BuiltinTypeId::Dynamic`을 사용할 수 있습니다.

**참고**  
`FieldIndex` 인덱스 값은 0보다 커야 합니다. 0 값은 인덱스 키용으로 예약되어 있습니다(`StoreEntityIndexKey()` 참조).

**Example 프리미티브 데이터 유형을 사용한 예제**  

```
namespace
{
    constexpr Api::FieldIndex k_isTrueFieldId { /* value */ 1 };
}

Result<void> LoadEntityFields(
    Api::Entity& entity, 
    Transaction& transaction)
{
    std::int8_t* dest = nullptr;
    
    WEAVERRUNTIME_TRY(Api::LoadEntityField(
        transaction,
        entity,
        Api::BuiltinTypeIdToTypeId(
            Aws::WeaverRuntime::Api::BuiltinTypeId::Bool),
        k_isTrueFieldId,
        &dest));
    
    bool isTrueValue = *reinterpret_cast<bool*>(dest);
}
```

**Example struct를 사용한 데이터 보관 예제**  

```
namespace
{
    constexpr Api::FieldIndex k_dataFieldId { /* value */ 1 };
}

struct Data
{
    bool boolData;
    float floatData;
};

Result<void> LoadEntityFields(
    Api::Entity& entity, 
    Transaction& transaction)
{
    std::int8_t* dest = nullptr;
    
    WEAVERRUNTIME_TRY(Api::LoadEntityField(
        transaction,
        entity,
        Api::BuiltinTypeIdToTypeId(
            Aws::WeaverRuntime::Api::BuiltinTypeId::Dynamic),
        k_dataFieldId,
        &dest));
    
    Data dataValue = *reinterpret_cast<Data*>(dest);
}
```

# 제거된 엔터티의 필드 데이터 로드
<a name="working-with_app-sdk_ent_readwrite_load-removed"></a>

앱의 소유권 및 구독 영역에서 제거된 엔터티의 엔터티 필드 데이터는 로드(상태 패브릭에서 읽기)할 수 없습니다. 다음 예제에서는 `Api::ChangeListAction::Remove`의 결과로 엔터티에 대한 `Api::LoadIndexKey()` 호출로 인해 오류가 발생합니다. 두 번째 예제는 앱에서 직접 항목 데이터를 저장하고 로드하는 올바른 방법을 보여줍니다.

**Example 잘못된 코드의 예제**  

```
Result<void> ProcessSubscriptionChanges(Transaction& transaction)
{
    /* ... */
    
    WEAVERRUNTIME_TRY(Api::SubscriptionChangeList subscriptionChangeList, 
        Api::AllSubscriptionEvents(transaction));
    
    for (const Api::SubscriptionEvent& event : 
        subscriptionChangeList.changes)
    {
        switch (event.action)
        {
        case Api::ChangeListAction::Remove:
            {
                std::int8_t* dest = nullptr;
    
                /**
                 * Error!
                 * This calls LoadEntityIndexKey on an entity that
                 * has been removed from the subscription area.
                 */
                WEAVERRUNTIME_TRY(Api::LoadEntityIndexKey(
                    transaction,
                    event.entity,
                    Api::BuiltinTypeIdToTypeId(
                        Api::BuiltinTypeId::Vector3F32),
                    &dest));
    
                AZ::Vector3 position = 
                    *reinterpret_cast<AZ::Vector3*>(dest);
                break;
            }
        }
 
    }

    /* ... */
}
```

**Example 앱에서 항목 데이터를 저장하고 로드하는 올바른 방법의 예제**  

```
Result<void> ReadAndSaveSubscribedEntityPositions(Transaction& transaction)
{
    static std::unordered_map<Api::EntityId, AZ::Vector3> 
        positionsBySubscribedEntity;

    WEAVERRUNTIME_TRY(Api::SubscriptionChangeList subscriptionChangeList, 
        Api::AllSubscriptionEvents(transaction));

    for (const Api::SubscriptionEvent& event : 
        subscriptionChangeList.changes)
    {
        switch (event.action)
        {
        case Api::ChangeListAction::Add:
            {
                std::int8_t* dest = nullptr;

                /**
                 * Add the position when the entity is added.
                 */
                WEAVERRUNTIME_TRY(Api::LoadEntityIndexKey(
                    transaction,
                    event.entity,
                    Api::BuiltinTypeIdToTypeId(
                        Api::BuiltinTypeId::Vector3F32),
                    &dest));

                AZ::Vector3 position = 
                    *reinterpret_cast<AZ::Vector3*>(dest);
                positionsBySubscribedEntity.emplace(
                    event.entity.descriptor->id, position);

                break;
            }
        case Api::ChangeListAction::Update:
            {
                std::int8_t* dest = nullptr;

                /**
                 * Update the position when the entity is updated.
                 */
                WEAVERRUNTIME_TRY(Api::LoadEntityIndexKey(
                    transaction,
                    event.entity,
                    Api::BuiltinTypeIdToTypeId(
                        Api::BuiltinTypeId::Vector3F32),
                    &dest));

                AZ::Vector3 position = 
                    *reinterpret_cast<AZ::Vector3*>(dest);
                positionsBySubscribedEntity[event.entity.descriptor->id] = 
                    position;

                break;
            }
        case Api::ChangeListAction::Remove:
            {
                /**
                 * Load the position when the entity is removed.
                 */
                AZ::Vector3 position = positionsBySubscribedEntity[
                    event.entity.descriptor->id];

                /**
                 * Do something with position...
                 */
                break;
            }
        }
    }
    
    /* ... */
}
```