

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

# AWS IoT 디바이스 섀도우 서비스
<a name="iot-device-shadows"></a>

 AWS IoT 디바이스 섀도우 서비스는 AWS IoT 사물 객체에 섀도우를 추가합니다. 섀도우를 사용하면 디바이스가 연결되어 AWS IoT 있는지 여부에 관계없이 앱 및 기타 서비스에서 디바이스의 상태를 사용할 수 있습니다. AWS IoT 사물 객체에는 여러 개의 명명된 섀도우가 있을 수 있으므로 IoT 솔루션에서 디바이스를 다른 앱 및 서비스에 연결할 수 있는 더 많은 옵션이 제공됩니다.

AWS IoT 사물 객체는 명시적으로 생성될 때까지 섀도우가 없습니다. AWS IoT 콘솔을 사용하여 섀도우를 생성, 업데이트 및 삭제할 수 있습니다. 디바이스, 기타 웹 클라이언트 및 서비스는 MQTT 및 [예약된 MQTT 주제](reserved-topics.md#reserved-topics-shadow), [디바이스 섀도우 REST API](device-shadow-rest-api.md)를 사용한 HTTP 및 [AWS IoT의AWS CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot-data/index.html)를 사용하여 섀도우를 생성, 업데이트 및 삭제할 수 있습니다. 섀도우는에 의해 클라우드 AWS 에 저장되므로 디바이스 연결 여부에 관계없이 앱 및 기타 클라우드 서비스에서 디바이스 상태 데이터를 수집하고 보고할 수 있습니다.

## 섀도우 사용
<a name="device-shadow-using"></a>

섀도우는 디바이스, 앱 및 기타 클라우드 서비스가 데이터를 공유할 수 있는 신뢰할 수 있는 데이터 스토어를 제공합니다. 이를 통해 디바이스, 앱 및 기타 클라우드 서비스가 디바이스 상태를 유지하면서 연결하거나 연결을 끊을 수 있습니다.

디바이스, 앱 및 기타 클라우드 서비스가 연결되어 AWS IoT있는 동안 섀도우를 통해 디바이스의 현재 상태에 액세스하고 제어할 수 있습니다. 예를 들어 앱은 섀도우를 업데이트하여 디바이스 상태 변경을 요청할 수 있습니다.는 디바이스 변경을 나타내는 메시지를 AWS IoT 게시합니다. 디바이스는 이 메시지를 수신하고, 메시지와 일치하도록 상태를 업데이트하고, 업데이트된 상태로 메시지를 게시합니다. 디바이스 섀도우 서비스는 해당 섀도우에 이 업데이트된 상태를 반영합니다. 앱은 섀도우의 업데이트를 구독하거나 섀도우에 현재 상태를 쿼리할 수 있습니다.

디바이스가 오프라인 상태가 되더라도 앱은 여전히 AWS IoT 및 디바이스의 섀도우와 통신할 수 있습니다. 디바이스가 다시 연결되면 섀도우의 현재 상태를 수신하여 섀도우와 일치하도록 상태를 업데이트한 다음 업데이트된 상태로 메시지를 게시할 수 있습니다. 마찬가지로 앱이 오프라인으로 전환되고 오프라인 상태인 동안 디바이스 상태가 변경된 경우, 디바이스는 섀도우를 업데이트하여 앱이 다시 연결될 때 섀도우에 현재 상태를 쿼리하도록 할 수 있습니다.

디바이스가 자주 오프라인 상태이고 디바이스가 다시 연결된 후 델타 메시지를 수신하도록 디바이스를 구성하려는 경우 영구 세션 기능을 사용할 수 있습니다. 영구 세션 만료 기간에 대한 자세한 내용은 [영구 세션 만료 기간](https://docs.aws.amazon.com//general/latest/gr/iot-core.html#message-broker-limits)을 참조하세요.

### 명명된 섀도우 또는 명명되지 않은 섀도우 사용 선택
<a name="iot-device-shadow-named"></a>

디바이스 섀도우 서비스는 명명된 섀도우 및 명명되지 않은 섀도우, 즉 클래식 섀도우를 지원합니다. 사물 객체의 경우 명명된 섀도우는 여러 개 가질 수 있으며 명명되지 않은 섀도우는 하나만 가질 수 있습니다. 사물 객체는 명명된 예약 섀도우를 가질 수 있습니다. 이 섀도우는 이름을 업데이트할 수 없다는 점을 제외하면 명명된 섀도우와 비슷하게 작동합니다. 자세한 내용은 [명명된 예약 섀도우](https://docs.aws.amazon.com/iot/latest/developerguide/preparing-to-use-software-package-catalog.html#reserved-named-shadow)를 참조하세요.

사물 객체는 명명된 섀도우와 명명되지 않은 섀도우를 동시에 가질 수 있습니다. 그러나 각각에 액세스하는 데 사용되는 API는 약간 다르므로 솔루션에 가장 적합한 섀도우 유형을 결정하고 해당 유형만 사용하는 것이 더 효율적일 수 있습니다. 섀도우에 액세스하기 위한 API에 대한 자세한 내용은 [섀도우 주제](reserved-topics.md#reserved-topics-shadow) 단원을 참조하세요.

명명된 섀도우를 사용하여 사물 객체의 상태에 대한 다양한 보기를 생성할 수 있습니다. 예를 들어, 많은 속성을 가진 사물 객체를 각각 섀도우 이름으로 식별된 논리적 속성 그룹이 있는 섀도우로 분리할 수 있습니다. 속성을 섀도우별로 그룹화하고 정책을 사용하여 액세스를 제어함으로써 속성에 대한 액세스를 제한할 수도 있습니다. 디바이스 섀도우에 사용하는 정책에 대한 자세한 내용은 [AWS IoT에 사용되는 작업, 리소스 및 조건 키](https://docs.aws.amazon.com//service-authorization/latest/reference/list_awsiot.html)와 [AWS IoT Core 정책](https://docs.aws.amazon.com//iot/latest/developerguide/iot-policies.html)을 참조하세요.

명명되지 않은 클래식 섀도우는 명명된 섀도우보다 더 간단하지만 다소 제한적입니다. 각 AWS IoT 사물 객체에는 이름이 지정되지 않은 섀도우가 하나만 있을 수 있습니다. IoT 솔루션의 섀도우 데이터 사용이 제한적일 것으로 예상되는 경우 이 방법을 사용하여 섀도우 사용을 시작할 수 있습니다. 그러나 나중에 섀도우를 추가하려는 경우 처음부터 명명된 섀도우를 사용하는 것이 좋습니다.

플릿 인덱싱은 명명되지 않은 섀도우와 명명된 섀도우를 다르게 지원합니다. 자세한 정보는 [플릿 인덱싱 관리](managing-fleet-index.md)를 참조하세요.

### 섀도우 액세스
<a name="device-shadow-using-access"></a>

모든 섀도우는 예약된 [MQTT 주제](reserved-topics.md#reserved-topics-shadow) 및 섀도우에서 `get`, `update` 및 `delete` 작업을 지원하는 [HTTP URL](device-shadow-rest-api.md)을 보유합니다.

섀도우는 [JSON 섀도우 문서](device-shadow-document.md)를 사용하여 데이터를 저장하고 검색합니다. 섀도우 문서에는 디바이스 상태의 다음 측면을 설명하는 상태 속성이 포함되어 있습니다.
+ `desired`

  앱은 `desired` 객체를 업데이트하여 디바이스 속성에 대해 원하는 상태를 지정합니다.
+ `reported`

  디바이스는 `reported` 객체에 현재 상태를 보고합니다.
+ `delta`

  AWS IoT 는 `delta` 객체에서 원하는 상태와 보고된 상태 간의 차이를 보고합니다.

섀도우에 저장된 데이터는 업데이트 작업 메시지 본문의 상태 속성에 의해 결정됩니다. 후속 업데이트 작업은 기존 데이터 객체의 값을 수정하고 섀도우의 상태 객체에서 키 및 기타 요소를 추가 및 삭제할 수 있습니다. 섀도우 액세스에 대한 자세한 내용은 [디바이스에서 섀도우 사용](device-shadow-comms-device.md) 및 [앱 및 서비스에서 섀도우 사용](device-shadow-comms-app.md) 단원을 참조하세요.

**중요**  
업데이트 요청 권한은 신뢰할 수 있는 앱 및 디바이스로 제한되어야 합니다. 이렇게 하면 섀도우의 상태 속성이 예기치 않게 변경되는 것을 방지할 수 있습니다. 그렇지 않으면 섀도우를 사용하는 디바이스 및 앱이 상태 속성의 키가 변경될 수 있도록 설계되어야 합니다.

### 디바이스, 앱 및 기타 클라우드 서비스에서 섀도우 사용
<a name="device-shadow-implementing"></a>

디바이스, 앱 및 기타 클라우드 서비스에서 섀도우를 사용하려면 이러한 모든 작업 간에 일관성과 조정이 필요합니다. AWS IoT 디바이스 섀도우 서비스는 섀도우 상태를 저장하고, 섀도우 상태가 변경될 때 메시지를 보내고, 상태를 변경하는 메시지에 응답합니다. IoT 솔루션의 디바이스, 앱 및 기타 클라우드 서비스는 해당 상태를 관리하고 디바이스 섀도우의 상태와 일관성을 유지해야 합니다.

섀도우 상태 데이터는 동적이며 섀도우 액세스 권한이 있는 디바이스, 앱 및 기타 클라우드 서비스에 의해 변경될 수 있습니다. 이러한 이유로 각 디바이스, 앱 및 기타 클라우드 서비스가 섀도우와 상호 작용하는 방식을 고려하는 것이 중요합니다. 다음 예를 참조하세요.
+ 섀도우와 상태 데이터를 통신할 때 *디바이스*는 섀도우 상태의 `reported` 속성에만 기록해야 합니다.
+ *앱 및 기타 클라우드 서비스*는 섀도우를 통해 디바이스에 상태 변경 요청을 전달할 때 `desired` 속성에만 기록해야 합니다.

**중요**  
섀도우 데이터 객체에 포함된 데이터는 다른 섀도우 및 사물의 속성 및 사물 객체의 디바이스가 게시할 수 있는 MQTT 메시지의 콘텐츠와 같은 기타 사물 객체 속성과는 독립적입니다. 그러나 필요한 경우 디바이스는 서로 다른 MQTT 주제 및 섀도우에서 동일한 데이터를 보고할 수 있습니다.  
여러 섀도우를 지원하는 디바이스는 서로 다른 섀도우에서 보고하는 데이터의 일관성을 유지해야 합니다.

### 메시지 순서
<a name="message-ordering"></a>

 AWS IoT 서비스의 메시지가 특정 순서로 디바이스에 도착한다는 보장은 없습니다. 다음 시나리오는 이 경우에 어떤 일이 발생하는지 보여줍니다.

초기 상태 문서:

```
{
  "state": {
    "reported": {
      "color": "blue"
    }
  },
  "version": 9,
  "timestamp": 123456776
}
```

업데이트 1:

```
{
  "state": {
    "desired": {
      "color": "RED"
    }
  },
  "version": 10,
  "timestamp": 123456777
}
```

업데이트 2:

```
{
  "state": {
    "desired": {
      "color": "GREEN"
    }
  },
  "version": 11,
  "timestamp": 123456778
}
```

최종 상태 문서:

```
{
  "state": {
    "reported": {
      "color": "GREEN"
    }
  },
  "version": 12,
  "timestamp": 123456779
}
```

이로 인해 델타 메시지 2개가 생성됩니다.

```
{
  "state": {
    "color": "RED"
  },
  "version": 11,
  "timestamp": 123456778
}
```

```
{
  "state": {
    "color": "GREEN"
  },
  "version": 12,
  "timestamp": 123456779
}
```

디바이스가 이들 메시지를 틀린 순서로 수신할 수도 있습니다. 이들 메시지에서의 상태는 누적적이므로 디바이스는 현재 추적 중인 것보다 빠른 버전 번호는 무시할 수 있습니다. 디바이스가 버전 11보다 먼저 버전 12의 델타를 수신할 경우 버전 11 메시지는 무시할 수 있습니다.

### 섀도우 메시지 트리밍
<a name="device-shadow-trim-messages"></a>

디바이스로 전송되는 섀도우 메시지의 크기를 줄이려면 디바이스에 필요한 필드만 선택하고 디바이스가 수신 대기하는 MQTT 주제에 메시지를 다시 게시하는 규칙을 정의합니다.

이 규칙은 JSON 형식으로 지정되며 다음과 같아야 합니다.

```
{
  "sql": "SELECT state, version FROM '$aws/things/+/shadow/update/delta'",
  "ruleDisabled": false,
  "actions": [
    {
      "republish": {
        "topic": "${topic(3)}/delta",
        "roleArn": "arn:aws:iam:123456789012:role/my-iot-role"
      }
    }
  ]
}
```

SELECT 문은 메시지 가운데 지정된 주제로 재게시할 필드를 결정합니다. "\$1" 와일드 카드는 모든 섀도우 이름과 일치시키는 데 사용됩니다. 이 규칙은 모든 일치하는 메시지를 지정된 주제로 재게시하도록 지정합니다. 메시지를 재게시할 주제를 지정하는 데는 `"topic()"` 함수가 사용됩니다. `topic(3)`은 원래 주제의 사물 이름으로 평가됩니다. 규칙 생성에 대한 자세한 내용은 [에 대한 규칙 AWS IoT](iot-rules.md) 단원을 참조하세요.

# 디바이스에서 섀도우 사용
<a name="device-shadow-comms-device"></a>

이 섹션에서는 디바이스가 디바이스 섀도우 서비스와 통신하는 데 선호되는 방법인 MQTT 메시지를 사용한 섀도우와의 AWS IoT 디바이스 통신에 대해 설명합니다.

섀도우 통신은 MQTT의 게시/구독 통신 모델을 사용하여 요청/응답 모델을 에뮬레이트합니다. 모든 섀도우 작업은 요청 주제, 성공한 응답 주제(`accepted`) 및 오류 응답 주제(`rejected`)로 구성됩니다.

앱 및 서비스에서 디바이스가 연결되어 있는지 여부를 확인할 수 있도록 하려면 [디바이스 연결 상태 감지](device-shadow-comms-app.md#thing-connection) 단원을 참조하세요.

**중요**  
MQTT는 게시/구독 통신 모델을 사용하기 때문에 요청 주제를 게시하기 *전*에 응답 주제를 구독해야 합니다. 그렇지 않으면 게시한 요청에 대한 응답을 받지 못합니다.  
[AWS IoT Device SDK](iot-sdks.md)를 사용하여 디바이스 섀도우 서비스 API를 호출하면 이 작업이 자동으로 처리됩니다.

이 섹션의 예에서는 이 표에 설명된 대로 *ShadowTopicPrefix*가 명명된 섀도우 또는 명명되지 않은 섀도우를 참조할 수 있는 주제의 축약 형식을 사용합니다.

섀도우는 명명되거나 명명되지 않을(클래식) 수 있습니다. 각 섀도우에 사용되는 주제는 주제 접두사만 다릅니다. 이 표에서는 각 섀도우 유형에서 사용하는 주제 접두사를 보여줍니다.


| *ShadowTopicPrefix* 값 | 섀도우 유형 | 
| --- | --- | 
| \$1aws/things/thingName/shadow | 명명되지 않은(클래식) 섀도우 | 
| \$1aws/things/thingName/shadow/name/shadowName | 명명된 섀도우 | 

**중요**  
앱 또는 서비스의 섀도우 사용이 일관되고 디바이스의 해당 구현에 의해 지원되는지 확인합니다. 예를 들어 섀도우가 생성, 업데이트 및 삭제되는 방법을 고려합니다. 또한 디바이스와, 섀도우를 통해 해당 디바이스에 액세스하는 앱 또는 서비스에서 업데이트가 처리되는 방식을 고려합니다. 디바이스의 상태가 업데이트되고 보고되는 방식과 앱 및 서비스가 디바이스 및 섀도우와 상호 작용하는 방식에 대한 설계가 명확해야 합니다.

전체 주제를 생성하려면 참조할 섀도우 유형에 대해 `ShadowTopicPrefix`를 선택하고 `thingName` 및 `shadowName`(해당하는 경우)을 해당 값으로 바꾸고 다음 표에 표시된 대로 주제 스텁을 추가합니다. 주제는 대/소문자를 구분합니다.

섀도우에 대해 예약된 주제에 대한 자세한 내용은 [섀도우 주제](reserved-topics.md#reserved-topics-shadow) 단원을 참조하세요.

## 에 처음 연결할 때 디바이스 초기화 AWS IoT
<a name="device-shadow-comms-device-first-connect"></a>

디바이스가에 등록한 후에는 지원하는 섀도우에 대해 이러한 MQTT 메시지를 구독 AWS IoT해야 합니다.


| Topic | 의미 | 이 주제를 수신할 때 디바이스가 수행해야 하는 작업 | 
| --- | --- | --- | 
|  `ShadowTopicPrefix/delete/accepted`  |  `delete` 요청이 수락되고 섀도우가 AWS IoT 삭제되었습니다.  |  삭제된 섀도우를 수용하는 데 필요한 작업(예: 업데이트 게시 중지)  | 
|  `ShadowTopicPrefix/delete/rejected`  |  에서 `delete` 요청을 거부 AWS IoT 했으며 섀도우가 삭제되지 않았습니다. 메시지 본문에 오류 정보가 포함되어 있습니다.  |  메시지 본문의 오류 메시지에 대한 응답  | 
|  `ShadowTopicPrefix/get/accepted`  |  에서 `get` 요청을 수락 AWS IoT했으며 메시지 본문에 현재 섀도우 문서가 포함되어 있습니다.  |  메시지 본문에서 상태 문서를 처리하는 데 필요한 작업  | 
|  `ShadowTopicPrefix/get/rejected`  |  에서 `get` 요청을 거부 AWS IoT했으며 메시지 본문에 오류 정보가 포함되어 있습니다.  |  메시지 본문의 오류 메시지에 대한 응답  | 
|  `ShadowTopicPrefix/update/accepted`  |  에서 `update` 요청을 수락 AWS IoT했으며 메시지 본문에 현재 섀도우 문서가 포함되어 있습니다.  |  메시지 본문의 업데이트된 데이터가 디바이스 상태와 일치하는지 확인  | 
|  `ShadowTopicPrefix/update/rejected`  |  에서 `update` 요청을 거부 AWS IoT했으며 메시지 본문에 오류 정보가 포함되어 있습니다.  |  메시지 본문의 오류 메시지에 대한 응답  | 
|  `ShadowTopicPrefix/update/delta`  |  에 대한 요청에 의해 섀도우 문서가 업데이트되었으며 메시지 본문 AWS IoT에 요청된 변경 사항이 포함되어 있습니다.  |  메시지 본문의 원하는 상태와 일치하도록 디바이스의 상태 업데이트  | 
|  `ShadowTopicPrefix/update/documents`  |  섀도우 업데이트가 최근에 완료되었으며 메시지 본문에 현재 섀도우 문서가 포함되어 있습니다.  |  메시지 본문의 업데이트된 상태가 디바이스의 상태와 일치하는지 확인  | 

각 섀도우에 대해 위 표의 메시지를 구독한 후 디바이스는 각 섀도우에 `/get` 주제를 게시하여 지원하는 섀도우가 이미 생성되었는지 테스트해야 합니다. `/get/accepted` 메시지가 수신되면 메시지 본문에 섀도우 문서가 포함되며, 디바이스에서 이 문서를 사용하여 해당 상태를 초기화할 수 있습니다. `/get/rejected` 메시지가 수신되면 현재 디바이스 상태와 함께 `/update` 메시지를 게시하여 섀도우를 생성해야 합니다.

예를 들어, 클래식 섀도우나 명명된 섀도우가 없는 사물 `My_IoT_Thing`이 있다고 가정합니다. 이제 예약된 주제 `$aws/things/My_IoT_Thing/shadow/get`에 대한 `/get` 요청을 게시하면 사물에 섀도우가 없기 때문에 `$aws/things/My_IoT_Thing/shadow/get/rejected` 주제에 대한 오류가 반환됩니다. 이 오류를 해결하려면 먼저 다음 페이로드와 같은 현재 디바이스 상태를 포함하는 `$aws/things/My_IoT_Thing/shadow/update` 주제를 사용하여 `/update` 메시지를 게시합니다.

```
{
	"state": {
		"reported": {
			"welcome": "aws-iot",
			"color": "yellow"
		}
	}
}
```

이제 사물에 대한 클래식 섀도우가 생성되고 메시지가 `$aws/things/My_IoT_Thing/shadow/update/accepted` 주제에 게시됩니다. 주제 `$aws/things/My_IoT_Thing/shadow/get`에 게시하는 경우 디바이스 상태와 함께 `$aws/things/My_IoT_Thing/shadow/get/accepted` 주제에 대한 응답이 반환됩니다.

명명된 섀도우의 경우 get 요청을 사용하기 전에 먼저 명명된 섀도우를 생성하거나 섀도우 이름이 포함된 업데이트를 게시해야 합니다. 예를 들어 명명된 섀도우 `namedShadow1`을 생성하려면 먼저 디바이스 상태 정보를 주제 `$aws/things/My_IoT_Thing/shadow/name/namedShadow1/update`에 게시합니다. 상태 정보를 검색하려면 명명된 섀도우 `$aws/things/My_IoT_Thing/shadow/name/namedShadow1/get`에 대한 `/get` 요청을 사용합니다.

## 디바이스가 연결되어 있는 동안 메시지 처리 AWS IoT
<a name="device-shadow-comms-device-while-connected"></a>

디바이스가 연결되어 있는 동안 **/update/delta** 메시지를 수신할 AWS IoT수 있으며 다음을 통해 디바이스 상태를 섀도우의 변경 사항과 일치해야 합니다.

1. 수신된 모든 **/update/delta** 메시지를 읽고 일치하도록 디바이스 상태를 동기화합니다.

1. 디바이스의 상태가 변경될 때마다 디바이스의 현재 상태가 포함된 `reported` 메시지 본문과 함께 **/update** 메시지 게시.

디바이스가 연결되어 있는 동안 표시된 경우 이러한 메시지를 게시해야 합니다.


| 표시 | Topic | Payload | 
| --- | --- | --- | 
|  디바이스의 상태가 변경되었습니다.  |  `ShadowTopicPrefix/update`  |  `reported` 속성이 있는 섀도우 문서  | 
| 디바이스가 섀도우와 동기화되지 않았을 수 있습니다. |  `ShadowTopicPrefix/get`  | (비어 있음) | 
|  디바이스에 대한 작업은 디바이스가 제거되거나 교체되는 경우와 같이 디바이스에서 더 이상 섀도우를 지원하지 않음을 나타냅니다.  |  `ShadowTopicPrefix/delete`  | (비어 있음) | 

## 디바이스가에 다시 연결될 때 메시지 처리 AWS IoT
<a name="device-shadow-comms-device-reconnect"></a>

하나 이상의 섀도우가 있는 디바이스가 연결되면 다음을 통해 지원하는 모든 섀도우의 상태와 동기화 AWS IoT해야 합니다.

1. 수신된 모든 **/update/delta** 메시지를 읽고 일치하도록 디바이스 상태를 동기화합니다.

1. 디바이스의 현재 상태가 포함된 `reported` 메시지 본문과 함께 **/update** 메시지 게시.

# 앱 및 서비스에서 섀도우 사용
<a name="device-shadow-comms-app"></a>

이 섹션에서는 앱 또는 서비스가 AWS IoT 디바이스 섀도우 서비스와 상호 작용하는 방법을 설명합니다. 이 예에서는 앱 또는 서비스가 섀도우만 대상으로 상호 작용하거나 섀도우를 통해 디바이스만 대상으로 상호 작용한다고 가정합니다. 이 예에는 섀도우 생성 또는 삭제와 같은 관리 작업이 포함되지 않습니다.

이 예제에서는 AWS IoT 디바이스 섀도우 서비스의 REST API를 사용하여 섀도우와 상호 작용합니다. 게시/구독 통신 모델을 사용하는 [디바이스에서 섀도우 사용](device-shadow-comms-device.md)의 예제와 달리, 이 예제에서는 REST API의 요청/응답 통신 모델을 사용합니다. 즉, 앱 또는 서비스가 요청을 해야 응답을 받을 수 있습니다 AWS IoT. 그러나 이 모델의 단점은 알림을 지원하지 않는다는 것입니다. 앱 또는 서비스에서 디바이스 상태 변경에 대한 시기 적절한 알림이 필요한 경우 [디바이스에서 섀도우 사용](device-shadow-comms-device.md)에 설명된 대로 게시/구독 통신 모델을 지원하는 MQTT 또는 MQTT over WSS 프로토콜을 고려하세요.

**중요**  
앱 또는 서비스의 섀도우 사용이 일관되고 디바이스의 해당 구현에 의해 지원되는지 확인합니다. 예를 들어, 섀도우를 생성, 업데이트 및 삭제하는 방법과 디바이스 및 섀도우에 액세스하는 앱 또는 서비스에서 업데이트가 처리되는 방법을 고려합니다. 디바이스의 상태가 업데이트되고 보고되는 방식과 앱 및 서비스가 디바이스 및 섀도우와 상호 작용하는 방식에 대한 설계가 명확해야 합니다.

명명된 섀도우에 대한 REST API의 URL은 다음과 같습니다.

```
https://endpoint/things/thingName/shadow?name=shadowName
```

또한 명명되지 않은 섀도우에 대한 REST API의 URL은 다음과 같습니다.

```
https://endpoint/things/thingName/shadow
```

여기서 각 항목은 다음과 같습니다.

엔드포인트  
CLI 명령에 의해 반환된 엔드포인트는 다음과 같습니다.  

```
aws iot describe-endpoint --endpoint-type IOT:Data-ATS
```

thingName  
섀도우가 속한 사물 객체의 이름입니다.

shadowName  
명명된 섀도우의 이름입니다. 이 파라미터는 명명되지 않은 섀도우와 함께 사용되지 않습니다.

## 에 연결할 때 앱 또는 서비스 초기화 AWS IoT
<a name="device-shadow-comms-app-first-connect"></a>

앱이 처음 연결되면 사용 중인 섀도우의 현재 상태를 가져오는 데 사용하는 섀도우의 URLs로 HTTP GET 요청을 보내야 AWS IoT합니다. 이를 통해 앱이나 서비스를 섀도우와 동기화할 수 있습니다.

## 앱 또는 서비스가에 연결되어 있는 동안 처리 상태 변경 AWS IoT
<a name="device-shadow-comms-app-while-connected"></a>

앱 또는 서비스가 연결되어 있는 동안 사용하는 섀도우의 URLs에 HTTP GET 요청을 전송하여 현재 상태를 주기적으로 쿼리할 AWS IoT수 있습니다.

최종 사용자가 앱 또는 서비스와 상호 작용하여 디바이스의 상태를 변경하는 경우 앱이나 서비스는 섀도우의 `desired` 상태를 업데이트하는 데 사용되는 섀도우의 URL로 HTTP POST 요청을 전송할 수 있습니다. 이 요청은 허용된 변경 사항을 반환하지만 디바이스가 새 상태로 섀도우를 업데이트할 때까지 HTTP GET 요청을 만들어 섀도우를 폴링해야 할 수 있습니다.

## 디바이스 연결 상태 감지
<a name="thing-connection"></a>

현재 디바이스가 연결되어 있는지 확인하려면 섀도우 문서에 `connected` 속성을 포함시키고 MQTT LWT(Last Will and Testament) 메시지를 사용하세요. 이 메시지는 디바이스가 오류로 인해 연결 해제될 경우 `connected` 속성을 `false`로 설정합니다.

**참고**  
 AWS IoT 예약된 주제(\$1로 시작하는 주제)로 전송된 MQTT LWT 메시지는 AWS IoT 디바이스 섀도우 서비스에서 무시됩니다. 그러나 구독한 클라이언트와 AWS IoT 규칙 엔진에서 처리하므로 예약되지 않은 주제로 전송되는 LWT 메시지와 MQTT LWT 메시지를 섀도우의 예약된 업데이트 주제인에 섀도우 업데이트 메시지로 다시 게시하는 규칙을 생성해야 합니다`ShadowTopicPrefix/update`.

**디바이스 섀도우 서비스에 LWT 메시지를 전송하려면**

1. 예약된 주제에 대해 MQTT LWT 메시지를 재게시하는 규칙을 생성합니다. 다음 예는 `my/things/myLightBulb/update` 주제에 대한 메시지를 수신하고 `$aws/things/myLightBulb/shadow/update`에 재게시하는 규칙입니다.

   ```
   {
       "rule": {
       "ruleDisabled": false,
       "sql": "SELECT * FROM 'my/things/myLightBulb/update'",
       "description": "Turn my/things/ into $aws/things/",
       "actions": [
           {
           "republish": {
               "topic": "$$aws/things/myLightBulb/shadow/update",
               "roleArn": "arn:aws:iam:123456789012:role/aws_iot_republish"
               }
           }
        ]
      }
   }
   ```

1. 디바이스가 연결되면 재게시 규칙이 인식할 수 있도록 예약되지 않은 주제에 LWT 메시지를 AWS IoT등록합니다. 이 예제에서 해당 주제는 `my/things/myLightBulb/update`이고 연결된 속성을 `false`로 설정합니다.

   ```
   {
       "state": {        
           "reported": {
               "connected":"false"
           }
       }
   }
   ```

1. 연결 후 디바이스는 섀도우 업데이트 주제인 `$aws/things/myLightBulb/shadow/update`에 메시지를 게시하여 `connected` 속성을 `true`로 설정하는 등 현재 상태를 보고합니다.

   ```
   {
        "state": {        
           "reported": {
               "connected":"true"
           }
       }
   }
   ```

1. 디바이스가 정상적으로 연결 해제되기 전에, 섀도우 업데이트 주제인 `$aws/things/myLightBulb/shadow/update`에 메시지를 게시하여 `connected` 속성을 `false`로 설정하는 등 최신 상태를 보고합니다.

   ```
   {
       "state": {        
           "reported": {
               "connected":"false"
           }
       }
   }
   ```

1. 오류로 인해 디바이스 연결이 끊어지면 AWS IoT 메시지 브로커가 디바이스를 대신하여 디바이스의 LWT 메시지를 게시합니다. 재게시 규칙은 이 메시지를 감지하고 섀도우 업데이트 메시지를 게시하여 디바이스 섀도우의 `connected` 속성을 업데이트합니다.

**참고**  
연결 해제 처리의 비동기적 특성으로 인해 LWT 메시지는 재연결 중에 순서대로 디스패치되지 않습니다. [수명 주기 이벤트](life-cycle-events.md)를 사용하여 연결 상태 감지의 정확도를 높이는 것이 좋습니다. 이러한 이벤트는 out-of-order 이벤트를 관리하는 속성을 제공하기 때문입니다.

# 디바이스 섀도우 서비스 통신 시뮬레이션
<a name="using-device-shadows"></a>

이 주제에서는 디바이스 섀도우 서비스가 중개자 역할을 하는 방법을 보여 주며 디바이스 및 앱에서 섀도우를 사용하여 디바이스 상태를 업데이트, 저장 및 검색할 수 있도록 합니다.

이 주제에 설명된 상호 작용을 시연하고 자세히 살펴보려면 AWS 계정 및를 실행할 수 있는 시스템이 필요합니다 AWS CLI. 이러한 계정과 시스템이 없으면 코드 예제에서 상호 작용을 볼 수 있습니다.

이 예제에서 AWS IoT 콘솔은 디바이스를 나타냅니다. 는 섀도우를 통해 디바이스에 액세스하는 앱 또는 서비스를 AWS CLI 나타냅니다. AWS CLI 인터페이스는 앱이 통신에 사용할 수 있는 API와 매우 유사합니다 AWS IoT. 이 예제의 디바이스는 스마트 전구이며 앱은 전구의 상태를 표시하고 전구의 상태를 변경할 수 있습니다.

## 시뮬레이션 설정
<a name="using-device-shadows-setup"></a>

이 절차에서는 디바이스를 시뮬레이션하는 [AWS IoT 콘솔](https://console.aws.amazon.com/iot/home) 및 앱을 시뮬레이션하는 명령줄 창을 열어 시뮬레이션을 초기화합니다.

**시뮬레이션 환경을 설정하려면**

1. 이 주제의 예제를 직접 실행 AWS 계정 하려면이 필요합니다. 이 없는 경우에 설명된 대로 AWS 계정생성합니다[설정 AWS 계정](setting-up.md).

1. [AWS IoT 콘솔](https://console.aws.amazon.com/iot/home)을 열고 왼쪽 메뉴에서 **테스트**를 선택하여 **MQTT 클라이언트**를 엽니다.

1. 다른 창을 열고 AWS CLI 가 설치된 시스템에서 터미널 창을 엽니다.

두 개의 창이 열려 있어야 합니다. 하나는 **테스트** 페이지에 AWS IoT 콘솔이 있고 다른 하나는 명령줄 프롬프트가 있습니다.

## 디바이스 초기화
<a name="using-device-shadows-init-device"></a>

이 시뮬레이션에서는 *mySimulatedThing*이라는 이름의 사물 객체와 *simShadow1*이라는 해당 섀도우로 작업합니다.

**사물 객체 및 해당 IoT 정책 생성**  
사물을 생성하려면, **AWS IoT 콘솔**에서:

1. **관리(Manage)**를 선택한 후 **사물(Things)**을 선택합니다.

1. 사물이 나열되면 **생성** 버튼을 클릭합니다. 그렇지 않으면 **단일 사물 등록**을 클릭하여 단일 AWS IoT 사물을 생성합니다.

1. 이름 `mySimulatedThing`을 입력하고 다른 설정은 기본값으로 그대로 둔 채 **다음(Next)**을 클릭합니다.

1. 원 클릭 인증서 생성을 사용하여 AWS IoT에 대한 디바이스 연결을 인증할 인증서를 생성합니다. 인증서를 활성화하려면 **활성화(Activate)**를 클릭합니다.

1. MQTT 예약 주제를 게시 및 구독할 수 있는 권한을 디바이스에 부여하는 정책 `My_IoT_Policy`를 연결할 수 있습니다. AWS IoT 사물을 생성하는 방법과이 정책을 생성하는 방법에 대한 자세한 단계는 섹션을 참조하세요[사물 객체 만들기](create-iot-resources.md#create-aws-thing).

**사물 객체에 대한 명명된 섀도우 생성**  
아래에 설명된 대로 주제 `$aws/things/mySimulatedThing/shadow/name/simShadow1/update`에 업데이트 요청을 게시하여 사물에 대한 명명된 섀도우를 생성할 수 있습니다.

또는 명명된 섀도를 생성하려면:

1. **AWS IoT 콘솔**의 표시된 사물 목록에서 사물 객체를 선택한 다음 **섀도우(Shadows)**를 선택합니다.

1. **섀도우 추가(Add a shadow)**를 선택하고 이름 `simShadow1`을 입력한 다음 **생성(Create)**을 선택하여 명명된 섀도우를 추가합니다.

**예약된 MQTT 주제를 구독하고 주제에 게시**  
콘솔에서, 예약된 MQTT 섀도우 주제를 구독합니다. 이러한 주제는 `get`, `update` 및 `delete` 작업에 대한 응답으로, 디바이스에서 작업을 게시한 후 응답을 받을 수 있습니다.

****MQTT 클라이언트**에서 MQTT 주제를 구독하려면**

1. **MQTT 클라이언트(MQTT client)**에서 **주제 구독(Subscribe to a topic)**을 선택합니다.

1. 구독할 `get`, `update` 및 `delete` 주제를 입력합니다. 다음 목록에서 한 번에 하나의 주제를 복사하여 **주제 필터(Topic filter)** 필드에 붙여넣고 **구독(Subscribe)**을 클릭합니다. **구독(Subscriptions)** 아래에 주제가 표시되어야 합니다.
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/delete/accepted`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/delete/rejected`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/get/accepted`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/get/rejected`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/accepted`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/rejected`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/delta`
   + `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/documents`

   이 시점에서 시뮬레이션된 디바이스는 AWS IoT에서 게시하는 주제를 수신할 준비가 되었습니다.

****MQTT 클라이언트**에서 MQTT 주제에 게시하려면**  
디바이스가 자체적으로 초기화되고 응답 주제를 구독한 후에는 지원하는 섀도우를 쿼리해야 합니다. 이 시뮬레이션은 *mySimulatedThing*이라는 사물 객체를 지원하는 *simShadow1*이라는 이름의 섀도우 하나만 지원합니다.

****MQTT 클라이언트**에서 현재 섀도우 상태를 가져오려면**

1. **MQTT 클라이언트**에서 **주제에 게시(Publish to a topic)**를 선택합니다.

1. **게시(Publish)** 아래에서, 다음 주제를 입력하고 메시지 본문 창에서 가져올 주제의 입력 위치 아래에 있는 내용을 모두 삭제합니다. 그런 다음 **주제에 게시(Publish to topic)**를 선택하여 요청을 게시합니다. `$aws/things/mySimulatedThing/shadow/name/simShadow1/get`.

   명명된 섀도우 `simShadow1`을 생성하지 않은 경우, 섀도우가 생성되지 않았으므로 이 예제와 같이 `$aws/things/mySimulatedThing/shadow/name/simShadow1/get/rejected` 주제에 메시지가 수신되고 `code`는 `404`입니다. 이것을 다음에 생성하겠습니다.

   ```
   {
     "code": 404,
     "message": "No shadow exists with name: 'simShadow1'"
   }
   ```

**디바이스의 현재 상태로 섀도우를 생성하려면**

1. **MQTT 클라이언트**에서, **주제에 게시(Publish to a topic)**를 선택하여 다음 주제를 입력합니다.

   ```
   $aws/things/mySimulatedThing/shadow/name/simShadow1/update
   ```

1. 메시지 본문 창에서 주제의 입력 위치 아래에 다음 섀도우 문서를 입력하여 디바이스가 해당 ID와 현재 색상(RGB 값)을 보고하고 있음을 표시합니다. **게시(Publish)**를 선택하여 요청을 게시합니다.

   ```
   {
     "state": {
       "reported": {
         "ID": "SmartLamp21",
         "ColorRGB": [
           128,
           128,
           128
         ]
       }
     },
     "clientToken": "426bfd96-e720-46d3-95cd-014e3ef12bb6"
   }
   ```

다음 주제에서 메시지를 수신한 경우: 
+ `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/accepted`: 섀도우가 생성되고 메시지 본문에 현재 섀도우 문서가 포함되어 있음을 의미합니다.
+ `$aws/things/mySimulatedThing/shadow/name/simShadow1/update/rejected`: 메시지 본문의 오류를 검토합니다.
+ `$aws/things/mySimulatedThing/shadow/name/simShadow1/get/accepted`: 섀도우가 이미 존재하며 메시지 본문에 다음 예와 같은 현재 섀도우 상태가 포함됩니다. 이를 통해 디바이스를 설정하거나 섀도우 상태와 일치하는지 확인할 수 있습니다.

  ```
  {
    "state": {
      "reported": {
        "ID": "SmartLamp21",
        "ColorRGB": [
          128,
          128,
          128
        ]
      }
    },
    "metadata": {
      "reported": {
        "ID": {
          "timestamp": 1591140517
        },
        "ColorRGB": [
          {
            "timestamp": 1591140517
          },
          {
            "timestamp": 1591140517
          },
          {
            "timestamp": 1591140517
          }
        ]
      }
    },
    "version": 3,
    "timestamp": 1591140517,
    "clientToken": "426bfd96-e720-46d3-95cd-014e3ef12bb6"
  }
  ```

## 앱에서 업데이트 전송하기
<a name="using-device-shadows-app-update"></a>

이 섹션에서는 AWS CLI 를 사용하여 앱이 섀도우와 상호 작용하는 방법을 보여줍니다.

**를 사용하여 섀도우의 현재 상태를 가져오려면 AWS CLI**  
명령줄에서 다음 명령을 입력합니다.

```
aws iot-data get-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 /dev/stdout
```

Windows 플랫폼에서는 `/dev/stdout` 대신 `con`을 사용할 수 있습니다.

```
aws iot-data get-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 con
```

섀도우가 존재하고 현재 상태를 반영하기 위해 디바이스에 의해 초기화되었기 때문에 다음 섀도우 문서를 반환해야 합니다.

```
{
  "state": {
    "reported": {
      "ID": "SmartLamp21",
      "ColorRGB": [
        128,
        128,
        128
      ]
    }
  },
  "metadata": {
    "reported": {
      "ID": {
        "timestamp": 1591140517
      },
      "ColorRGB": [
        {
          "timestamp": 1591140517
        },
        {
          "timestamp": 1591140517
        },
        {
          "timestamp": 1591140517
        }
      ]
    }
  },
  "version": 3,
  "timestamp": 1591141111
}
```

앱은 이 응답을 사용하여 디바이스 상태의 표현을 초기화할 수 있습니다.

앱이 상태를 업데이트하면(예: 최종 사용자가 스마트 전구의 색상을 노란색으로 변경한 경우) 앱에서 **update-thing-shadow** 명령을 전송합니다. 이 명령은 `UpdateThingShadow` REST API에 해당합니다.

**앱에서 섀도우를 업데이트하려면**  
명령줄에서 다음 명령을 입력합니다.

------
#### [ AWS CLI v2.x ]

```
aws iot-data update-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 \
    --cli-binary-format raw-in-base64-out \
    --payload '{"state":{"desired":{"ColorRGB":[255,255,0]}},"clientToken":"21b21b21-bfd2-4279-8c65-e2f697ff4fab"}' /dev/stdout
```

------
#### [ AWS CLI v1.x ]

```
aws iot-data update-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 \
    --payload '{"state":{"desired":{"ColorRGB":[255,255,0]}},"clientToken":"21b21b21-bfd2-4279-8c65-e2f697ff4fab"}' /dev/stdout
```

------

성공한 경우 이 명령은 다음 섀도우 문서를 반환해야 합니다.

```
{
  "state": {
    "desired": {
      "ColorRGB": [
        255,
        255,
        0
      ]
    }
  },
  "metadata": {
    "desired": {
      "ColorRGB": [
        {
          "timestamp": 1591141596
        },
        {
          "timestamp": 1591141596
        },
        {
          "timestamp": 1591141596
        }
      ]
    }
  },
  "version": 4,
  "timestamp": 1591141596,
  "clientToken": "21b21b21-bfd2-4279-8c65-e2f697ff4fab"
}
```

## 디바이스의 업데이트에 응답
<a name="using-device-shadows-device-update"></a>

 AWS 콘솔에서 **MQTT 클라이언트**로 돌아가면 이전 섹션에서 실행된 업데이트 명령을 반영하기 위해가 AWS IoT 게시한 메시지가 표시됩니다.

****MQTT 클라이언트**에서 업데이트 메시지를 보려면**  
**MQTT 클라이언트**의 **구독(Subscriptions)** 열에서 **\$1aws/things/mySimulatedThing/shadow/name/simShadow1/update/delta**를 선택합니다. 주제 이름이 잘리는 경우 커서를 그 위에 잠시 두면 전체 주제 이름이 표시됩니다. 이 주제의 주제 로그에 다음과 유사한 `/delta` 메시지가 표시되어야 합니다.

```
{
  "version": 4,
  "timestamp": 1591141596,
  "state": {
    "ColorRGB": [
      255,
      255,
      0
    ]
  },
  "metadata": {
    "ColorRGB": [
      {
        "timestamp": 1591141596
      },
      {
        "timestamp": 1591141596
      },
      {
        "timestamp": 1591141596
      }
    ]
  },
  "clientToken": "21b21b21-bfd2-4279-8c65-e2f697ff4fab"
}
```

디바이스에서 이 메시지의 콘텐츠를 처리하여 디바이스 상태를 메시지의 `desired` 상태와 일치하도록 설정합니다.

디바이스가 메시지의 상태와 일치하도록 `desired` 상태를 업데이트한 후에는 업데이트 메시지를 게시 AWS IoT 하여 새로 보고된 상태를 로 다시 보내야 합니다. 이 절차는 **MQTT 클라이언트**에서 시뮬레이션합니다.

**디바이스에서 섀도우를 업데이트하려면**

1. **MQTT 클라이언트**에서 **주제에 게시(Publish to a topic)**를 선택합니다.

1. 메시지 본문 창에서 메시지 본문 창 위의 주제 필드에 섀도우의 주제와 `/update` 작업: `$aws/things/mySimulatedThing/shadow/name/simShadow1/update`를 입력하고 메시지 본문에 디바이스의 현재 상태를 설명하는 다음과 같은 업데이트된 섀도우 문서를 입력합니다. **게시(Publish)**를 클릭하여 업데이트된 디바이스 상태를 게시합니다.

   ```
   {
     "state": {
       "reported": {
         "ColorRGB": [255,255,0]
         }
     },
     "clientToken": "a4dc2227-9213-4c6a-a6a5-053304f60258"
   }
   ```

   에서 메시지를 성공적으로 수신한 경우이 예제와 같이 **MQTT 클라이언트**의 **\$1aws/things/mySimulatedThing/shadow/name/simShadow1/update/accepted** 메시지 로그에 현재 섀도우 상태가 포함된 새 응답이 AWS IoT표시됩니다.

   ```
   {
     "state": {
       "reported": {
         "ColorRGB": [
           255,
           255,
           0
         ]
       }
     },
     "metadata": {
       "reported": {
         "ColorRGB": [
           {
             "timestamp": 1591142747
           },
           {
             "timestamp": 1591142747
           },
           {
             "timestamp": 1591142747
           }
         ]
       }
     },
     "version": 5,
     "timestamp": 1591142747,
     "clientToken": "a4dc2227-9213-4c6a-a6a5-053304f60258"
   }
   ```

또한 디바이스의 보고된 상태를 성공적으로 업데이트하면 AWS IoT 가 이전 절차에서 디바이스가 수행한 섀도우 업데이트로 인해 발생한이 메시지 본문과 같은 메시지의 섀도우 상태에 대한 포괄적인 설명을 `update/documents` 주제에 전송합니다.

```
{
  "previous": {
    "state": {
      "desired": {
        "ColorRGB": [
          255,
          255,
          0
        ]
      },
      "reported": {
        "ID": "SmartLamp21",
        "ColorRGB": [
          128,
          128,
          128
        ]
      }
    },
    "metadata": {
      "desired": {
        "ColorRGB": [
          {
            "timestamp": 1591141596
          },
          {
            "timestamp": 1591141596
          },
          {
            "timestamp": 1591141596
          }
        ]
      },
      "reported": {
        "ID": {
          "timestamp": 1591140517
        },
        "ColorRGB": [
          {
            "timestamp": 1591140517
          },
          {
            "timestamp": 1591140517
          },
          {
            "timestamp": 1591140517
          }
        ]
      }
    },
    "version": 4
  },
  "current": {
    "state": {
      "desired": {
        "ColorRGB": [
          255,
          255,
          0
        ]
      },
      "reported": {
        "ID": "SmartLamp21",
        "ColorRGB": [
          255,
          255,
          0
        ]
      }
    },
    "metadata": {
      "desired": {
        "ColorRGB": [
          {
            "timestamp": 1591141596
          },
          {
            "timestamp": 1591141596
          },
          {
            "timestamp": 1591141596
          }
        ]
      },
      "reported": {
        "ID": {
          "timestamp": 1591140517
        },
        "ColorRGB": [
          {
            "timestamp": 1591142747
          },
          {
            "timestamp": 1591142747
          },
          {
            "timestamp": 1591142747
          }
        ]
      }
    },
    "version": 5
  },
  "timestamp": 1591142747,
  "clientToken": "a4dc2227-9213-4c6a-a6a5-053304f60258"
}
```

## 앱에서 업데이트 관찰
<a name="using-device-shadows-view-result"></a>

이제 앱이 디바이스에서 보고한 대로 섀도우에 현재 상태를 쿼리할 수 있습니다.

**를 사용하여 섀도우의 현재 상태를 가져오려면 AWS CLI**

1. 명령줄에서 다음 명령을 입력합니다.

   ```
   aws iot-data get-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 /dev/stdout
   ```

   Windows 플랫폼에서는 `/dev/stdout` 대신 `con`을 사용할 수 있습니다.

   ```
   aws iot-data get-thing-shadow --thing-name mySimulatedThing --shadow-name simShadow1 con
   ```

1. 현재 상태를 반영하기 위해 디바이스에 의해 섀도우가 방금 업데이트되었기 때문에 다음 섀도우 문서를 반환해야 합니다.

   ```
   {
     "state": {
       "desired": {
         "ColorRGB": [
           255,
           255,
           0
         ]
       },
       "reported": {
         "ID": "SmartLamp21",
         "ColorRGB": [
           255,
           255,
           0
         ]
       }
     },
     "metadata": {
       "desired": {
         "ColorRGB": [
           {
             "timestamp": 1591141596
           },
           {
             "timestamp": 1591141596
           },
           {
             "timestamp": 1591141596
           }
         ]
       },
       "reported": {
         "ID": {
           "timestamp": 1591140517
         },
         "ColorRGB": [
           {
             "timestamp": 1591142747
           },
           {
             "timestamp": 1591142747
           },
           {
             "timestamp": 1591142747
           }
         ]
       }
     },
     "version": 5,
     "timestamp": 1591143269
   }
   ```

## 시뮬레이션 이후의 작업
<a name="using-device-shadows-next-steps"></a>

 AWS CLI (앱을 나타냄)와 콘솔(디바이스를 나타냄) 사이의 상호 작용을 실험하여 IoT 솔루션을 모델링합니다.

# 섀도우와의 상호 작용
<a name="device-shadow-data-flow"></a>

이 주제에서는 섀도우 작업을 위해 AWS IoT 에서 제공하는 세 가지 메서드와 관련된 메시지에 대해 설명합니다. 이러한 메서드는 다음과 같습니다.

`UPDATE`  <a name="update"></a>
섀도우가 없는 경우 섀도우를 생성하거나, 메시지 본문에 제공된 상태 정보로 기존 섀도우의 콘텐츠를 업데이트합니다. AWS IoT 는 각 업데이트와 함께 타임스탬프를 기록하여 상태가 마지막으로 업데이트된 시점을 나타냅니다. 섀도우의 상태가 변경되면는 `desired`와 `reported` 상태 간의 차이가 있는 `/delta` 메시지를 모든 MQTT 구독자에게 AWS IoT 보냅니다. `/delta` 메시지를 수신한 디바이스 또는 앱은 차이에 따라 작업을 수행할 수 있습니다. 예를 들어 디바이스가 원하는 상태로 업데이트할 수도 있고, 앱이 디바이스의 상태 변경을 반영하도록 UI를 업데이트할 수도 있습니다.

`GET`  <a name="get"></a>
메타데이터를 포함하여 섀도우의 전체 상태가 포함된 현재 섀도우 문서를 검색합니다.

`DELETE`  <a name="delete"></a>
디바이스 섀도우와 해당 콘텐츠를 삭제합니다.  
삭제된 디바이스 섀도우 문서는 복원할 수 없지만 삭제된 디바이스 섀도우 문서의 이름으로 새 디바이스 섀도우를 생성할 수 있습니다. 지난 48시간 이내에 삭제된 것과 동일한 이름의 디바이스 섀도우 문서를 생성하는 경우 새 디바이스 섀도우 문서의 버전 번호는 삭제된 문서의 버전 번호를 따릅니다. 디바이스 섀도우 문서가 48시간 이상 삭제된 경우 동일한 이름을 가진 새 디바이스 섀도우 문서의 버전 번호는 0이 됩니다.

## 프로토콜 지원
<a name="protocol-support"></a>

AWS IoT 는 섀도우와 상호 작용하기 위해 HTTPS 프로토콜을 통한 [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html) 및 REST API를 지원합니다.는 MQTT 게시 및 구독 작업에 대한 예약 요청 및 응답 주제 세트를 AWS IoT 제공합니다. 디바이스와 앱은 요청 주제를 게시하기 전에 응답 주제를 구독하여에서 요청을 AWS IoT 처리하는 방법에 대한 정보를 확인해야 합니다. 자세한 내용은 [디바이스 섀도우 MQTT 주제](device-shadow-mqtt.md) 및 [디바이스 섀도우 REST API](device-shadow-rest-api.md) 섹션을 참조하세요.

## 상태 요청 및 보고
<a name="shadow-reporting-state"></a>

 AWS IoT 및 섀도우를 사용하여 IoT 솔루션을 설계할 때는 변경을 요청할 앱 또는 디바이스와 이를 구현할 앱을 결정해야 합니다. 일반적으로 디바이스는 변경 사항을 구현하고 섀도우에 다시 보고하며, 앱과 서비스는 섀도우에 응답하고 변경을 요청합니다. 솔루션은 다를 수 있지만 이 주제의 예에서는 클라이언트 앱 또는 서비스가 섀도우의 변경을 요청하고 디바이스가 변경을 수행하며 이를 섀도우에 다시 보고한다고 가정합니다.

## 섀도우 업데이트
<a name="update-device-shadow"></a>

앱이나 서비스는 [UpdateThingShadow](device-shadow-rest-api.md#API_UpdateThingShadow) API를 사용하거나 [/update](device-shadow-mqtt.md#update-pub-sub-topic) 주제에 게시하여 섀도우의 상태를 업데이트할 수 있습니다. 업데이트는 요청에 지정된 필드에만 영향을 미칩니다.

### 클라이언트가 상태 변경을 요청할 때 섀도우 업데이트
<a name="update-pub-sub-topic-client"></a>

**클라이언트가 MQTT 프로토콜을 사용하여 섀도우의 상태 변경을 요청하는 경우**

1. 클라이언트가 변경할 속성을 식별할 수 있도록 현재 섀도우 문서가 있어야 합니다. 현재 섀도우 문서를 가져오는 방법은 /get 작업을 참조하세요.

1. 클라이언트는 다음 MQTT 주제를 구독합니다.
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`
   + `$aws/things/thingName/shadow/name/shadowName/update/documents`

1. 클라이언트는 원하는 섀도우 상태를 포함하는 상태 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update` 요청 주제를 게시합니다. 변경할 속성만 문서에 포함시켜야 합니다. 다음은 원하는 상태의 문서에 대한 예입니다.

   ```
   {
     "state": {
       "desired": {
         "color": {
           "r": 10
         },
         "engine": "ON"
       }
     }
   }
   ```

1. 업데이트 요청이 유효한 경우는 섀도우에서 원하는 상태를 AWS IoT 업데이트하고 다음 주제에 메시지를 게시합니다.
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`

   `/update/accepted` 메시지에는 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서가 포함되어 있으며 `/update/delta` 메시지에는 [/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta) 섀도우 문서가 포함되어 있습니다.

1. 업데이트 요청이 유효하지 않은 경우는 오류를 설명하는 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json) 섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/rejected` 주제가 포함된 메시지를 AWS IoT 게시합니다.

**클라이언트가 API를 사용하여 섀도우에서 상태 변경을 요청하는 경우**

1. 클라이언트는 [요청 상태 문서](device-shadow-document.md#device-shadow-example-request-json) 상태 문서를 메시지 본문으로 사용하여 `UpdateThingShadow` API를 호출합니다.

1. 요청이 유효하면는 HTTP 성공 응답 코드와 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서를 응답 메시지 본문으로 AWS IoT 반환합니다.

   AWS IoT 또한는 구독하는 모든 디바이스 또는 클라이언트에 대한 [/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta) 섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/delta` 주제에 MQTT 메시지를 게시합니다.

1. 요청이 유효하지 않은 경우는 HTTP 오류 응답 코드를 응답 메시지 본문[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)으로 AWS IoT 반환합니다.

디바이스가 `/update/delta` 주제에 대한 `/desired` 상태를 수신하면 디바이스에서 원하는 변경을 수행합니다. 그런 다음 `/update` 주제에 메시지를 전송해 현재 상태를 섀도우에 보고합니다.

### 디바이스가 현재 상태를 보고할 때 섀도우 업데이트
<a name="update-pub-sub-topic-device"></a>

**디바이스가 MQTT 프로토콜을 사용하여 섀도우에 현재 상태를 보고하는 경우**

1. 디바이스는 섀도우를 업데이트하기 전에 다음 MQTT 주제를 구독해야 합니다.
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`
   + `$aws/things/thingName/shadow/name/shadowName/update/documents`

1. 디바이스는 이 예에서와 같이 현재 상태를 보고하는 `$aws/things/thingName/shadow/name/shadowName/update` 주제에 메시지를 게시하여 현재 상태를 보고합니다.

   ```
   {
       "state": {
           "reported" : {
               "color" : { "r" : 10 },
               "engine" : "ON"
           }
       }
   }
   ```

1. 가 업데이트를 AWS IoT 수락하면 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/accepted` 주제에 메시지를 게시합니다.

1. 업데이트 요청이 유효하지 않은 경우는 오류를 설명하는 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json) 섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/rejected` 주제가 포함된 메시지를 AWS IoT 게시합니다.

**디바이스가 API를 사용하여 섀도우에 현재 상태를 보고하는 경우**

1. 디바이스는 [요청 상태 문서](device-shadow-document.md#device-shadow-example-request-json) 상태 문서를 메시지 본문으로 사용하여 `UpdateThingShadow` API를 호출합니다.

1. 요청이 유효하면는 섀도우를 AWS IoT 업데이트하고 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서와 함께 HTTP 성공 응답 코드를 응답 메시지 본문으로 반환합니다.

   AWS IoT 또한는 구독하는 모든 디바이스 또는 클라이언트에 대한 [/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta) 섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/delta` 주제에 MQTT 메시지를 게시합니다.

1. 요청이 유효하지 않은 경우는 HTTP 오류 응답 코드를 응답 메시지 본문[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)으로 AWS IoT 반환합니다.

### 낙관적 잠금
<a name="optimistic-locking"></a>

상태 문서 버전을 사용하면 업데이트하는 디바이스 섀도우 문서가 최신 버전인지 확인할 수 있습니다. 업데이트 요청에 버전을 입력하면 상태 문서의 현재 버전이 입력된 버전과 일치하지 않을 경우 서비스가 HTTP 409 충돌 응답 코드를 포함하는 요청을 거부합니다. 충돌 응답 코드는 `DeleteThingShadow`를 포함하여 `ThingShadow`를 수정하는 API에서도 발생할 수 있습니다.

예제:

초기 문서:

```
{
  "state": {
    "desired": {
      "colors": [
        "RED",
        "GREEN",
        "BLUE"
      ]
    }
  },
  "version": 10
}
```

업데이트: (버전이 일치하지 않음, 이 요청이 거부됨)

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 9
}
```

결과:

```
{
  "code": 409,
  "message": "Version conflict",
  "clientToken": "426bfd96-e720-46d3-95cd-014e3ef12bb6"
}
```

업데이트: (버전이 일치함, 이 요청이 수락됨)

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 10
}
```

최종 상태:

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 11
}
```

## 섀도우 문서 검색
<a name="retrieving-device-shadow"></a>

[GetThingShadow](device-shadow-rest-api.md#API_GetThingShadow) API를 사용하거나 [/get](device-shadow-mqtt.md#get-pub-sub-topic) 주제에 대해 구독 및 게시하여 섀도우 문서를 검색할 수 있습니다. 그러면 `desired` 및 `reported` 상태 사이의 델타를 포함하여 전체 섀도우 문서가 검색됩니다. 이 작업의 절차는 요청하는 주체가 디바이스인지 클라이언트인지에 관계없이 동일합니다.

**MQTT 프로토콜을 사용하여 섀도우 문서를 검색하려면**

1. 디바이스 또는 클라이언트는 섀도우를 업데이트하기 전에 다음 MQTT 주제를 구독해야 합니다.
   + `$aws/things/thingName/shadow/name/shadowName/get/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/get/rejected`

1. 디바이스나 클라이언트는 메시지 본문이 비어 있는 메시지를 `$aws/things/thingName/shadow/name/shadowName/get` 주제에 게시합니다.

1. 요청이 성공하면는 메시지 본문에가 있는 `$aws/things/thingName/shadow/name/shadowName/get/accepted` 주제에 메시지를 AWS IoT 게시[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)합니다.

1. 요청이 유효하지 않은 경우는 메시지 본문에가 있는 `$aws/things/thingName/shadow/name/shadowName/get/rejected` 주제에 메시지를 AWS IoT 게시[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)합니다.

**REST API를 사용하여 섀도우 문서를 검색하려면**

1. 디바이스 또는 클라이언트는 빈 메시지 본문을 사용하여 `GetThingShadow` API를 호출합니다.

1. 요청이 유효한 경우는 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서가 포함된 HTTP 성공 응답 코드를 응답 메시지 본문으로 AWS IoT 반환합니다.

1. 요청이 유효하지 않은 경우는 HTTP 오류 응답 코드를 응답 메시지 본문[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)으로 AWS IoT 반환합니다.

## 섀도우 데이터 삭제
<a name="deleting-thing-data"></a>

섀도우 데이터를 삭제하는 방법에는 두 가지가 있습니다. 섀도우 문서에서 특정 속성을 삭제하거나 섀도우를 완전히 삭제할 수 있습니다.
+ 섀도우에서 특정 속성을 삭제하려면 삭제할 속성의 값을 `null`로 설정하여 섀도우를 업데이트합니다. 섀도우 문서에서 값이 `null`인 필드가 제거됩니다.
+ 전체 섀도우를 삭제하려면 [DeleteThingShadow](device-shadow-rest-api.md#API_DeleteThingShadow) API를 사용하거나 [/delete](device-shadow-mqtt.md#delete-pub-sub-topic) 주제에 게시합니다.

**참고**  
섀도를 삭제해도 버전 번호가 0으로 즉시 재설정되지는 않습니다. 48시간 후에 0으로 재설정됩니다.

### 섀도우 문서에서 속성 삭제
<a name="deleting-shadow-property"></a>

**MQTT 프로토콜을 사용하여 섀도우에서 속성을 삭제하려면**

1. 디바이스 또는 클라이언트가 변경할 속성을 식별할 수 있도록 현재 섀도우 문서가 있어야 합니다. 현재 섀도우 문서를 가져오는 방법은 [섀도우 문서 검색](#retrieving-device-shadow) 단원을 참조하세요.

1. 디바이스 또는 클라이언트는 다음 MQTT 주제를 구독합니다.
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`

1. 디바이스나 클라이언트는 삭제할 섀도우 속성에 `null` 값을 할당하는 상태 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update` 요청 주제를 게시합니다. 변경할 속성만 문서에 포함시켜야 합니다. 다음은 `engine` 속성을 삭제하는 문서의 예입니다.

   ```
   {
     "state": {
       "desired": {
         "engine": null
       }
     }
   }
   ```

1. 업데이트 요청이 유효한 경우는 섀도우에서 지정된 속성을 AWS IoT 삭제하고 메시지 본문에 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)섀도우 문서가 있는 `$aws/things/thingName/shadow/name/shadowName/update/accepted` 주제와 함께 메시지를 게시합니다.

1. 업데이트 요청이 유효하지 않은 경우는 오류를 설명하는 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json) 섀도우 문서와 함께 `$aws/things/thingName/shadow/name/shadowName/update/rejected` 주제가 포함된 메시지를 AWS IoT 게시합니다.

**REST API를 사용하여 섀도우에서 속성을 삭제하려면**

1. 디바이스 또는 클라이언트는 삭제할 섀도우의 속성에 `null` 값을 할당하는 [요청 상태 문서](device-shadow-document.md#device-shadow-example-request-json)을 사용하여 `UpdateThingShadow` API를 호출합니다. 문서에서 삭제할 속성만 포함합니다. 다음은 `engine` 속성을 삭제하는 문서의 예입니다.

   ```
   {
     "state": {
       "desired": {
         "engine": null
       }
     }
   }
   ```

1. 요청이 유효하면는 HTTP 성공 응답 코드와 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서를 응답 메시지 본문으로 AWS IoT 반환합니다.

1. 요청이 유효하지 않은 경우는 HTTP 오류 응답 코드를 응답 메시지 본문[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)으로 AWS IoT 반환합니다.

### 섀도우 삭제
<a name="deleting-device-shadow"></a>

다음은 디바이스의 섀도우를 삭제할 때 고려해야 할 몇 가지 사항입니다.
+ 디바이스의 섀도우 상태를 `null`로 설정해도 섀도우가 삭제되지는 않습니다. 섀도우 버전은 다음 업데이트 시 증가합니다.
+ 디바이스 섀도우를 삭제해도 사물 객체가 삭제되지는 않습니다. 사물 객체를 삭제해도 해당 디바이스 섀도우는 삭제되지 않습니다.
+ 섀도를 삭제해도 버전 번호가 0으로 즉시 재설정되지는 않습니다. 48시간 후에 0으로 재설정됩니다.

**MQTT 프로토콜을 사용하여 섀도우를 삭제하려면**

1. 디바이스 또는 클라이언트는 다음 MQTT 주제를 구독합니다.
   + `$aws/things/thingName/shadow/name/shadowName/delete/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/delete/rejected`

1. 디바이스 또는 클라이언트는 빈 메시지 버퍼를 사용하여 `$aws/things/thingName/shadow/name/shadowName/delete`를 게시합니다.

1. 삭제 요청이 유효한 경우는 섀도우를 AWS IoT 삭제하고 `$aws/things/thingName/shadow/name/shadowName/delete/accepted` 주제 및 축약된 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서가 포함된 메시지를 메시지 본문에 게시합니다. 다음은 수락된 삭제 메시지의 예입니다.

   ```
   {
     "version": 4,
     "timestamp": 1591057529
   }
   ```

1. 업데이트 요청이 유효하지 않은 경우는 오류를 설명하는 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json) 섀도우 문서가 포함된 `$aws/things/thingName/shadow/name/shadowName/delete/rejected` 주제가 포함된 메시지를 AWS IoT 게시합니다.

**REST API를 사용하여 섀도우를 삭제하려면**

1. 디바이스 또는 클라이언트는 빈 메시지 버퍼를 사용하여 `DeleteThingShadow` API를 호출합니다.

1. 요청이 유효하면 메시지 본문에 HTTP 성공 응답 코드와 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 및 축약된 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 섀도우 문서를 AWS IoT 반환합니다. 다음은 수락된 삭제 메시지의 예입니다.

   ```
   {
     "version": 4,
     "timestamp": 1591057529
   }
   ```

1. 요청이 유효하지 않은 경우는 HTTP 오류 응답 코드를 응답 메시지 본문[오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)으로 AWS IoT 반환합니다.

# 디바이스 섀도우 REST API
<a name="device-shadow-rest-api"></a>

섀도우는 상태 정보 업데이트를 위해 다음 URI를 노출시킵니다.

```
https://account-specific-prefix-ats.iot.region.amazonaws.com/things/thingName/shadow
```

엔드포인트는에 고유합니다 AWS 계정. 엔드포인트를 찾으려면 다음을 수행할 수 있습니다.
+  AWS CLI에서 [describe-endpoint](https://docs.aws.amazon.com/cli/latest/reference/iot/describe-endpoint.html) 명령을 사용합니다.
+  AWS IoT 콘솔 설정을 사용합니다. **설정(Settings)**에서 **사용자 지정 엔드포인트(Custom endpoint)** 아래에 엔드포인트가 나열됩니다.
+  AWS IoT 콘솔 사물 세부 정보 페이지를 사용합니다. 콘솔에서:

  1. **관리(Manage)**를 열고 **관리(Manage)** 아래에서 **사물(Things)**을 선택합니다.

  1. 사물 목록에서 엔드포인트 URI를 가져올 항목을 선택합니다.

  1. **디바이스 섀도우(Device Shadows)** 탭을 선택하고 섀도우를 선택합니다. **디바이스 섀도우 세부 정보** 페이지의 **디바이스 섀도우 URL** 섹션에서 엔드포인트 URI를 볼 수 있습니다.

엔드포인트의 형식은 다음과 같습니다.

```
identifier.iot.region.amazonaws.com
```

섀도우 REST API는 [디바이스 통신 프로토콜](protocols.md)에서 설명한 것과 동일한 HTTPS 프로토콜/포트 매핑을 따릅니다.

**참고**  
API를 사용하려면 `iotdevicegateway`를 인증을 위한 서비스 이름으로 사용해야 합니다. 자세한 내용은 [IoTDataPlane](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-iot-data-plane/classes/iotdataplane.html)을 참조하세요.

**Topics**
+ [GetThingShadow](#API_GetThingShadow)
+ [UpdateThingShadow](#API_UpdateThingShadow)
+ [DeleteThingShadow](#API_DeleteThingShadow)
+ [ListNamedShadowsForThing](#API_ListNamedShadowsForThing)

API를 사용하여 API의 쿼리 파라미터의 일부로 `name=shadowName`을 제공하여 명명된 섀도우를 생성할 수도 있습니다.

## GetThingShadow
<a name="API_GetThingShadow"></a>

지정된 사물의 섀도우를 가져옵니다.

응답 상태 문서는 `desired` 상태와 `reported` 상태 간 델타를 포함합니다.

**요청**  
요청은 표준 HTTP 헤더와 다음 URI를 포함합니다.

```
HTTP GET https://endpoint/things/thingName/shadow?name=shadowName
Request body: (none)
```

명명되지 않은(클래식) 섀도우에는 `name` 쿼리 파라미터가 필요하지 않습니다.

**응답**  
성공 시, 응답은 표준 HTTP 헤더와 다음 코드 및 본문을 포함합니다.

```
HTTP 200
Response Body: response state document
```

자세한 내용은 [응답 상태 문서 예제](device-shadow-document.md#device-shadow-example-response-json) 섹션을 참조하세요.

**권한 부여**  
섀도우를 검색하려면 호출자가 `iot:GetThingShadow` 작업을 수행하도록 허용하는 정책이 필요합니다. 디바이스 섀도우 서비스는 두 가지 인증 양식, 즉 IAM 자격 증명을 사용하는 서명 버전 4 또는 클라이언트 인증서를 사용하는 TLS 상호 인증을 수용합니다.

다음은 호출자가 디바이스 섀도우를 검색하도록 허용하는 정책 예제입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iot:GetThingShadow",
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:thing/thing"
            ]
        }
    ]
}
```

## UpdateThingShadow
<a name="API_UpdateThingShadow"></a>

지정된 사물의 섀도우를 업데이트합니다.

업데이트는 요청 상태 문서에 지정된 필드에만 영향을 미칩니다. 디바이스 섀도우에서 `null` 값의 필드가 모두 제거됩니다.

**요청**  
요청은 표준 HTTP 헤더와 다음 URI 및 본문을 포함합니다.

```
HTTP POST https://endpoint/things/thingName/shadow?name=shadowName
Request body: request state document
```

명명되지 않은(클래식) 섀도우에는 `name` 쿼리 파라미터가 필요하지 않습니다.

자세한 내용은 [요청 상태 문서 예제](device-shadow-document.md#device-shadow-example-request-json) 섹션을 참조하세요.

**응답**  
성공 시, 응답은 표준 HTTP 헤더와 다음 코드 및 본문을 포함합니다.

```
HTTP 200
Response body: response state document
```

자세한 내용은 [응답 상태 문서 예제](device-shadow-document.md#device-shadow-example-response-json) 섹션을 참조하세요.

**권한 부여**  
섀도우를 업데이트하려면 호출자가 `iot:UpdateThingShadow` 작업을 수행하도록 허용하는 정책이 필요합니다. 디바이스 섀도우 서비스는 두 가지 인증 양식, 즉 IAM 자격 증명을 사용하는 서명 버전 4 또는 클라이언트 인증서를 사용하는 TLS 상호 인증을 수용합니다.

다음은 호출자가 디바이스 섀도우를 업데이트하도록 허용하는 정책 예제입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iot:UpdateThingShadow",
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:thing/thing"
            ]
        }
    ]
}
```

## DeleteThingShadow
<a name="API_DeleteThingShadow"></a>

지정된 사물의 섀도를 삭제합니다.

**요청**  
요청은 표준 HTTP 헤더와 다음 URI를 포함합니다.

```
HTTP DELETE https://endpoint/things/thingName/shadow?name=shadowName
Request body: (none)
```

명명되지 않은(클래식) 섀도우에는 `name` 쿼리 파라미터가 필요하지 않습니다.

**응답**  
성공 시, 응답은 표준 HTTP 헤더와 다음 코드 및 본문을 포함합니다.

```
HTTP 200
Response body: Empty response state document
```

섀도우를 삭제해도 버전 번호가 0으로 재설정되지는 않습니다.

**권한 부여**  
디바이스 섀도우를 삭제하려면 호출자가 `iot:DeleteThingShadow` 작업을 수행하도록 허용하는 정책이 필요합니다. 디바이스 섀도우 서비스는 두 가지 인증 양식, 즉 IAM 자격 증명을 사용하는 서명 버전 4 또는 클라이언트 인증서를 사용하는 TLS 상호 인증을 수용합니다.

다음은 호출자가 디바이스 섀도우를 삭제하도록 허용하는 정책 예제입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iot:DeleteThingShadow",
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:thing/thing"
            ]
        }
    ]
}
```

## ListNamedShadowsForThing
<a name="API_ListNamedShadowsForThing"></a>

지정한 사물에 대한 섀도우를 나열합니다.

**요청**  
요청은 표준 HTTP 헤더와 다음 URI를 포함합니다.

```
HTTP GET /api/things/shadow/ListNamedShadowsForThing/thingName?nextToken=nextToken&pageSize=pageSize
Request body: (none)
```

nextToken  
다음 결과 집합을 가져오기 위한 토큰입니다.  
이 값은 페이징된 결과에서 반환되며 다음 페이지를 반환하는 호출에 사용됩니다.

pageSize  
각 호출에서 반환할 섀도우 이름의 수입니다. 또한 `nextToken` 단원도 참조하세요.

thingName  
명명된 섀도우를 나열할 사물의 이름입니다.

**응답**  
성공 시, 응답은 표준 HTTP 헤더와 다음 코드 및 [섀도우 이름 목록 응답 문서](device-shadow-document.md#device-shadow-list-json)를 포함합니다.

**참고**  
명명되지 않은(클래식) 섀도우는 이 목록에 나타나지 않습니다. 클래식 섀도우만 있거나 지정한 `thingName`이 없는 경우 응답은 빈 목록입니다.

```
HTTP 200
Response body: Shadow name list document
```

**권한 부여**  
디바이스 섀도우 목록을 표시하려면 호출자가 `iot:ListNamedShadowsForThing` 작업을 수행하도록 허용하는 정책이 필요합니다. 디바이스 섀도우 서비스는 두 가지 인증 양식, 즉 IAM 자격 증명을 사용하는 서명 버전 4 또는 클라이언트 인증서를 사용하는 TLS 상호 인증을 수용합니다.

다음은 호출자가 사물의 명명된 섀도우를 나열하도록 허용하는 정책 예제입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iot:ListNamedShadowsForThing",
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:thing/thing"
            ]
        }
    ]
}
```

# 디바이스 섀도우 MQTT 주제
<a name="device-shadow-mqtt"></a>

디바이스 섀도우 서비스는 디바이스 및 앱이 디바이스(섀도우)의 상태 정보를 가져오거나 업데이트하거나 삭제할 수 있도록 예약된 MQTT 주제를 사용합니다.

섀도우 주제에 대해 게시 또는 구독하려면 주제 기반 인증이 필요합니다. AWS IoT 은(는) 기존 주제 구조에 새 주제를 추가할 권리를 보유합니다. 그러므로 섀도우 주제에 대한 와일드 카드 구독은 삼가도록 권장합니다. 예를 들어가 새 섀도우 주제를 AWS IoT 도입함에 따라이 주제 필터와 일치하는 주제 수가 증가할 수 `$aws/things/thingName/shadow/#` 있으므로와 같은 주제 필터를 구독하지 마세요. 이러한 주제에 게시되는 메시지의 예는 [섀도우와의 상호 작용](device-shadow-data-flow.md) 섹션을 참조하세요.

섀도우는 명명되거나 명명되지 않을(클래식) 수 있습니다. 각 섀도우에 사용되는 주제는 주제 접두사만 다릅니다. 이 표에서는 각 섀도우 유형에서 사용하는 주제 접두사를 보여줍니다.


| *ShadowTopicPrefix* 값 | 섀도우 유형 | 
| --- | --- | 
| \$1aws/things/thingName/shadow | 명명되지 않은(클래식) 섀도우 | 
| \$1aws/things/thingName/shadow/name/shadowName | 명명된 섀도우 | 

전체 주제를 생성하려면 참조할 섀도우 유형에 대해 `ShadowTopicPrefix`를 선택하고 `thingName` 및 `shadowName`(해당하는 경우)을 해당 값으로 바꾸고 다음 섹션에 표시된 대로 주제 스텁을 추가합니다.

다음은 섀도우와 상호 작용하기 위해 사용되는 MQTT 주제입니다.

**Topics**
+ [/get](#get-pub-sub-topic)
+ [/get/accepted](#get-accepted-pub-sub-topic)
+ [/get/rejected](#get-rejected-pub-sub-topic)
+ [/update](#update-pub-sub-topic)
+ [/update/delta](#update-delta-pub-sub-topic)
+ [/update/accepted](#update-accepted-pub-sub-topic)
+ [/update/documents](#update-documents-pub-sub-topic)
+ [/update/rejected](#update-rejected-pub-sub-topic)
+ [/delete](#delete-pub-sub-topic)
+ [/delete/accepted](#delete-accepted-pub-sub-topic)
+ [/delete/rejected](#delete-rejected-pub-sub-topic)

## /get
<a name="get-pub-sub-topic"></a>

디바이스 섀도우를 가져오려면 이 주제에 빈 메시지를 게시합니다.

```
ShadowTopicPrefix/get
```

AWS IoT 는 [/get/accepted](#get-accepted-pub-sub-topic) 또는에 게시하여 응답합니다[/get/rejected](#get-rejected-pub-sub-topic).

### 예제 정책
<a name="get-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Publish"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/get"
            ]
        }
    ]
}
```

## /get/accepted
<a name="get-accepted-pub-sub-topic"></a>

AWS IoT 는 디바이스의 섀도우를 반환할 때이 주제에 응답 섀도우 문서를 게시합니다.

```
ShadowTopicPrefix/get/accepted
```

자세한 내용은 [응답 상태 문서](device-shadow-document.md#device-shadow-example-response-json) 단원을 참조하십시오.

### 예제 정책
<a name="get-accepted-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/get/accepted"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/get/accepted"
            ]
        }
    ]
}
```

## /get/rejected
<a name="get-rejected-pub-sub-topic"></a>

AWS IoT 는 디바이스의 섀도우를 반환할 수 없을 때이 주제에 오류 응답 문서를 게시합니다.

```
ShadowTopicPrefix/get/rejected
```

자세한 내용은 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json) 단원을 참조하십시오.

### 예제 정책
<a name="get-rejected-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
        "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/get/rejected"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Receive"
      ],
      "Resource": [
        "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/get/rejected"
      ]
    }
  ]
}
```

## /update
<a name="update-pub-sub-topic"></a>

디바이스 섀도우를 업데이트하려면 이 주제에 요청 상태 문서를 게시합니다.

```
ShadowTopicPrefix/update
```

메시지 본문에 [부분 요청 상태 문서](device-shadow-document.md#device-shadow-example-request-json)가 포함되어 있습니다.

디바이스의 상태를 업데이트하려고 시도하는 클라이언트는 다음과 같은 `desired` 속성을 가진 JSON 요청 상태 문서를 전송합니다.

```
{
  "state": {
    "desired": {
      "color": "red",
      "power": "on"
    }
  }
}
```

섀도우를 업데이트하는 디바이스는 다음과 같은 `reported` 속성을 가진 JSON 요청 상태 문서를 전송합니다.

```
{
  "state": {
    "reported": {
      "color": "red",
      "power": "on"
    }
  }
}
```

AWS IoT 는 [/update/accepted](#update-accepted-pub-sub-topic) 또는에 게시하여 응답합니다[/update/rejected](#update-rejected-pub-sub-topic).

### 예제 정책
<a name="update-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Publish"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/update"
            ]
        }
    ]
}
```

## /update/delta
<a name="update-delta-pub-sub-topic"></a>

AWS IoT 는 디바이스의 섀도우에 대한 변경을 수락하고 응답 상태 문서에 `desired` 및 상태에 대한 다양한 값이 포함되어 있을 때이 주제에 응답 `reported` 상태 문서를 게시합니다.

```
ShadowTopicPrefix/update/delta
```

메시지 버퍼에 [/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta)가 포함되어 있습니다.

### 메시지 본문 세부 정보
<a name="update-delta-rules"></a>
+ `update/delta`에 게시되는 메시지에는 `desired` 및 `reported` 섹션이 서로 다른 경우에만 원하는 속성이 포함됩니다. 이 메시지는 이러한 속성이 현재 업데이트 메시지에 포함되어 있든지, 또는 이미 AWS IoT에 저장되어 있든지 상관없이 모두 포함합니다. `desired` 및 `reported` 섹션이 서로 다르지 않은 속성은 포함하지 않습니다.
+ 속성이 `reported` 섹션에는 있지만 `desired` 섹션에는 동일한 속성이 없는 경우 이 속성은 포함되지 않습니다.
+ 속성이 `desired` 섹션에는 있지만 `reported` 섹션에는 동일한 속성이 없는 경우 이 속성은 포함됩니다.
+ 속성이 `reported` 섹션에서 삭제되었지만 `desired` 섹션에는 계속 존재하는 경우 이 속성은 포함됩니다.

### 예제 정책
<a name="update-delta-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/update/delta"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/update/delta"
            ]
        }
    ]
}
```

## /update/accepted
<a name="update-accepted-pub-sub-topic"></a>

AWS IoT 는 디바이스 섀도우에 대한 변경을 수락할 때이 주제에 응답 상태 문서를 게시합니다.

```
ShadowTopicPrefix/update/accepted
```

메시지 버퍼에 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)가 포함되어 있습니다.

### 예제 정책
<a name="update-accepted-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/update/accepted"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/update/accepted"
            ]
        }
    ]
}
```

## /update/documents
<a name="update-documents-pub-sub-topic"></a>

AWS IoT 는 섀도우에 대한 업데이트가 성공적으로 수행될 때마다 상태 문서를이 주제에 게시합니다.

```
ShadowTopicPrefix/update/documents
```

메시지 본문에 [/documents response state document](device-shadow-document.md#device-shadow-example-response-json-documents)가 포함되어 있습니다.

### 예제 정책
<a name="update-documents-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/update/documents"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/update/documents"
            ]
        }
    ]
}
```

## /update/rejected
<a name="update-rejected-pub-sub-topic"></a>

AWS IoT 는 디바이스 섀도우에 대한 변경을 거부할 때 오류 응답 문서를이 주제에 게시합니다.

```
ShadowTopicPrefix/update/rejected
```

메시지 본문에 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)가 포함되어 있습니다.

### 예제 정책
<a name="update-rejected-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/update/rejected"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/update/rejected"
            ]
        }
    ]
}
```

## /delete
<a name="delete-pub-sub-topic"></a>

디바이스 섀도우를 삭제하려면 삭제 주제에 빈 메시지를 게시합니다.

```
ShadowTopicPrefix/delete
```

메시지의 내용은 무시됩니다.

섀도우를 삭제해도 버전 번호가 0으로 재설정되지는 않습니다.

AWS IoT 는 [/delete/accepted](#delete-accepted-pub-sub-topic) 또는에 게시하여 응답합니다[/delete/rejected](#delete-rejected-pub-sub-topic).

### 예제 정책
<a name="delete-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Publish"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/delete"
            ]
        }
    ]
}
```

## /delete/accepted
<a name="delete-accepted-pub-sub-topic"></a>

AWS IoT 는 디바이스의 섀도우가 삭제될 때이 주제에 메시지를 게시합니다.

```
ShadowTopicPrefix/delete/accepted
```

### 예제 정책
<a name="delete-accepted-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/delete/accepted"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/delete/accepted"
            ]
        }
    ]
}
```

## /delete/rejected
<a name="delete-rejected-pub-sub-topic"></a>

AWS IoT 는 디바이스의 섀도우를 삭제할 수 없을 때이 주제에 오류 응답 문서를 게시합니다.

```
ShadowTopicPrefix/delete/rejected
```

메시지 본문에 [오류 응답 문서](device-shadow-document.md#device-shadow-example-error-json)가 포함되어 있습니다.

### 예제 정책
<a name="delete-rejected-policy"></a>

다음은 필요한 정책의 예입니다.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Subscribe"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingName/shadow/delete/rejected"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iot:Receive"
            ],
            "Resource": [
                "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingName/shadow/delete/rejected"
            ]
        }
    ]
}
```

# 디바이스 섀도우 서비스 문서
<a name="device-shadow-document"></a>

디바이스 섀도우 서비스는 JSON 사양의 모든 규칙을 준수합니다. 값, 객체 및 배열이 디바이스 섀도우 문서에 저장됩니다.

**Topics**
+ [섀도우 문서 예제](#device-shadow-document-syntax)
+ [문서 속성](#document-structure)
+ [델타 상태](#delta-state)
+ [섀도우 문서 버전 관리](#versioning)
+ [섀도우 문서의 클라이언트 토큰](#client-token)
+ [빈 섀도우 문서 속성](#device-shadow-empty-fields)
+ [섀도우 문서의 배열 값](#device-shadow-arrays)

## 섀도우 문서 예제
<a name="device-shadow-document-syntax"></a><a name="device-shadow-example"></a>

디바이스 섀도우 서비스는 [REST API](device-shadow-rest-api.md) 또는 [MQTT Pub/Sub 메시지](device-shadow-mqtt.md)를 사용한 UPDATE, GET 및 DELETE 작업에서 다음 문서를 사용합니다.

**Topics**
+ [요청 상태 문서](#device-shadow-example-request-json)
+ [응답 상태 문서](#device-shadow-example-response-json)
+ [오류 응답 문서](#device-shadow-example-error-json)
+ [섀도우 이름 목록 응답 문서](#device-shadow-list-json)

### 요청 상태 문서
<a name="device-shadow-example-request-json"></a>

요청 상태 문서의 형식은 다음과 같습니다.

```
{
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        },
        "reported": {
            "attribute1": integer1,
            "attribute2": "string1",
            ...
            "attributeN": boolean1
        }
    },
    "clientToken": "token",
    "version": version
}
```
+ `state` — 업데이트는 지정된 필드에만 영향을 미칩니다. 일반적으로 `desired` 또는 `reported` 속성 중 하나를 사용하지만 동일한 요청에서는 둘 다 사용하지는 않습니다.
  + `desired` — 디바이스에서 업데이트하도록 요청된 상태 속성 및 값입니다.
  + `reported` — 디바이스에서 보고한 상태 속성 및 값입니다.
+ `clientToken` — 사용할 경우, 클라이언트 토큰으로 요청과 해당 응답을 일치시킬 수 있습니다.
+ `version` — 사용할 경우, 디바이스 섀도우 서비스는 지정된 버전이 서비스가 보유하는 최신 버전과 일치하는 경우에만 업데이트를 처리합니다.

### 응답 상태 문서
<a name="device-shadow-example-response-json"></a>

응답 상태 문서의 형식은 응답 유형에 따라 다음과 같습니다.

#### /accepted response state document
<a name="device-shadow-example-response-json-accepted"></a>

```
{
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        }
    },
    "metadata": {
        "desired": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        }
    },
    "timestamp": timestamp,
    "clientToken": "token",
    "version": version
}
```

#### /delta response state document
<a name="device-shadow-example-response-json-delta"></a>

```
{
    "state": {
        "attribute1": integer2,
        "attribute2": "string2",
        ...
        "attributeN": boolean2
    },
    "metadata": {
        "attribute1": {
            "timestamp": timestamp
        },
        "attribute2": {
            "timestamp": timestamp
        },
        ...
        "attributeN": {
            "timestamp": timestamp
        }
    },
    "timestamp": timestamp,
    "clientToken": "token",
    "version": version
}
```

#### /documents response state document
<a name="device-shadow-example-response-json-documents"></a>

```
{
  "previous" : {
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        },
        "reported": {
            "attribute1": integer1,
            "attribute2": "string1",
            ...
            "attributeN": boolean1
        }
    },
    "metadata": {
        "desired": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        },
        "reported": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        }
    },
    "version": version-1
  },
  "current": {
    "state": {
        "desired": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        },
        "reported": {
            "attribute1": integer2,
            "attribute2": "string2",
            ...
            "attributeN": boolean2
        }
    },
    "metadata": {
        "desired": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        },
        "reported": {
            "attribute1": {
                "timestamp": timestamp
            },
            "attribute2": {
                "timestamp": timestamp
            },
            ...
            "attributeN": {
                "timestamp": timestamp
            }
        }
    },
    "version": version
  },
  "timestamp": timestamp,
  "clientToken": "token"
}
```

#### 응답 상태 문서 속성
<a name="device-shadow-example-response-json-properties"></a>
+ `previous` — 성공적으로 업데이트되면 업데이트 전 객체의 `state`를 포함합니다.
+ `current` — 성공적으로 업데이트되면 업데이트 후 객체의 `state`를 포함합니다.
+ `state`
  + `reported` — 사물이 `reported` 섹션의 데이터를 보고하고 요청 상태 문서에 있는 필드만 포함하는 경우에만 존재합니다.
  + `desired` — 디바이스가 `desired` 섹션의 데이터를 보고하고 요청 상태 문서에 있는 필드만 포함하는 경우에만 존재합니다.
+ `metadata` — 언제 상태가 업데이트되었는지 확인할 수 있도록 `desired` 및 `reported` 섹션의 각 속성에 대한 타임스탬프를 포함합니다.
+ `timestamp` - 응답이 생성된 Epoch 날짜 및 시간입니다 AWS IoT.
+ `clientToken` — 유효한 JSON을 `/update` 주제에 게시할 때 클라이언트 토큰이 사용된 경우에만 존재합니다.
+ `version` — AWS IoT에서 공유되는 디바이스 섀도우에 대한 문서의 현재 버전입니다. 현재 버전은 이전 문서 버전보다 1이 증가합니다.

### 오류 응답 문서
<a name="device-shadow-example-error-json"></a>

오류 응답 문서의 형식은 다음과 같습니다.

```
{
    "code": error-code,
    "message": "error-message",
    "timestamp": timestamp,
    "clientToken": "token"
}
```
+ `code` — 오류 유형을 나타내는 HTTP 응답 코드입니다.
+ `message` — 추가 정보를 제공하는 텍스트 메시지입니다.
+ `timestamp` - 응답이 생성된 날짜와 시간입니다 AWS IoT. 이 속성은 모든 오류 응답 문서에 존재하지 않습니다.
+ `clientToken` — 게시된 메시지에 클라이언트 토큰이 사용된 경우에만 존재합니다.

자세한 내용은 [디바이스 섀도우 오류 메시지](device-shadow-error-messages.md) 단원을 참조하세요.

### 섀도우 이름 목록 응답 문서
<a name="device-shadow-list-json"></a>

섀도우 이름 목록 응답 문서의 형식은 다음과 같습니다.

```
{
    "results": [
        "shadowName-1",
        "shadowName-2",
        "shadowName-3",
        "shadowName-n"
    ],
    "nextToken": "nextToken",
    "timestamp": timestamp
}
```
+ `results` — 섀도우 이름의 배열입니다.
+ `nextToken` — 시퀀스의 다음 페이지를 가져오기 위해 페이징된 요청에 사용할 토큰 값입니다. 반환할 섀도우 이름이 더 이상 없는 경우에는 이 속성이 존재하지 않습니다.
+ `timestamp` - 응답이 생성된 날짜와 시간입니다 AWS IoT.

## 문서 속성
<a name="document-structure"></a>

디바이스 섀도우 문서의 속성은 다음과 같습니다.

`state`  <a name="state"></a>  
`desired`  <a name="desired"></a>
디바이스의 원하는 상태입니다. 앱은 문서의 이 부분에 기록하여, 디바이스와 연결할 필요 없이 디바이스의 상태를 직접 업데이트할 수 있습니다.  
`reported`  <a name="reported"></a>
디바이스의 보고된 상태입니다. 디바이스는 문서의 이 부분을 기록하여 새 상태를 보고합니다. 앱은 문서의 이 부분을 읽어 디바이스의 마지막 보고 상태를 확인합니다.

`metadata`  <a name="metadata"></a>
문서의 `state` 섹션에 저장된 데이터에 대한 정보입니다. 여기에는 `state` 섹션의 각 속성에 대한 Epoch 시간 형식의 타임스탬프가 포함되는데, 이를 통해 각 속성이 업데이트된 시간을 알 수 있습니다.  
메타데이터는 서비스 제한 또는 요금에 대한 문서 크기에 도움이 되지 않습니다. 자세한 내용은 [AWS IoT 서비스 한도](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_iot) 단원을 참조하세요.

`timestamp`  <a name="timestamp"></a>
메시지가 전송된 시기를 나타냅니다 AWS IoT. 메시지 내 타임스탬프와 `desired` 또는 `reported` 섹션의 개별 속성에 대한 타임스탬프를 사용하면 디바이스에 내장 클록이 없어도 디바이스에서 속성의 사용 기간을 확인할 수 있습니다.

`clientToken`  <a name="clientToken"></a>
MQTT 환경에서 응답을 요청에 연결할 수 있는 디바이스 고유 문자열입니다.

`version`  <a name="version"></a>
문서 버전입니다. 문서가 업데이트될 때마다 이 버전 번호가 증가합니다. 업데이트되는 문서의 버전이 최신인지 확인하는 데 사용됩니다.

자세한 내용은 [섀도우 문서 예제](#device-shadow-document-syntax) 단원을 참조하세요.

## 델타 상태
<a name="delta-state"></a><a name="observing-state-changes"></a>

델타 상태는 `desired` 상태와 `reported` 상태 간 차이를 포함하는 가상의 상태 유형입니다. `desired` 섹션에는 있지만 `reported` 섹션에는 없는 필드가 델타에 포함됩니다. `reported` 섹션에는 있고 `desired` 섹션에는 없는 필드는 델타에 포함되지 않습니다. 델타는 메타데이터를 포함하며, 해당 값은 `desired` 필드 내 메타데이터와 동일합니다. 다음 예를 참조하세요.

```
{
  "state": {
    "desired": {
      "color": "RED",
      "state": "STOP"
    },
    "reported": {
      "color": "GREEN",
      "engine": "ON"
    },
    "delta": {
      "color": "RED",
      "state": "STOP"
    }
  },
  "metadata": {
    "desired": {
      "color": {
        "timestamp": 12345
      },
      "state": {
        "timestamp": 12345
      }
      },
      "reported": {
        "color": {
          "timestamp": 12345
        },
        "engine": {
          "timestamp": 12345
        }
      },
      "delta": {
        "color": {
          "timestamp": 12345
        },
        "state": {
          "timestamp": 12345
        }
      }
    },
    "version": 17,
    "timestamp": 123456789
  }
}
```

중첩된 객체가 다를 경우 델타는 루트까지의 전체 경로를 포함합니다.

```
{
  "state": {
    "desired": {
      "lights": {
        "color": {
          "r": 255,
          "g": 255,
          "b": 255
        }
      }
    },
    "reported": {
      "lights": {
        "color": {
          "r": 255,
          "g": 0,
          "b": 255
        }
      }
    },
    "delta": {
      "lights": {
        "color": {
          "g": 255
        }
      }
    }
  },
  "version": 18,
  "timestamp": 123456789
}
```

디바이스 섀도우 서비스는 `desired` 상태의 각 필드를 `reported` 상태와 비교하여 델타를 계산합니다.

배열은 값처럼 취급됩니다. `desired` 섹션의 한 배열이 `reported` 섹션의 배열과 일치하지 않을 경우 원하는 배열 전체가 델타로 복사됩니다.

## 섀도우 문서 버전 관리
<a name="versioning"></a>

디바이스 섀도우 서비스는 요청과 응답의 모든 업데이트 메시지에 대한 버전 관리를 지원합니다. 즉, 섀도우가 업데이트될 때마다 JSON 문서의 버전이 증가합니다. 이를 통해 2가지가 보장됩니다.
+ 클라이언트가 구 버전을 사용하여 섀도우를 덮어쓰려 할 경우 오류 응답을 받을 수 있습니다. 클라이언트에 디바이스 섀도우를 업데이트하기 전에 재동기화해야 한다는 알림이 제공됩니다.
+ 수신된 메시지가 클라이언트에 저장된 것보다 낮은 버전일 경우 클라이언트는 메시지에 대한 작업을 수행하지 않기로 결정할 수 있습니다.

클라이언트는 섀도우 문서에 버전을 포함하지 않음으로써 버전 일치를 무시할 수 있습니다.

## 섀도우 문서의 클라이언트 토큰
<a name="client-token"></a>

클라이언트 토큰을 MQTT 기반 메시징과 함께 사용하여 요청 및 요청 응답에 동일한 클라이언트 토큰이 포함되었는지 확인할 수 있습니다. 이는 응답과 요청이 연결되도록 합니다.

**참고**  
클라이언트 토큰은 64바이트보다 길면 안 됩니다. 클라이언트 토큰이 64바이트보다 길면 400(잘못된 요청) 응답과 *잘못된 클라이언트 토큰* 오류 메시지가 표시됩니다.

## 빈 섀도우 문서 속성
<a name="device-shadow-empty-fields"></a>

섀도우 문서의 `reported` 및 `desired` 속성은 비어 있거나 현재 섀도우 상태에 적용되지 않을 경우 생략할 수 있습니다. 예를 들어 섀도우 문서는 원하는 상태가 있을 경우에만 `desired` 속성을 포함합니다. 예를 들어 다음은 유효한 상태 문서이지만 `desired` 속성이 없습니다.

```
{
    "reported" : { "temp": 55 }
}
```

`reported` 속성은 디바이스에 의해 섀도우가 업데이트되지 않은 경우와 같이 비어 있을 수도 있습니다.

```
{
    "desired" : { "color" : "RED" }
}
```

업데이트로 인해 `desired` 또는 `reported` 속성이 null이 될 경우 해당 속성이 문서에서 제거됩니다. 다음은 `null`로 설정하여 `desired` 속성을 제거하는 방법을 보여줍니다. 예를 들어 디바이스가 상태를 업데이트할 때 이 작업을 수행할 수 있습니다.

```
{ 
    "state": {
        "reported": {
            "color": "red" 
        }, 
        "desired": null 
    } 
}
```

섀도우 문서에는 `desired` 또는 `reported` 속성이 없을 수도 있으므로 섀도우 문서를 비워 둘 수 있습니다. 비어 있지만 유효한 섀도우 문서의 예입니다.

```
{
}
```

## 섀도우 문서의 배열 값
<a name="device-shadow-arrays"></a>

섀도우는 배열을 지원하지만, 배열에 대한 업데이트가 전체 배열을 대체한다는 점에서 배열을 일반적인 값으로 취급합니다. 배열을 일부만 업데이트할 수는 없습니다.

Initial state:

```
{
    "desired" : { "colors" : ["RED", "GREEN", "BLUE" ] }
}
```

업데이트:

```
{
    "desired" : { "colors" : ["RED"] }
}
```

최종 상태:

```
{
    "desired" : { "colors" : ["RED"] }
}
```

배열은 null 값을 가질 수 없습니다. 예를 들어 다음 배열은 유효하지 않으므로 거부됩니다.

```
{
    "desired" : { 
        "colors" : [ null, "RED", "GREEN" ]
    }
}
```

# 디바이스 섀도우 오류 메시지
<a name="device-shadow-error-messages"></a>

디바이스 섀도우 서비스는 상태 문서에 대한 변경 시도가 실패할 경우 (MQTT를 통해) 메시지를 오류 주제에 게시합니다. 이 메시지는 예약된 `$aws` 주제 중 하나로의 게시 요청에 대한 응답으로만 생성됩니다. 클라이언트가 REST API를 사용하여 문서를 업데이트하는 경우에는 클라이언트가 응답의 일부로 HTTP 오류 코드를 수신하며 MQTT 오류 메시지는 생성되지 않습니다.


****  

| HTTP 오류 코드 | 오류 메시지 | 
| --- | --- | 
| 400(잘못된 요청) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 401(권한이 없음) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 403(금지됨) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 404(찾을 수 없음) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 409(충돌) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 413(페이로드가 너무 큼) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 415(지원되지 않는 미디어 유형) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 429(요청이 너무 많음) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 
| 500(내부 서버 오류) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/iot/latest/developerguide/device-shadow-error-messages.html)  | 