

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

# AWS IoT Device SDK 를 사용하여 Greengrass nucleus, 기타 구성 요소 및 AWS IoT Core
<a name="interprocess-communication"></a>

코어 디바이스에서 실행되는 구성 요소는의 AWS IoT Greengrass 코어 프로세스 간 통신(IPC) 라이브러리를 사용하여 AWS IoT Greengrass nucleus 및 기타 Greengrass 구성 요소와 통신 AWS IoT Device SDK 할 수 있습니다. IPC를 사용하는 사용자 지정 구성 요소를 개발하고 실행하려면 AWS IoT Device SDK 를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 연결하고 IPC 작업을 수행해야 합니다.

IPC 인터페이스는 두 가지 유형의 작업을 지원합니다.
+ **요청/응답**

  구성 요소가 IPC 서비스에 요청을 보내고 요청 결과가 포함된 응답을 수신합니다.
+ **Subscription**

  구성 요소가 IPC 서비스에 구독 요청을 보내고 응답으로 이벤트 메시지 스트림을 예상합니다. 구성 요소에서 이벤트 메시지, 오류 및 스트림 종료를 처리하는 구독 핸들러를 제공합니다. 에는 각 IPC 작업에 대한 올바른 응답 및 이벤트 유형이 있는 핸들러 인터페이스가 AWS IoT Device SDK 포함되어 있습니다. 자세한 내용은 [IPC 이벤트 스트림 구독](#ipc-subscribe-operations) 단원을 참조하십시오.

**Topics**
+ [IPC 클라이언트 버전](#ipc-client-versions)
+ [프로세스 간 통신을 위해 지원되는 SDK](#ipc-requirements)
+ [AWS IoT Greengrass 코어 IPC 서비스에 연결](#ipc-service-connect)
+ [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](#ipc-authorization-policies)
+ [IPC 이벤트 스트림 구독](#ipc-subscribe-operations)
+ [IPC 모범 사례](#ipc-best-practices)
+ [로컬 메시지 게시/구독](ipc-publish-subscribe.md)
+ [AWS IoT Core MQTT 메시지 게시/구독](ipc-iot-core-mqtt.md)
+ [구성 요소 수명 주기와 연동](ipc-component-lifecycle.md)
+ [구성 요소 구성과 연동](ipc-component-configuration.md)
+ [보안 암호 값 검색](ipc-secret-manager.md)
+ [로컬 섀도와 연동](ipc-local-shadows.md)
+ [로컬 배포 및 구성 요소 관리](ipc-local-deployments-components.md)
+ [클라이언트 디바이스 인증 및 권한 부여](ipc-client-device-auth.md)

## IPC 클라이언트 버전
<a name="ipc-client-versions"></a>

Java 및 Python SDKs의 이후 버전에서는 IPC 클라이언트 V2라는 향상된 버전의 IPC 클라이언트를 AWS IoT Greengrass 제공합니다. IPC 클라이언트 V2의 특징은 다음과 같습니다.
+ IPC 작업을 사용하기 위해 작성해야 하는 코드의 양이 감소하고 IPC 클라이언트 V1에서 발생할 수 있는 일반적인 오류를 방지하는 데 도움이 됩니다.
+ 구독 핸들러 콜백을 별도의 스레드로 호출하므로 이제 구독 핸들러 콜백에서 추가 IPC 함수 호출이 포함된 차단 코드를 실행할 수 있습니다. IPC 클라이언트 V1에서는 동일한 스레드를 사용하여 IPC 서버와 통신하고 구독 핸들러 콜백을 직접 호출합니다.
+ Lambda 표현식(Java) 또는 함수(Python)를 사용하여 구독 작업을 직접적으로 호출할 수 있습니다. IPC 클라이언트 V1에서는 구독 핸들러 클래스를 정의해야 합니다.
+ 각 IPC 작업의 동기 및 비동기 버전을 제공합니다. IPC 클라이언트 V1에서는 각 작업의 비동기 버전만 제공합니다.

이러한 개선 사항을 활용하려면 IPC 클라이언트 V2를 사용하는 것이 좋습니다. 그러나 이 설명서와 일부 온라인 콘텐츠의 많은 예제에서는 IPC 클라이언트 V1을 사용하는 방법만 보여줍니다. 다음 예제와 자습서를 사용하여 IPC 클라이언트 V2를 사용하는 샘플 구성 요소를 확인할 수 있습니다.
+ [PublishToTopic 예제](ipc-publish-subscribe.md#ipc-operation-publishtotopic-examples)
+ [SubscribeToTopic 예제](ipc-publish-subscribe.md#ipc-operation-subscribetotopic-examples)
+ [자습서: 구성 요소 업데이트가 지연되는 Greengrass 구성 요소 개발](defer-component-updates-tutorial.md)
+ [자습서: MQTT를 통해 로컬 IoT 디바이스와 상호 작용](client-devices-tutorial.md)

현재 C\$1\$1 v2 AWS IoT Device SDK 용는 IPC 클라이언트 V1만 지원합니다.

## 프로세스 간 통신을 위해 지원되는 SDK
<a name="ipc-requirements"></a>

 AWS IoT Greengrass 코어 IPC 라이브러리는 다음 AWS IoT Device SDK 버전에 포함되어 있습니다.


| SDK | 최소 버전 | 사용법 | 
| --- | --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.6.0  |  [Java v2 AWS IoT Device SDK 용 사용(IPC 클라이언트 V2)](#ipc-java-v2) 섹션을 참조하세요  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.9.0  |  [Python v2(IPC 클라이언트 V2) AWS IoT Device SDK 에 사용](#ipc-python-v2) 섹션을 참조하세요  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  |  [C\$1\$1 v2 AWS IoT Device SDK 에 사용](#ipc-cpp) 섹션을 참조하세요  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  |  [JavaScript v2 AWS IoT Device SDK 용 사용(IPC 클라이언트 V1)](#ipc-nodejs) 섹션을 참조하세요  | 

## AWS IoT Greengrass 코어 IPC 서비스에 연결
<a name="ipc-service-connect"></a>

사용자 지정 구성 요소에서 프로세스 간 통신을 사용하려면 AWS IoT Greengrass 코어 소프트웨어가 실행하는 IPC 서버 소켓에 대한 연결을 생성해야 합니다. 다음 작업을 완료하여 원하는 언어로 AWS IoT Device SDK 를 다운로드하고 사용합니다.

### Java v2 AWS IoT Device SDK 용 사용(IPC 클라이언트 V2)
<a name="ipc-java-v2"></a>

**AWS IoT Device SDK for Java v2(IPC 클라이언트 V2)를 사용하려면**

1. [AWS IoT Device SDK for Java v2](https://github.com/aws/aws-iot-device-sdk-java-v2)(v1.6.0 이상)를 다운로드합니다.

1. <a name="use-ipc-java-component-install-step"></a>다음 중 하나를 수행하여 구성 요소에서 사용자 지정 코드를 실행합니다.
   + 구성 요소를가 포함된 JAR 파일로 빌드 AWS IoT Device SDK하고 구성 요소 레시피에서이 JAR 파일을 실행합니다.
   +  AWS IoT Device SDK JAR을 구성 요소 아티팩트로 정의하고 구성 요소 레시피에서 애플리케이션을 실행할 때 해당 아티팩트를 클래스 경로에 추가합니다.

1. 다음 코드를 사용하여 IPC 클라이언트를 생성합니다.

   ```
   try (GreengrassCoreIPCClientV2 ipcClient = GreengrassCoreIPCClientV2.builder().build()) {
       // Use client.
   } catch (Exception e) {
       LOGGER.log(Level.SEVERE, "Exception occurred when using IPC.", e);
       System.exit(1);
   }
   ```

### Python v2(IPC 클라이언트 V2) AWS IoT Device SDK 에 사용
<a name="ipc-python-v2"></a>

**Python v2 AWS IoT Device SDK 용를 사용하려면(IPC 클라이언트 V2)**

1. [AWS IoT Device SDK for Python](https://github.com/aws/aws-iot-device-sdk-python-v2)(v1.9.0 이상)을 다운로드합니다.

1. <a name="use-ipc-python-component-install-step"></a>구성 요소 레시피의 설치 수명 주기에 SDK의 [설치 단계](https://github.com/aws/aws-iot-device-sdk-python-v2#installation)를 추가합니다.

1.  AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 다음 코드를 사용하여 IPC 클라이언트를 생성합니다.

   ```
   from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
   
   try:
       ipc_client = GreengrassCoreIPCClientV2()
       # Use IPC client.
   except Exception:
       print('Exception occurred when using IPC.', file=sys.stderr)
       traceback.print_exc()
       exit(1)
   ```

### C\$1\$1 v2 AWS IoT Device SDK 에 사용
<a name="ipc-cpp"></a>

<a name="iot-device-sdk-cpp-v2-build-requirements-intro"></a>C\$1\$1용 AWS IoT Device SDK v2를 빌드하려면 디바이스에 다음 도구가 있어야 합니다.<a name="iot-device-sdk-cpp-v2-build-requirements"></a>
+ C\$1\$1 11 이상
+ CMake 3.1 이상
+ 다음 컴파일러 중 하나입니다.
  + GCC 4.8 이상
  + Clang 3.9 이상
  + MSVC 2015 이상

**C\$1\$1 v2 AWS IoT Device SDK 용를 사용하려면**

1. [AWS IoT Device SDK for C\$1\$1 v2](https://github.com/aws/aws-iot-device-sdk-cpp-v2)(v1.17.0 이상)를 다운로드합니다.

1. [README의 설치 지침에 따라 소스에서 C\$1\$1 v2용 ](https://github.com/aws/aws-iot-device-sdk-cpp-v2#Installation)를 빌드합니다. AWS IoT Device SDK 

1. C\$1\$1 빌드 도구에서 이전 단계에서 빌드한 Greengrass IPC 라이브러리 `AWS::GreengrassIpc-cpp`를 연결합니다. 다음 `CMakeLists.txt` 예제에서는 Greengrass IPC 라이브러리를 CMake로 빌드하는 프로젝트에 연결합니다.

   ```
   cmake_minimum_required(VERSION 3.1)
   project (greengrassv2_pubsub_subscriber)
   
   file(GLOB MAIN_SRC
           "*.h"
           "*.cpp"
           )
   add_executable(${PROJECT_NAME} ${MAIN_SRC})
   
   set_target_properties(${PROJECT_NAME} PROPERTIES
           LINKER_LANGUAGE CXX
           CXX_STANDARD 11)
   find_package(aws-crt-cpp PATHS ~/sdk-cpp-workspace/build)
   find_package(EventstreamRpc-cpp PATHS ~/sdk-cpp-workspace/build)
   find_package(GreengrassIpc-cpp PATHS ~/sdk-cpp-workspace/build)
   target_link_libraries(${PROJECT_NAME} AWS::GreengrassIpc-cpp)
   ```

1. 구성 요소 코드에서 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성하여 IPC 클라이언트()를 생성합니다`Aws::Greengrass::GreengrassCoreIpcClient`. IPC 연결, 연결 해제 및 오류 이벤트를 처리하는 IPC 연결 수명 주기 핸들러를 정의해야 합니다. 다음 예제에서는 IPC 클라이언트와 IPC 클라이언트가 연결 및 연결 해제하고 오류가 발생할 때 출력하는 IPC 연결 수명 주기 핸들러를 생성합니다.

   ```
   #include <iostream>
   
   #include <aws/crt/Api.h>
   #include <aws/greengrass/GreengrassCoreIpcClient.h>
   
   using namespace Aws::Crt;
   using namespace Aws::Greengrass;
   
   class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
       void OnConnectCallback() override {
           std::cout << "OnConnectCallback" << std::endl;
       }
   
       void OnDisconnectCallback(RpcError error) override {
           std::cout << "OnDisconnectCallback: " << error.StatusToString() << std::endl;
           exit(-1);
       }
   
       bool OnErrorCallback(RpcError error) override {
           std::cout << "OnErrorCallback: " << error.StatusToString() << std::endl;
           return true;
       }
   };
   
   int main() {
       // Create the IPC client.
       ApiHandle apiHandle(g_allocator);
       Io::EventLoopGroup eventLoopGroup(1);
       Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
       Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
       IpcClientLifecycleHandler ipcLifecycleHandler;
       GreengrassCoreIpcClient ipcClient(bootstrap);
       auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
       if (!connectionStatus) {
           std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
           exit(-1);
       }
       
       // Use the IPC client to create an operation request.
       
       // Activate the operation request.
       auto activate = operation.Activate(request, nullptr);
       activate.wait();
   
       // Wait for Greengrass Core to respond to the request.
       auto responseFuture = operation.GetResult();
       if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
           std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
           exit(-1);
       }
   
       // Check the result of the request.
       auto response = responseFuture.get();
       if (response) {
           std::cout << "Successfully published to topic: " << topic << std::endl;
       } else {
           // An error occurred.
           std::cout << "Failed to publish to topic: " << topic << std::endl;
           auto errorType = response.GetResultType();
           if (errorType == OPERATION_ERROR) {
               auto *error = response.GetOperationError();
               std::cout << "Operation error: " << error->GetMessage().value() << std::endl;
           } else {
               std::cout << "RPC error: " << response.GetRpcError() << std::endl;
           }
           exit(-1);
       }
       
       return 0;
   }
   ```

1. 구성 요소에서 사용자 지정 코드를 실행하려면 코드를 이진 아티팩트로 빌드하고 구성 요소 레시피에서 이진 아티팩트를 실행합니다. AWS IoT Greengrass 코어 소프트웨어가 이진 아티팩트를 실행할 수 `OWNER` 있도록 아티팩트의 `Execute` 권한을 로 설정합니다.

   구성 요소 레시피의 `Manifests` 섹션은 다음 예제와 같을 수 있습니다.

------
#### [ JSON ]

   ```
   {
     ...
     "Manifests": [
       {
         "Lifecycle": {
           "Run": "{artifacts:path}/greengrassv2_pubsub_subscriber"
         },
         "Artifacts": [
           {
             "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberCpp/1.0.0/greengrassv2_pubsub_subscriber",
             "Permission": {
               "Execute": "OWNER"
             }
           }
         ]
       }
     ]
   }
   ```

------
#### [ YAML ]

   ```
   ...
   Manifests:
     - Lifecycle:
         Run: {artifacts:path}/greengrassv2_pubsub_subscriber
       Artifacts:
         - URI: s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberCpp/1.0.0/greengrassv2_pubsub_subscriber
           Permission:
             Execute: OWNER
   ```

------

### JavaScript v2 AWS IoT Device SDK 용 사용(IPC 클라이언트 V1)
<a name="ipc-nodejs"></a>

<a name="iot-device-sdk-nodejs-build-requirements-intro"></a>NodeJS에서 사용할 AWS IoT Device SDK for JavaScript v2를 빌드하려면 디바이스에 다음 도구가 있어야 합니다.<a name="iot-device-sdk-nodejs-build-requirements"></a>
+ NodeJS 10.0 이상
  + `node -v`를 실행하여 노드 버전을 확인합니다.
+ CMake 3.1 이상

**AWS IoT Device SDK for JavaScript v2(IPC 클라이언트 V1)를 사용하려면**

1. [AWS IoT Device SDK for JavaScript v2](https://github.com/aws/aws-iot-device-sdk-js-v2)(v1.12.10 이상)를 다운로드합니다.

1. [README의 설치 지침에](https://github.com/aws/aws-iot-device-sdk-js-v2/tree/v1.12.1#installation) 따라 소스에서 for JavaScript v2 AWS IoT Device SDK 를 빌드합니다.

1.  AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 다음 단계를 완료하여 IPC 클라이언트를 생성하고 연결을 설정합니다.

1. 다음 코드를 사용하여 IPC 클라이언트를 생성합니다.

   ```
   import * as greengrascoreipc from 'aws-iot-device-sdk-v2';
   
   let client = greengrascoreipc.createClient();
   ```

1. 다음 코드를 사용하여 구성 요소와 Greengrass nucleus 사이의 연결을 설정합니다.

   ```
   await client.connect();
   ```

## 구성 요소에 IPC 작업을 수행할 수 있는 권한 부여
<a name="ipc-authorization-policies"></a>

사용자 지정 구성 요소가 일부 IPC 작업을 사용하도록 허용하려면 구성 요소가 특정 리소스에서 작업을 수행하도록 허용하는 *권한 부여 정책*을 정의해야 합니다. 각 권한 부여 정책에서는 정책에서 허용하는 작업 목록과 리소스 목록을 정의합니다. 예를 들어 메시징 IPC 서비스 게시/구독에서는 주제 리소스에 대한 게시 및 구독 작업을 정의합니다. `*` 와일드카드를 사용하여 모든 작업 또는 모든 리소스에 대한 액세스를 허용할 수 있습니다.

구성 요소 레시피에서나 구성 요소를 배포할 때 설정할 수 있는 `accessControl` 구성 파라미터로 권한 부여 정책을 정의합니다. `accessControl` 객체는 IPC 서비스 식별자를 권한 부여 정책 목록에 매핑합니다. 각 IPC 서비스에 대해 여러 권한 부여 정책을 정의하여 액세스를 제어할 수 있습니다. 각 권한 부여 정책에는 정책 ID가 있으며, 이는 모든 구성 요소에서 고유해야 합니다.

**작은 정보**  
고유한 정책 ID를 생성하려면 구성 요소 이름, IPC 서비스 이름 및 카운터를 결합할 수 있습니다. 예를 들어 `com.example.HelloWorld`라는 구성 요소에서는 다음 ID를 사용하여 두 개의 게시/구독 권한 부여 정책을 정의할 수 있습니다.  
`com.example.HelloWorld:pubsub:1`
`com.example.HelloWorld:pubsub:2`

권한 부여 정책에서는 다음 형식을 사용합니다. 이 객체는 `accessControl` 구성 파라미터입니다.

------
#### [ JSON ]

```
{
  "IPC service identifier": {
    "policyId": {
      "policyDescription": "description",
      "operations": [
        "operation1",
        "operation2"
      ],
      "resources": [
        "resource1",
        "resource2"
      ]
    }
  }
}
```

------
#### [ YAML ]

```
IPC service identifier:
  policyId:
    policyDescription: description
    operations:
      - operation1
      - operation2
    resources:
      - resource1
      - resource2
```

------

### 권한 부여 정책의 와일드카드
<a name="ipc-authorization-policy-wildcards"></a>

IPC 권한 부여 정책의 `resources` 요소에 `*` 와일드카드를 사용하여 단일 권한 부여 정책에서 여러 리소스에 대한 액세스를 허용할 수 있습니다.
+ 모든 버전의 [Greengrass nucleus](greengrass-nucleus-component.md)에서 단일 `*` 문자를 리소스로 지정하여 모든 리소스에 대한 액세스를 허용할 수 있습니다.
+ [Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서는 임의의 문자 조합과 일치하도록 `*` 문자를 리소스에 지정할 수 있습니다. 예를 들어 `factory/1/devices/Thermostat*/status`를 지정하여 각 디바이스의 이름이 `Thermostat`로 시작되는 공장의 모든 온도조절 디바이스의 상태 주제에 대한 액세스를 허용할 수 있습니다.

 AWS IoT Core MQTT IPC 서비스에 대한 권한 부여 정책을 정의할 때 MQTT 와일드카드(`+` 및 `#`)를 사용하여 여러 리소스와 일치시킬 수도 있습니다. 자세한 내용은 [MQTT IPC 권한 부여 정책의 AWS IoT Core MQTT 와일드카드를 참조하세요](ipc-iot-core-mqtt.md#ipc-iot-core-mqtt-authorization-mqtt-wildcards).

### 권한 부여 정책의 레시피 변수
<a name="ipc-authorization-policy-recipe-variables"></a>

[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상을 사용하고 Greengrass nucleus의 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 구성 옵션을 `true`로 설정한 경우 권한 부여 정책에서 `{iot:thingName}` [레시피 변수](component-recipe-reference.md#recipe-variables)를 사용할 수 있습니다. MQTT 주제 또는 디바이스 섀도 등에 대한 코어 디바이스의 이름이 포함된 권한 부여 정책이 필요한 경우 이 레시피 변수를 사용하여 코어 디바이스 그룹에 대한 단일 권한 부여 정책을 구성할 수 있습니다. 예를 들어 섀도 IPC 작업을 위해 다음 리소스에 대한 구성 요소 액세스를 허용할 수 있습니다.

```
$aws/things/{iot:thingName}/shadow/
```

### 권한 부여 정책의 특수 문자
<a name="ipc-authorization-policy-special-characters"></a>

권한 부여 정책에서 리터럴 `*` 또는 `?` 문자를 지정하려면 이스케이프 시퀀스를 사용해야 합니다. 다음 이스케이프 시퀀스는 AWS IoT Greengrass 코어 소프트웨어에 캐릭터의 특별한 의미 대신 리터럴 값을 사용하도록 지시합니다. 예를 들어 `*` 문자는 임의의 문자 조합과 일치하는 [와일드카드](#ipc-authorization-policy-wildcards)입니다.


| 리터럴 문자 | 이스케이프 시퀀스 | 참고 | 
| --- | --- | --- | 
|  `*`  |  `${*}`  |  | 
|  `?`  |  `${?}`  |  AWS IoT Greengrass 는 현재 단일 문자와 일치하는 `?` 와일드카드를 지원하지 않습니다.  | 
|  `$`  |  `${$}`  |  `${`이 포함된 리소스와 일치시키려면 이스케이프 시퀀스를 사용합니다. 예를 들어 `${resourceName}`이라는 리소스와 일치시키려면 `${$}{resourceName}`을 지정해야 합니다. 그렇지 않으면 `$`가 포함된 리소스와 일치시키려면 리터럴 `$`를 사용할 수 있습니다. 예를 들어 `$aws`로 시작하는 주제에 대한 액세스를 허용할 수 있습니다.  | 

### 권한 부여 정책 예제
<a name="ipc-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 권한 부여 정책이 있는 구성 요소 레시피 예제**  
다음 예제 구성 요소 레시피에는 권한 부여 정책을 정의하는 `accessControl` 객체가 포함되어 있습니다. 이 정책은 `com.example.HelloWorld` 구성 요소에 `test/topic` 주제에 게시할 수 있는 권한을 부여합니다.  

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.HelloWorld",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.HelloWorld:pubsub:1": {
            "policyDescription": "Allows access to publish to test/topic.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "test/topic"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "java -jar {artifacts:path}/HelloWorld.jar"
      }
    }
  ]
}
```

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.HelloWorld
ComponentVersion: '1.0.0'
ComponentDescription: A component that publishes messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        "com.example.HelloWorld:pubsub:1":
          policyDescription: Allows access to publish to test/topic.
          operations:
            - "aws.greengrass#PublishToTopic"
          resources:
            - "test/topic"
Manifests:
  - Lifecycle:
      Run: |-
        java -jar {artifacts:path}/HelloWorld.jar
```

**Example 권한 부여 정책이 있는 구성 요소 구성 업데이트 예제**  
배포의 다음 예제 구성 업데이트에서는 권한 부여 정책을 정의하는 `accessControl` 객체로 구성 요소를 구성하도록 지정합니다. 이 정책은 `com.example.HelloWorld` 구성 요소에 `test/topic` 주제에 게시할 수 있는 권한을 부여합니다.    
**병합할 구성**  

```
{
  "accessControl": {
    "aws.greengrass.ipc.pubsub": {
      "com.example.HelloWorld:pubsub:1": {
        "policyDescription": "Allows access to publish to test/topic.",
        "operations": [
          "aws.greengrass#PublishToTopic"
        ],
        "resources": [
          "test/topic"
        ]
      }
    }
  }
}
```
다음 명령은 코어 디바이스에 배포를 생성합니다.  

```
aws greengrassv2 create-deployment --cli-input-json file://hello-world-deployment.json
```
`hello-world-deployment.json` 파일에는 다음 JSON 문서가 포함되어 있습니다.  

```
{
  "targetArn": "arn:aws:iot:us-west-2:123456789012:thing/MyGreengrassCore",
  "deploymentName": "Deployment for MyGreengrassCore",
  "components": {
    "com.example.HelloWorld": {
      "componentVersion": "1.0.0",
      "configurationUpdate": {
        "merge": "{\"accessControl\":{\"aws.greengrass.ipc.pubsub\":{\"com.example.HelloWorld:pubsub:1\":{\"policyDescription\":\"Allows access to publish to test/topic.\",\"operations\":[\"aws.greengrass#PublishToTopic\"],\"resources\":[\"test/topic\"]}}}}"
      }
    }
  }
}
```
다음 [Greengrass CLI](greengrass-cli-component.md) 명령은 코어 디바이스에 로컬 배포를 생성합니다.  

```
sudo greengrass-cli deployment create \
  --recipeDir recipes \
  --artifactDir artifacts \
  --merge "com.example.HelloWorld=1.0.0" \
  --update-config hello-world-configuration.json
```
`hello-world-configuration.json` 파일에는 다음 JSON 문서가 포함되어 있습니다.  

```
{
  "com.example.HelloWorld": {
    "MERGE": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.HelloWorld:pubsub:1": {
            "policyDescription": "Allows access to publish to test/topic.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "test/topic"
            ]
          }
        }
      }
    }
  }
}
```

## IPC 이벤트 스트림 구독
<a name="ipc-subscribe-operations"></a>

IPC 작업을 사용하여 Greengrass 코어 디바이스에서 이벤트 스트림을 구독할 수 있습니다. 구독 작업을 사용하려면 *구독 핸들러*를 정의하고 IPC 서비스에 대한 요청을 생성합니다. 그런 다음 IPC 클라이언트는 코어 디바이스가 구성 요소에 이벤트 메시지를 스트리밍할 때마다 구독 핸들러의 함수를 실행합니다.

구독을 닫아 이벤트 메시지 처리를 중지할 수 있습니다. 이렇게 하려면 구독을 여는 데 사용한 구독 작업 객체에 대해 `closeStream()`(Java), `close()`(Python) 또는 `Close()`(C\$1\$1)를 직접 호출합니다.

 AWS IoT Greengrass 코어 IPC 서비스는 다음 구독 작업을 지원합니다.
+ [SubscribeToTopic](ipc-publish-subscribe.md#ipc-operation-subscribetotopic)
+ [SubscribeToIoTCore](ipc-iot-core-mqtt.md#ipc-operation-subscribetoiotcore)
+ [SubscribeToComponentUpdates](ipc-component-lifecycle.md#ipc-operation-subscribetocomponentupdates)
+ [SubscribeToConfigurationUpdate](ipc-component-configuration.md#ipc-operation-subscribetoconfigurationupdate)
+ [SubscribeToValidateConfigurationUpdates](ipc-component-configuration.md#ipc-operation-subscribetovalidateconfigurationupdates)

**Topics**
+ [구독 핸들러 정의](#ipc-define-subscription-handlers)
+ [구독 핸들러 예제](#ipc-subscription-handler-examples)

### 구독 핸들러 정의
<a name="ipc-define-subscription-handlers"></a>

구독 핸들러를 정의하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 콜백 함수를 정의합니다. IPC 클라이언트 V1을 사용하는 경우 클래스에서 이러한 함수를 정의해야 합니다. 이후 버전의 Java 및 Python SDK에서 사용할 수 있는 IPC 클라이언트 V2를 사용하는 경우 구독 핸들러 클래스를 생성하지 않고도 이러한 함수를 정의할 수 있습니다.

------
#### [ Java ]

IPC 클라이언트 V1을 사용하는 경우 일반 `software.amazon.awssdk.eventstreamrpc.StreamResponseHandler<StreamEventType>` 인터페이스를 구현해야 합니다. *StreamEventType*은 구독 작업에 대한 이벤트 메시지의 유형입니다. 이벤트 메시지, 오류 및 스트림 종료를 처리하는 다음 함수를 정의합니다.

IPC 클라이언트 V2를 사용하는 경우 구독 핸들러 클래스 외부에서 이러한 함수를 정의하거나 [lambda 표현식](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)을 사용할 수 있습니다.

`void onStreamEvent(StreamEventType event)`  
IPC 클라이언트가 MQTT 메시지 또는 구성 요소 업데이트 알림과 같은 이벤트 메시지를 수신할 때 직접 호출하는 콜백입니다.

`boolean onStreamError(Throwable error)`  
스트림 오류가 발생할 때 IPC 클라이언트가 직접 호출하는 콜백입니다.  
<a name="ipc-subscription-handler-on-stream-error-return-value"></a>오류로 인해 구독 스트림을 닫으려면 true를 반환하고 스트림을 열린 상태로 유지하려면 false를 반환합니다.

`void onStreamClosed()`  
스트림이 닫힐 때 IPC 클라이언트가 직접 호출하는 콜백입니다.

------
#### [ Python ]

IPC 클라이언트 V1을 사용하는 경우 구독 작업에 해당하는 스트림 응답 핸들러 클래스를 확장해야 합니다. 에는 각 구독 작업에 대한 구독 핸들러 클래스가 AWS IoT Device SDK 포함되어 있습니다. *StreamEventType*은 구독 작업에 대한 이벤트 메시지의 유형입니다. 이벤트 메시지, 오류 및 스트림 종료를 처리하는 다음 함수를 정의합니다.

IPC 클라이언트 V2를 사용하는 경우 구독 핸들러 클래스 외부에서 이러한 함수를 정의하거나 [lambda 표현식](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions)을 사용할 수 있습니다.

`def on_stream_event(self, event: StreamEventType) -> None`  
IPC 클라이언트가 MQTT 메시지 또는 구성 요소 업데이트 알림과 같은 이벤트 메시지를 수신할 때 직접 호출하는 콜백입니다.

`def on_stream_error(self, error: Exception) -> bool`  
스트림 오류가 발생할 때 IPC 클라이언트가 직접 호출하는 콜백입니다.  
<a name="ipc-subscription-handler-on-stream-error-return-value"></a>오류로 인해 구독 스트림을 닫으려면 true를 반환하고 스트림을 열린 상태로 유지하려면 false를 반환합니다.

`def on_stream_closed(self) -> None`  
스트림이 닫힐 때 IPC 클라이언트가 직접 호출하는 콜백입니다.

------
#### [ C\$1\$1 (IPC client V1) ]

구독 작업에 해당하는 스트림 응답 핸들러 클래스에서 파생되는 클래스를 구현합니다. 에는 각 구독 작업에 대한 구독 핸들러 기본 클래스가 AWS IoT Device SDK 포함되어 있습니다. *StreamEventType*은 구독 작업에 대한 이벤트 메시지의 유형입니다. 이벤트 메시지, 오류 및 스트림 종료를 처리하는 다음 함수를 정의합니다.

`void OnStreamEvent(StreamEventType *event)`  
IPC 클라이언트가 MQTT 메시지 또는 구성 요소 업데이트 알림과 같은 이벤트 메시지를 수신할 때 직접 호출하는 콜백입니다.

`bool OnStreamError(OperationError *error)`  
스트림 오류가 발생할 때 IPC 클라이언트가 직접 호출하는 콜백입니다.  
<a name="ipc-subscription-handler-on-stream-error-return-value"></a>오류로 인해 구독 스트림을 닫으려면 true를 반환하고 스트림을 열린 상태로 유지하려면 false를 반환합니다.

`void OnStreamClosed()`  
스트림이 닫힐 때 IPC 클라이언트가 직접 호출하는 콜백입니다.

------
#### [ JavaScript ]

구독 작업에 해당하는 스트림 응답 핸들러 클래스에서 파생되는 클래스를 구현합니다. 에는 각 구독 작업에 대한 구독 핸들러 기본 클래스가 AWS IoT Device SDK 포함되어 있습니다. *StreamEventType*은 구독 작업에 대한 이벤트 메시지의 유형입니다. 이벤트 메시지, 오류 및 스트림 종료를 처리하는 다음 함수를 정의합니다.

`on(event: 'ended', listener: StreamingOperationEndedListener)`  
스트림이 닫힐 때 IPC 클라이언트가 직접 호출하는 콜백입니다.

`on(event: 'streamError', listener: StreamingRpcErrorListener)`  
스트림 오류가 발생할 때 IPC 클라이언트가 직접 호출하는 콜백입니다.  
<a name="ipc-subscription-handler-on-stream-error-return-value"></a>오류로 인해 구독 스트림을 닫으려면 true를 반환하고 스트림을 열린 상태로 유지하려면 false를 반환합니다.

`on(event: 'message', listener: (message: InboundMessageType) => void)`  
IPC 클라이언트가 MQTT 메시지 또는 구성 요소 업데이트 알림과 같은 이벤트 메시지를 수신할 때 직접 호출하는 콜백입니다.

------

### 구독 핸들러 예제
<a name="ipc-subscription-handler-examples"></a>

다음 예제에서는 [SubscribeToTopic](ipc-publish-subscribe.md#ipc-operation-subscribetotopic) 작업 및 구독 핸들러를 사용하여 로컬 게시/구독 메시지를 구독하는 방법을 보여줍니다.

------
#### [ Java (IPC client V2) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-java-v2"></a>

```
package com.aws.greengrass.docs.samples.ipc;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.SubscribeToTopicResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.*;

import java.nio.charset.StandardCharsets;
import java.util.Optional;

public class SubscribeToTopicV2 {

    public static void main(String[] args) {
        String topic = args[0];
        try (GreengrassCoreIPCClientV2 ipcClient = GreengrassCoreIPCClientV2.builder().build()) {
            SubscribeToTopicRequest request = new SubscribeToTopicRequest().withTopic(topic);
            GreengrassCoreIPCClientV2.StreamingResponse<SubscribeToTopicResponse,
                    SubscribeToTopicResponseHandler> response =
                    ipcClient.subscribeToTopic(request, SubscribeToTopicV2::onStreamEvent,
                            Optional.of(SubscribeToTopicV2::onStreamError),
                            Optional.of(SubscribeToTopicV2::onStreamClosed));
            SubscribeToTopicResponseHandler responseHandler = response.getHandler();
            System.out.println("Successfully subscribed to topic: " + topic);

            // Keep the main thread alive, or the process will exit.
            try {
                while (true) {
                    Thread.sleep(10000);
                }
            } catch (InterruptedException e) {
                System.out.println("Subscribe interrupted.");
            }

            // To stop subscribing, close the stream.
            responseHandler.closeStream();
        } catch (Exception e) {
            if (e.getCause() instanceof UnauthorizedError) {
                System.err.println("Unauthorized error while publishing to topic: " + topic);
            } else {
                System.err.println("Exception occurred when using IPC.");
            }
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static void onStreamEvent(SubscriptionResponseMessage subscriptionResponseMessage) {
        try {
            BinaryMessage binaryMessage = subscriptionResponseMessage.getBinaryMessage();
            String message = new String(binaryMessage.getMessage(), StandardCharsets.UTF_8);
            String topic = binaryMessage.getContext().getTopic();
            System.out.printf("Received new message on topic %s: %s%n", topic, message);
        } catch (Exception e) {
            System.err.println("Exception occurred while processing subscription response " +
                    "message.");
            e.printStackTrace();
        }
    }

    public static boolean onStreamError(Throwable error) {
        System.err.println("Received a stream error.");
        error.printStackTrace();
        return false; // Return true to close stream, false to keep stream open.
    }

    public static void onStreamClosed() {
        System.out.println("Subscribe to topic stream closed.");
    }
}
```

------
#### [ Python (IPC client V2) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-python-v2"></a>

```
import sys
import time
import traceback

from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
from awsiot.greengrasscoreipc.model import (
    SubscriptionResponseMessage,
    UnauthorizedError
)


def main():
    args = sys.argv[1:]
    topic = args[0]

    try:
        ipc_client = GreengrassCoreIPCClientV2()
        # Subscription operations return a tuple with the response and the operation.
        _, operation = ipc_client.subscribe_to_topic(topic=topic, on_stream_event=on_stream_event,
                                                     on_stream_error=on_stream_error, on_stream_closed=on_stream_closed)
        print('Successfully subscribed to topic: ' + topic)

        # Keep the main thread alive, or the process will exit.
        try:
            while True:
                time.sleep(10)
        except InterruptedError:
            print('Subscribe interrupted.')

        # To stop subscribing, close the stream.
        operation.close()
    except UnauthorizedError:
        print('Unauthorized error while subscribing to topic: ' +
              topic, file=sys.stderr)
        traceback.print_exc()
        exit(1)
    except Exception:
        print('Exception occurred', file=sys.stderr)
        traceback.print_exc()
        exit(1)


def on_stream_event(event: SubscriptionResponseMessage) -> None:
    try:
        message = str(event.binary_message.message, 'utf-8')
        topic = event.binary_message.context.topic
        print('Received new message on topic %s: %s' % (topic, message))
    except:
        traceback.print_exc()


def on_stream_error(error: Exception) -> bool:
    print('Received a stream error.', file=sys.stderr)
    traceback.print_exc()
    return False  # Return True to close stream, False to keep stream open.


def on_stream_closed() -> None:
    print('Subscribe to topic stream closed.')


if __name__ == '__main__':
    main()
```

------
#### [ C\$1\$1 (IPC client V1) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-cpp"></a>

```
#include <iostream>

#include </crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class SubscribeResponseHandler : public SubscribeToTopicStreamHandler {
    public:
        virtual ~SubscribeResponseHandler() {}

    private:
        void OnStreamEvent(SubscriptionResponseMessage *response) override {
            auto jsonMessage = response->GetJsonMessage();
            if (jsonMessage.has_value() && jsonMessage.value().GetMessage().has_value()) {
                auto messageString = jsonMessage.value().GetMessage().value().View().WriteReadable();
                // Handle JSON message.
            } else {
                auto binaryMessage = response->GetBinaryMessage();
                if (binaryMessage.has_value() && binaryMessage.value().GetMessage().has_value()) {
                    auto messageBytes = binaryMessage.value().GetMessage().value();
                    std::string messageString(messageBytes.begin(), messageBytes.end());
                    // Handle binary message.
                }
            }
        }

        bool OnStreamError(OperationError *error) override {
            // Handle error.
            return false; // Return true to close stream, false to keep stream open.
        }

        void OnStreamClosed() override {
            // Handle close.
        }
};

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        // Handle connection to IPC service.
    }

    void OnDisconnectCallback(RpcError error) override {
        // Handle disconnection from IPC service.
    }

    bool OnErrorCallback(RpcError error) override {
        // Handle IPC service connection error.
        return true;
    }
};

int main() {
    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    String topic("my/topic");
    int timeout = 10;

    SubscribeToTopicRequest request;
    request.SetTopic(topic);

    //SubscribeResponseHandler streamHandler;
    auto streamHandler = MakeShared<SubscribeResponseHandler>(DefaultAllocator());
    auto operation = ipcClient.NewSubscribeToTopic(streamHandler);
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (!response) {
        // Handle error.
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            (void)error;
            // Handle operation error.
        } else {
            // Handle RPC error.
        }
        exit(-1);
    }

    // Keep the main thread alive, or the process will exit.
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    operation->Close();
    return 0;
}
```

------
#### [ JavaScript ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-nodejs"></a>

```
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
import {SubscribeToTopicRequest, SubscriptionResponseMessage} from "aws-iot-device-sdk-v2/dist/greengrasscoreipc/model";
import {RpcError} from "aws-iot-device-sdk-v2/dist/eventstream_rpc";
 
class SubscribeToTopic {
    private ipcClient : greengrasscoreipc.Client
    private readonly topic : string;
 
    constructor() {
        // define your own constructor, e.g.
        this.topic = "<define_your_topic>";
        this.subscribeToTopic().then(r => console.log("Started workflow"));
    }
 
    private async subscribeToTopic() {
        try {
            this.ipcClient = await getIpcClient();
 
            const subscribeToTopicRequest : SubscribeToTopicRequest = {
                topic: this.topic,
            }
 
            const streamingOperation = this.ipcClient.subscribeToTopic(subscribeToTopicRequest, undefined); // conditionally apply options
 
            streamingOperation.on("message", (message: SubscriptionResponseMessage) => {
                // parse the message depending on your use cases, e.g.
                if(message.binaryMessage && message.binaryMessage.message) {
                    const receivedMessage = message.binaryMessage?.message.toString();
                }
            });
 
            streamingOperation.on("streamError", (error : RpcError) => {
                // define your own error handling logic
            })
 
            streamingOperation.on("ended", () => {
                // define your own logic
            })
 
            await streamingOperation.activate();
 
            // Keep the main thread alive, or the process will exit.
            await new Promise((resolve) => setTimeout(resolve, 10000))
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
// starting point
const subscribeToTopic = new SubscribeToTopic();
```

------
#### [ Rust ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
use gg_sdk::{Sdk, SubscribeToTopicPayload};
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let topic = "my/topic";

    let callback = |topic: &str, payload: SubscribeToTopicPayload| match payload
    {
        SubscribeToTopicPayload::Binary(message) => {
            let message = String::from_utf8_lossy(message);
            println!("Received new message on topic {topic}: {message}");
        }
        SubscribeToTopicPayload::Json(_) => {
            println!("Received new message on topic {topic}: (JSON message)");
        }
    };

    let _sub = sdk
        .subscribe_to_topic(topic, &callback)
        .expect("Failed to subscribe to topic");

    println!("Successfully subscribed to topic: {topic}");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

------
#### [ C ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
#include <assert.h>
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <gg/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx, GgBuffer topic, GgObject payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    if (gg_obj_type(payload) == GG_TYPE_BUF) {
        GgBuffer message = gg_obj_into_buf(payload);
        printf(
            "Received new message on topic %.*s: %.*s\n",
            (int) topic.len,
            topic.data,
            (int) message.len,
            message.data
        );
    } else {
        assert(gg_obj_type(payload) == GG_TYPE_MAP);
        printf(
            "Received new message on topic %.*s: (JSON message)\n",
            (int) topic.len,
            topic.data
        );
    }
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer topic = GG_STR("my/topic");

    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_topic(
        topic, on_subscription_response, NULL, &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to subscribe to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully subscribed to topic: %.*s\n", (int) topic.len, topic.data
    );

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the stream.
    ggipc_close_subscription(handle);
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
#include <gg/ipc/client.hpp>
#include <gg/object.hpp>
#include <unistd.h>
#include <cassert>
#include <iostream>

class ResponseHandler : public gg::ipc::LocalTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Object payload,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        if (payload.index() == GG_TYPE_BUF) {
            std::cout << "Received new message on topic " << topic << ": "
                      << get<gg::Buffer>(payload) << "\n";
        } else {
            assert(payload.index() == GG_TYPE_MAP);
            std::cout << "Received new message on topic " << topic
                      << ": (JSON message)\n";
        }
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view topic = "my/topic";

    static ResponseHandler handler;
    error = client.subscribe_to_topic(topic, handler);
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to topic: " << topic << "\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

------

## IPC 모범 사례
<a name="ipc-best-practices"></a>

사용자 지정 구성 요소에서 IPC를 사용하는 모범 사례는 IPC 클라이언트 V1과 IPC 클라이언트 V2 간에 다릅니다. 사용하는 IPC 클라이언트 버전에 대한 모범 사례를 따르세요.

------
#### [ IPC client V2 ]

IPC 클라이언트 V2는 별도의 스레드에서 콜백 함수를 실행하므로 IPC 클라이언트 V1에 비해 IPC를 사용하고 구독 핸들러 함수 작성할 때 따라야 할 지침이 더 적습니다.
+ <a name="ipc-best-practice-reuse-one-client"></a>**하나의 IPC 클라이언트 재사용**

  IPC 클라이언트를 생성한 후 계속 열어 두고 모든 IPC 작업에 재사용합니다. 여러 클라이언트를 생성하면 추가 리소스가 사용되어 리소스가 누출될 수 있습니다.
+ **예외 처리**

  IPC 클라이언트 V2는 구독 핸들러 함수의 catch되지 않은 예외를 기록합니다. 코드에서 발생하는 오류를 처리하려면 핸들러 함수의 예외를 catch해야 합니다.

------
#### [ IPC client V1 ]

IPC 클라이언트 V1은 IPC 서버와 통신하고 구독 핸들러를 직접 호출하는 단일 스레드를 사용합니다. 구독 핸들러 함수를 작성할 때는 이 동기 동작을 고려해야 합니다.
+ <a name="ipc-best-practice-reuse-one-client"></a>**하나의 IPC 클라이언트 재사용**

  IPC 클라이언트를 생성한 후 계속 열어 두고 모든 IPC 작업에 재사용합니다. 여러 클라이언트를 생성하면 추가 리소스가 사용되어 리소스가 누출될 수 있습니다.
+ **비동기적으로 차단 코드 실행**

  IPC 클라이언트 V1은 스레드가 차단된 동안 새 요청을 보내거나 새 이벤트 메시지를 처리할 수 없습니다. 핸들러 함수에서 실행하는 별도의 스레드에서 차단 코드를 실행해야 합니다. 차단 코드에는 `sleep` 호출, 지속적으로 실행되는 루프 및 완료하는 데 시간이 걸리는 동기 I/O 요청이 포함됩니다.
+ **비동기적으로 새 IPC 요청 전송**

  IPC 클라이언트 V1은 구독 핸들러 함수 내에서 새 요청을 보낼 수 없습니다. 응답을 기다리는 경우 요청에서 핸들러 함수를 차단하기 때문입니다. 핸들러 함수에서 실행하는 별도의 스레드에서 IPC 요청을 보내야 합니다.
+ **예외 처리**

  IPC 클라이언트 V1은 구독 핸들러 함수의 catch되지 않은 예외를 기록합니다. 핸들러 함수에서 예외를 throw하면 구독이 종료되고 구성 요소 로그에 예외가 표시되지 않습니다. 구독을 열린 상태로 유지하고 코드에서 발생하는 오류를 기록하려면 핸들러 함수의 예외를 catch해야 합니다.

------

# 로컬 메시지 게시/구독
<a name="ipc-publish-subscribe"></a>

게시/구독(pubsub) 메시징을 사용하면 주제에 메시지를 보내고 주제에서 메시지를 받을 수 있습니다. 구성 요소가 주제에 메시지를 게시하여 다른 구성 요소에 메시지를 보낼 수 있습니다. 그러면 해당 주제를 구독하는 구성 요소가 수신하는 메시지에 대한 작업을 수행할 수 있습니다.

**참고**  
이 게시/구독 IPC 서비스를 사용하여 AWS IoT Core MQTT를 게시하거나 구독할 수 없습니다. AWS IoT Core MQTT와 메시지를 교환하는 방법에 대한 자세한 내용은 섹션을 참조하세요[AWS IoT Core MQTT 메시지 게시/구독](ipc-iot-core-mqtt.md).

**Topics**
+ [최소 SDK 버전](#ipc-publish-subscribe-sdk-versions)
+ [권한 부여](#ipc-publish-subscribe-authorization)
+ [PublishToTopic](#ipc-operation-publishtotopic)
+ [SubscribeToTopic](#ipc-operation-subscribetotopic)
+ [예제](#ipc-publish-subscribe-examples)

## 최소 SDK 버전
<a name="ipc-publish-subscribe-sdk-versions"></a>

다음 표에는 로컬 주제에 메시지를 게시하고 구독하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK for JavaScript](https://github.com/aws/aws-iot-device-sdk-js-v2) v2  |  v1.12.0  | 

## 권한 부여
<a name="ipc-publish-subscribe-authorization"></a>

사용자 지정 구성 요소에서 로컬 게시/구독 메시징을 사용하려면 구성 요소가 주제에 대한 메시지를 보내고 받을 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

게시/구독 메시징에 대한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.ipc.pubsub`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#PublishToTopic`  |  구성 요소가 지정한 주제에 메시지를 게시할 수 있도록 허용합니다.  |  `test/topic`과 같은 주제 문자열입니다. 주제의 임의의 문자 조합과 일치시키려면 `*`를 사용합니다. 이 주제 문자열에서는 MQTT 주제 와일드카드(`#` 및 `+`)를 지원하지 않습니다.  | 
|  `aws.greengrass#SubscribeToTopic`  |  구성 요소가 지정하는 주제에 대한 메시지를 구독할 수 있도록 허용합니다.  |  `test/topic`과 같은 주제 문자열입니다. 주제의 임의의 문자 조합과 일치시키려면 `*`를 사용합니다. <a name="ipc-local-publish-subscribe-authorization-mqtt-wildcards"></a>[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서는 MQTT 주제 와일드카드(`#` 및 `+`)가 포함된 주제를 구독할 수 있습니다. 이 주제 문자열은 MQTT 주제 와일드카드를 리터럴 문자로 지원합니다. 예를 들어 구성 요소의 권한 부여 정책에서 `test/topic/#`에 대한 액세스 권한을 부여하는 경우 구성 요소는 `test/topic/#`는 구독할 수 있지만 `test/topic/filter`는 구독할 수 없습니다.  | 
|  `*`  |  구성 요소가 지정하는 주제에 대한 메시지를 게시하고 구독할 수 있도록 허용합니다.  |  `test/topic`과 같은 주제 문자열입니다. 주제의 임의의 문자 조합과 일치시키려면 `*`를 사용합니다. <a name="ipc-local-publish-subscribe-authorization-mqtt-wildcards"></a>[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서는 MQTT 주제 와일드카드(`#` 및 `+`)가 포함된 주제를 구독할 수 있습니다. 이 주제 문자열은 MQTT 주제 와일드카드를 리터럴 문자로 지원합니다. 예를 들어 구성 요소의 권한 부여 정책에서 `test/topic/#`에 대한 액세스 권한을 부여하는 경우 구성 요소는 `test/topic/#`는 구독할 수 있지만 `test/topic/filter`는 구독할 수 없습니다.  | 

### 권한 부여 정책 예제
<a name="ipc-publish-subscribe-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 권한 부여 정책 예제**  
다음 권한 부여 정책 예제에서는 구성 요소가 모든 주제를 게시하고 구독할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.pubsub": {
      "com.example.MyLocalPubSubComponent:pubsub:1": {
        "policyDescription": "Allows access to publish/subscribe to all topics.",
        "operations": [
          "aws.greengrass#PublishToTopic",
          "aws.greengrass#SubscribeToTopic"
        ],
        "resources": [
          "*"
        ]
      }
    }
  }
}
```

## PublishToTopic
<a name="ipc-operation-publishtotopic"></a>

주제에 메시지를 게시합니다.

### 요청
<a name="ipc-operation-publishtotopic-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`topic`  
메시지를 게시할 주제입니다.

`publishMessage`(Python: `publish_message`)  
게시할 메시지입니다. 이 객체 `PublishMessage`에는 다음 정보가 포함됩니다. `jsonMessage` 및 `binaryMessage` 중 하나를 지정해야 합니다.  <a name="ipc-publish-subscribe-message-shape"></a>  
`jsonMessage`(Python: `json_message`)  
(선택 사항) JSON 메시지입니다. 이 객체 `JsonMessage`에는 다음 정보가 포함됩니다.    
`message`  
객체인 JSON 메시지입니다.  
`context`  <a name="ipc-publish-subscribe-message-context-variable"></a>
메시지가 게시된 주제와 같은 메시지의 컨텍스트입니다.  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다. 다음 표에는 메시지 컨텍스트에 액세스하기 위해 사용해야 하는 AWS IoT Device SDK 의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-publish-subscribe.html)
 AWS IoT Greengrass 코어 소프트웨어는 `PublishToTopic` 및 `SubscribeToTopic` 작업에서 동일한 메시지 객체를 사용합니다. AWS IoT Greengrass 코어 소프트웨어는 구독 시 메시지에서이 컨텍스트 객체를 설정하고 게시하는 메시지에서이 컨텍스트 객체를 무시합니다.
이 객체 `MessageContext`에는 다음 정보가 포함됩니다.    
`topic`  
메시지가 게시된 주제입니다.  
`binaryMessage`(Python: `binary_message`)  
(선택 사항) 이진 메시지입니다. 이 객체 `BinaryMessage`에는 다음 정보가 포함됩니다.    
`message`  
Blob인 이진 메시지입니다.  
`context`  <a name="ipc-publish-subscribe-message-context-variable"></a>
메시지가 게시된 주제와 같은 메시지의 컨텍스트입니다.  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다. 다음 표에는 메시지 컨텍스트에 액세스하기 위해 사용해야 하는 AWS IoT Device SDK 의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-publish-subscribe.html)
 AWS IoT Greengrass 코어 소프트웨어는 `PublishToTopic` 및 `SubscribeToTopic` 작업에서 동일한 메시지 객체를 사용합니다. AWS IoT Greengrass 코어 소프트웨어는 구독 시 메시지에서이 컨텍스트 객체를 설정하고 게시하는 메시지에서이 컨텍스트 객체를 무시합니다.
이 객체 `MessageContext`에는 다음 정보가 포함됩니다.    
`topic`  
메시지가 게시된 주제입니다.

### 응답
<a name="ipc-operation-publishtotopic-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

### 예제
<a name="ipc-operation-publishtotopic-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V2) ]

**Example 예: 이진 메시지 게시**  

```
package com.aws.greengrass.docs.samples.ipc;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.model.BinaryMessage;
import software.amazon.awssdk.aws.greengrass.model.PublishMessage;
import software.amazon.awssdk.aws.greengrass.model.PublishToTopicRequest;
import software.amazon.awssdk.aws.greengrass.model.PublishToTopicResponse;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;

import java.nio.charset.StandardCharsets;

public class PublishToTopicV2 {

    public static void main(String[] args) {
        String topic = args[0];
        String message = args[1];
        try (GreengrassCoreIPCClientV2 ipcClient = GreengrassCoreIPCClientV2.builder().build()) {
            PublishToTopicV2.publishBinaryMessageToTopic(ipcClient, topic, message);
            System.out.println("Successfully published to topic: " + topic);
        } catch (Exception e) {
            if (e.getCause() instanceof UnauthorizedError) {
                System.err.println("Unauthorized error while publishing to topic: " + topic);
            } else {
                System.err.println("Exception occurred when using IPC.");
            }
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static PublishToTopicResponse publishBinaryMessageToTopic(
            GreengrassCoreIPCClientV2 ipcClient, String topic, String message) throws InterruptedException {
        BinaryMessage binaryMessage =
                new BinaryMessage().withMessage(message.getBytes(StandardCharsets.UTF_8));
        PublishMessage publishMessage = new PublishMessage().withBinaryMessage(binaryMessage);
        PublishToTopicRequest publishToTopicRequest =
                new PublishToTopicRequest().withTopic(topic).withPublishMessage(publishMessage);
        return ipcClient.publishToTopic(publishToTopicRequest);
    }
}
```

------
#### [ Python (IPC client V2) ]

**Example 예: 이진 메시지 게시**  

```
import sys
import traceback

from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
from awsiot.greengrasscoreipc.model import (
    PublishMessage,
    BinaryMessage
)


def main():
    args = sys.argv[1:]
    topic = args[0]
    message = args[1]

    try:
        ipc_client = GreengrassCoreIPCClientV2()
        publish_binary_message_to_topic(ipc_client, topic, message)
        print('Successfully published to topic: ' + topic)
    except Exception:
        print('Exception occurred', file=sys.stderr)
        traceback.print_exc()
        exit(1)


def publish_binary_message_to_topic(ipc_client, topic, message):
    binary_message = BinaryMessage(message=bytes(message, 'utf-8'))
    publish_message = PublishMessage(binary_message=binary_message)
    return ipc_client.publish_to_topic(topic=topic, publish_message=publish_message)


if __name__ == '__main__':
    main()
```

------
#### [ C\$1\$1 (IPC client V1) ]

**Example 예: 이진 메시지 게시**  

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        // Handle connection to IPC service.
    }

    void OnDisconnectCallback(RpcError error) override {
        // Handle disconnection from IPC service.
    }

    bool OnErrorCallback(RpcError error) override {
        // Handle IPC service connection error.
        return true;
    }
};

int main() {
    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    String topic("my/topic");
    String message("Hello, World!");
    int timeout = 10;

    PublishToTopicRequest request;
    Vector<uint8_t> messageData({message.begin(), message.end()});
    BinaryMessage binaryMessage;
    binaryMessage.SetMessage(messageData);
    PublishMessage publishMessage;
    publishMessage.SetBinaryMessage(binaryMessage);
    request.SetTopic(topic);
    request.SetPublishMessage(publishMessage);

    auto operation = ipcClient.NewPublishToTopic();
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (!response) {
        // Handle error.
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            (void)error;
            // Handle operation error.
        } else {
            // Handle RPC error.
        }
    }
    return 0;
}
```

------
#### [ JavaScript ]

**Example 예: 이진 메시지 게시**  

```
    
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
import {BinaryMessage, PublishMessage, PublishToTopicRequest} from "aws-iot-device-sdk-v2/dist/greengrasscoreipc/model";
 
class PublishToTopic {
    private ipcClient : greengrasscoreipc.Client
    private readonly topic : string;
    private readonly messageString : string;
 
    constructor() {
        // define your own constructor, e.g.
        this.topic = "<define_your_topic>";
        this.messageString = "<define_your_message_string>";
        this.publishToTopic().then(r => console.log("Started workflow"));
    }
 
    private async publishToTopic() {
        try {
            this.ipcClient = await getIpcClient();
 
            const binaryMessage : BinaryMessage = {
                message: this.messageString
            }
 
            const publishMessage : PublishMessage = {
                binaryMessage: binaryMessage
            }
 
            const request : PublishToTopicRequest = {
                topic: this.topic,
                publishMessage: publishMessage
            }
 
            this.ipcClient.publishToTopic(request).finally(() => console.log(`Published message ${publishMessage.binaryMessage?.message} to topic`))
 
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
// starting point
const publishToTopic = new PublishToTopic();
```

------
#### [ Rust ]

**Example 예: 이진 메시지 게시**  

```
use gg_sdk::Sdk;

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let message = b"Hello, World";
    let topic = "my/topic";

    sdk.publish_to_topic_binary(topic, message)
        .expect("Failed to publish to topic");

    println!("Successfully published to topic: {topic}");
}
```

------
#### [ C ]

**Example 예: 이진 메시지 게시**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer message = GG_STR("Hello, World");
    GgBuffer topic = GG_STR("my/topic");

    err = ggipc_publish_to_topic_binary(topic, message);
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to publish to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully published to topic: %.*s\n", (int) topic.len, topic.data
    );
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 이진 메시지 게시**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view message = "Hello, World";
    std::string_view topic = "my/topic";

    error = client.publish_to_topic(topic, message);
    if (error) {
        std::cerr << "Failed to publish to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully published to topic: " << topic << "\n";
}
```

------

## SubscribeToTopic
<a name="ipc-operation-subscribetotopic"></a>

주제에 대한 메시지를 구독합니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `SubscriptionResponseMessage`

### 요청
<a name="ipc-operation-subscribetotopic-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`topic`  
구독할 주제입니다.  
[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서 이 주제는 MQTT 주제 와일드카드(`#` 및 `+`)를 지원합니다.

`receiveMode`(Python: `receive_mode`)  
(선택 사항) 구성 요소가 자체에서 메시지를 수신하는지 여부를 지정하는 동작입니다. 이 동작을 변경하여 구성 요소가 자체 메시지에 대해 조치하도록 허용할 수 있습니다. 기본 동작은 주제에 MQTT 와일드카드가 포함되어 있는지 여부에 따라 달라집니다. 다음 옵션 중 하나를 선택합니다.  
+ `RECEIVE_ALL_MESSAGES` - 구독하는 구성 요소의 메시지를 포함하여 주제와 일치하는 모든 메시지를 수신합니다.

  이 모드는 MQTT 와일드카드가 포함되지 않은 주제를 구독할 때 기본 옵션입니다.
+ `RECEIVE_MESSAGES_FROM_OTHERS` - 구독하는 구성 요소의 메시지를 제외하고 주제와 일치하는 모든 메시지를 수신합니다.

  이 모드는 MQTT 와일드카드가 포함된 주제를 구독할 때 기본 옵션입니다.
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다. 다음 표에는 수신 모드를 설정하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-publish-subscribe.html)

### 응답
<a name="ipc-operation-subscribetotopic-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
메시지 스트림입니다. 이 객체 `SubscriptionResponseMessage`에는 다음 정보가 포함됩니다. 각 메시지에는 `jsonMessage` 또는 `binaryMessage`가 포함됩니다.  <a name="ipc-publish-subscribe-message-shape"></a>  
`jsonMessage`(Python: `json_message`)  
(선택 사항) JSON 메시지입니다. 이 객체 `JsonMessage`에는 다음 정보가 포함됩니다.    
`message`  
객체인 JSON 메시지입니다.  
`context`  <a name="ipc-publish-subscribe-message-context-variable"></a>
메시지가 게시된 주제와 같은 메시지의 컨텍스트입니다.  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다. 다음 표에는 메시지 컨텍스트에 액세스하기 위해 사용해야 하는 AWS IoT Device SDK 의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-publish-subscribe.html)
 AWS IoT Greengrass 코어 소프트웨어는 `PublishToTopic` 및 `SubscribeToTopic` 작업에서 동일한 메시지 객체를 사용합니다. AWS IoT Greengrass 코어 소프트웨어는 구독 시 메시지에서이 컨텍스트 객체를 설정하고 게시하는 메시지에서이 컨텍스트 객체를 무시합니다.
이 객체 `MessageContext`에는 다음 정보가 포함됩니다.    
`topic`  
메시지가 게시된 주제입니다.  
`binaryMessage`(Python: `binary_message`)  
(선택 사항) 이진 메시지입니다. 이 객체 `BinaryMessage`에는 다음 정보가 포함됩니다.    
`message`  
Blob인 이진 메시지입니다.  
`context`  <a name="ipc-publish-subscribe-message-context-variable"></a>
메시지가 게시된 주제와 같은 메시지의 컨텍스트입니다.  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다. 다음 표에는 메시지 컨텍스트에 액세스하기 위해 사용해야 하는 AWS IoT Device SDK 의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-publish-subscribe.html)
 AWS IoT Greengrass 코어 소프트웨어는 `PublishToTopic` 및 `SubscribeToTopic` 작업에서 동일한 메시지 객체를 사용합니다. AWS IoT Greengrass 코어 소프트웨어는 구독 시 메시지에서이 컨텍스트 객체를 설정하고 게시하는 메시지에서이 컨텍스트 객체를 무시합니다.
이 객체 `MessageContext`에는 다음 정보가 포함됩니다.    
`topic`  
메시지가 게시된 주제입니다.

`topicName`(Python: `topic_name`)  
메시지가 게시된 주제입니다.  
이 속성은 현재 사용되지 않습니다. [Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서는 `SubscriptionResponseMessage`에서 `(jsonMessage|binaryMessage).context.topic` 값을 가져와 메시지가 게시된 주제를 가져올 수 있습니다.

### 예제
<a name="ipc-operation-subscribetotopic-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V2) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-java-v2"></a>

```
package com.aws.greengrass.docs.samples.ipc;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.SubscribeToTopicResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.*;

import java.nio.charset.StandardCharsets;
import java.util.Optional;

public class SubscribeToTopicV2 {

    public static void main(String[] args) {
        String topic = args[0];
        try (GreengrassCoreIPCClientV2 ipcClient = GreengrassCoreIPCClientV2.builder().build()) {
            SubscribeToTopicRequest request = new SubscribeToTopicRequest().withTopic(topic);
            GreengrassCoreIPCClientV2.StreamingResponse<SubscribeToTopicResponse,
                    SubscribeToTopicResponseHandler> response =
                    ipcClient.subscribeToTopic(request, SubscribeToTopicV2::onStreamEvent,
                            Optional.of(SubscribeToTopicV2::onStreamError),
                            Optional.of(SubscribeToTopicV2::onStreamClosed));
            SubscribeToTopicResponseHandler responseHandler = response.getHandler();
            System.out.println("Successfully subscribed to topic: " + topic);

            // Keep the main thread alive, or the process will exit.
            try {
                while (true) {
                    Thread.sleep(10000);
                }
            } catch (InterruptedException e) {
                System.out.println("Subscribe interrupted.");
            }

            // To stop subscribing, close the stream.
            responseHandler.closeStream();
        } catch (Exception e) {
            if (e.getCause() instanceof UnauthorizedError) {
                System.err.println("Unauthorized error while publishing to topic: " + topic);
            } else {
                System.err.println("Exception occurred when using IPC.");
            }
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static void onStreamEvent(SubscriptionResponseMessage subscriptionResponseMessage) {
        try {
            BinaryMessage binaryMessage = subscriptionResponseMessage.getBinaryMessage();
            String message = new String(binaryMessage.getMessage(), StandardCharsets.UTF_8);
            String topic = binaryMessage.getContext().getTopic();
            System.out.printf("Received new message on topic %s: %s%n", topic, message);
        } catch (Exception e) {
            System.err.println("Exception occurred while processing subscription response " +
                    "message.");
            e.printStackTrace();
        }
    }

    public static boolean onStreamError(Throwable error) {
        System.err.println("Received a stream error.");
        error.printStackTrace();
        return false; // Return true to close stream, false to keep stream open.
    }

    public static void onStreamClosed() {
        System.out.println("Subscribe to topic stream closed.");
    }
}
```

------
#### [ Python (IPC client V2) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-python-v2"></a>

```
import sys
import time
import traceback

from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
from awsiot.greengrasscoreipc.model import (
    SubscriptionResponseMessage,
    UnauthorizedError
)


def main():
    args = sys.argv[1:]
    topic = args[0]

    try:
        ipc_client = GreengrassCoreIPCClientV2()
        # Subscription operations return a tuple with the response and the operation.
        _, operation = ipc_client.subscribe_to_topic(topic=topic, on_stream_event=on_stream_event,
                                                     on_stream_error=on_stream_error, on_stream_closed=on_stream_closed)
        print('Successfully subscribed to topic: ' + topic)

        # Keep the main thread alive, or the process will exit.
        try:
            while True:
                time.sleep(10)
        except InterruptedError:
            print('Subscribe interrupted.')

        # To stop subscribing, close the stream.
        operation.close()
    except UnauthorizedError:
        print('Unauthorized error while subscribing to topic: ' +
              topic, file=sys.stderr)
        traceback.print_exc()
        exit(1)
    except Exception:
        print('Exception occurred', file=sys.stderr)
        traceback.print_exc()
        exit(1)


def on_stream_event(event: SubscriptionResponseMessage) -> None:
    try:
        message = str(event.binary_message.message, 'utf-8')
        topic = event.binary_message.context.topic
        print('Received new message on topic %s: %s' % (topic, message))
    except:
        traceback.print_exc()


def on_stream_error(error: Exception) -> bool:
    print('Received a stream error.', file=sys.stderr)
    traceback.print_exc()
    return False  # Return True to close stream, False to keep stream open.


def on_stream_closed() -> None:
    print('Subscribe to topic stream closed.')


if __name__ == '__main__':
    main()
```

------
#### [ C\$1\$1 (IPC client V1) ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-cpp"></a>

```
#include <iostream>

#include </crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class SubscribeResponseHandler : public SubscribeToTopicStreamHandler {
    public:
        virtual ~SubscribeResponseHandler() {}

    private:
        void OnStreamEvent(SubscriptionResponseMessage *response) override {
            auto jsonMessage = response->GetJsonMessage();
            if (jsonMessage.has_value() && jsonMessage.value().GetMessage().has_value()) {
                auto messageString = jsonMessage.value().GetMessage().value().View().WriteReadable();
                // Handle JSON message.
            } else {
                auto binaryMessage = response->GetBinaryMessage();
                if (binaryMessage.has_value() && binaryMessage.value().GetMessage().has_value()) {
                    auto messageBytes = binaryMessage.value().GetMessage().value();
                    std::string messageString(messageBytes.begin(), messageBytes.end());
                    // Handle binary message.
                }
            }
        }

        bool OnStreamError(OperationError *error) override {
            // Handle error.
            return false; // Return true to close stream, false to keep stream open.
        }

        void OnStreamClosed() override {
            // Handle close.
        }
};

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        // Handle connection to IPC service.
    }

    void OnDisconnectCallback(RpcError error) override {
        // Handle disconnection from IPC service.
    }

    bool OnErrorCallback(RpcError error) override {
        // Handle IPC service connection error.
        return true;
    }
};

int main() {
    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    String topic("my/topic");
    int timeout = 10;

    SubscribeToTopicRequest request;
    request.SetTopic(topic);

    //SubscribeResponseHandler streamHandler;
    auto streamHandler = MakeShared<SubscribeResponseHandler>(DefaultAllocator());
    auto operation = ipcClient.NewSubscribeToTopic(streamHandler);
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (!response) {
        // Handle error.
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            (void)error;
            // Handle operation error.
        } else {
            // Handle RPC error.
        }
        exit(-1);
    }

    // Keep the main thread alive, or the process will exit.
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    operation->Close();
    return 0;
}
```

------
#### [ JavaScript ]

**Example 예: 로컬 게시/구독 메시지 구독**  <a name="ipc-operation-subscribetotopic-example-nodejs"></a>

```
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
import {SubscribeToTopicRequest, SubscriptionResponseMessage} from "aws-iot-device-sdk-v2/dist/greengrasscoreipc/model";
import {RpcError} from "aws-iot-device-sdk-v2/dist/eventstream_rpc";
 
class SubscribeToTopic {
    private ipcClient : greengrasscoreipc.Client
    private readonly topic : string;
 
    constructor() {
        // define your own constructor, e.g.
        this.topic = "<define_your_topic>";
        this.subscribeToTopic().then(r => console.log("Started workflow"));
    }
 
    private async subscribeToTopic() {
        try {
            this.ipcClient = await getIpcClient();
 
            const subscribeToTopicRequest : SubscribeToTopicRequest = {
                topic: this.topic,
            }
 
            const streamingOperation = this.ipcClient.subscribeToTopic(subscribeToTopicRequest, undefined); // conditionally apply options
 
            streamingOperation.on("message", (message: SubscriptionResponseMessage) => {
                // parse the message depending on your use cases, e.g.
                if(message.binaryMessage && message.binaryMessage.message) {
                    const receivedMessage = message.binaryMessage?.message.toString();
                }
            });
 
            streamingOperation.on("streamError", (error : RpcError) => {
                // define your own error handling logic
            })
 
            streamingOperation.on("ended", () => {
                // define your own logic
            })
 
            await streamingOperation.activate();
 
            // Keep the main thread alive, or the process will exit.
            await new Promise((resolve) => setTimeout(resolve, 10000))
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
// starting point
const subscribeToTopic = new SubscribeToTopic();
```

------
#### [ Rust ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
use gg_sdk::{Sdk, SubscribeToTopicPayload};
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let topic = "my/topic";

    let callback = |topic: &str, payload: SubscribeToTopicPayload| match payload
    {
        SubscribeToTopicPayload::Binary(message) => {
            let message = String::from_utf8_lossy(message);
            println!("Received new message on topic {topic}: {message}");
        }
        SubscribeToTopicPayload::Json(_) => {
            println!("Received new message on topic {topic}: (JSON message)");
        }
    };

    let _sub = sdk
        .subscribe_to_topic(topic, &callback)
        .expect("Failed to subscribe to topic");

    println!("Successfully subscribed to topic: {topic}");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

------
#### [ C ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
#include <assert.h>
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <gg/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx, GgBuffer topic, GgObject payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    if (gg_obj_type(payload) == GG_TYPE_BUF) {
        GgBuffer message = gg_obj_into_buf(payload);
        printf(
            "Received new message on topic %.*s: %.*s\n",
            (int) topic.len,
            topic.data,
            (int) message.len,
            message.data
        );
    } else {
        assert(gg_obj_type(payload) == GG_TYPE_MAP);
        printf(
            "Received new message on topic %.*s: (JSON message)\n",
            (int) topic.len,
            topic.data
        );
    }
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer topic = GG_STR("my/topic");

    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_topic(
        topic, on_subscription_response, NULL, &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to subscribe to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully subscribed to topic: %.*s\n", (int) topic.len, topic.data
    );

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the stream.
    ggipc_close_subscription(handle);
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 로컬 게시/구독 메시지 구독**  

```
#include <gg/ipc/client.hpp>
#include <gg/object.hpp>
#include <unistd.h>
#include <cassert>
#include <iostream>

class ResponseHandler : public gg::ipc::LocalTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Object payload,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        if (payload.index() == GG_TYPE_BUF) {
            std::cout << "Received new message on topic " << topic << ": "
                      << get<gg::Buffer>(payload) << "\n";
        } else {
            assert(payload.index() == GG_TYPE_MAP);
            std::cout << "Received new message on topic " << topic
                      << ": (JSON message)\n";
        }
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view topic = "my/topic";

    static ResponseHandler handler;
    error = client.subscribe_to_topic(topic, handler);
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to topic: " << topic << "\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

------

## 예제
<a name="ipc-publish-subscribe-examples"></a>

다음 예제를 사용하여 구성 요소에서 게시/구독 IPC 서비스를 사용하는 방법을 알아봅니다.

### 예제 게시/구독 게시자(Java, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-publisher-java"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherJava",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherJava:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "java -jar {artifacts:path}/PubSubPublisher.jar"
      }
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubPublisherJava
ComponentVersion: '1.0.0'
ComponentDescription: A component that publishes messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        'com.example.PubSubPublisherJava:pubsub:1':
          policyDescription: Allows access to publish to all topics.
          operations:
            - 'aws.greengrass#PublishToTopic'
          resources:
            - '*'
Manifests:
  - Lifecycle:
      Run: |-
        java -jar {artifacts:path}/PubSubPublisher.jar
```

------

다음 예제 Java 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0 */

package com.example.ipc.pubsub;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.model.*;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class PubSubPublisher {

    public static void main(String[] args) {
        String message = "Hello from the pub/sub publisher (Java).";
        String topic = "test/topic/java";

        try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection);

            while (true) {
                PublishToTopicRequest publishRequest = new PublishToTopicRequest();
                PublishMessage publishMessage = new PublishMessage();
                BinaryMessage binaryMessage = new BinaryMessage();
                binaryMessage.setMessage(message.getBytes(StandardCharsets.UTF_8));
                publishMessage.setBinaryMessage(binaryMessage);
                publishRequest.setPublishMessage(publishMessage);
                publishRequest.setTopic(topic);
                CompletableFuture<PublishToTopicResponse> futureResponse = ipcClient
                        .publishToTopic(publishRequest, Optional.empty()).getResponse();

                try {
                    futureResponse.get(10, TimeUnit.SECONDS);
                    System.out.println("Successfully published to topic: " + topic);
                } catch (TimeoutException e) {
                    System.err.println("Timeout occurred while publishing to topic: " + topic);
                } catch (ExecutionException e) {
                    if (e.getCause() instanceof UnauthorizedError) {
                        System.err.println("Unauthorized error while publishing to topic: " + topic);
                    } else {
                        System.err.println("Execution exception while publishing to topic: " + topic);
                    }
                    throw e;
                }
                Thread.sleep(5000);
            }
        } catch (InterruptedException e) {
            System.out.println("Publisher interrupted.");
        } catch (Exception e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }
}
```

### 예제 게시/구독 구독자(Java, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-subscriber-java"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberJava",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberJava:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "java -jar {artifacts:path}/PubSubSubscriber.jar"
      }
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubSubscriberJava
ComponentVersion: '1.0.0'
ComponentDescription: A component that subscribes to messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        'com.example.PubSubSubscriberJava:pubsub:1':
          policyDescription: Allows access to subscribe to all topics.
          operations:
            - 'aws.greengrass#SubscribeToTopic'
          resources:
            - '*'
Manifests:
  - Lifecycle:
      Run: |-
        java -jar {artifacts:path}/PubSubSubscriber.jar
```

------

다음 예제 Java 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0 */

package com.example.ipc.pubsub;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.SubscribeToTopicResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToTopicRequest;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToTopicResponse;
import software.amazon.awssdk.aws.greengrass.model.SubscriptionResponseMessage;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;
import software.amazon.awssdk.eventstreamrpc.StreamResponseHandler;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class PubSubSubscriber {

    public static void main(String[] args) {
        String topic = "test/topic/java";

        try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection);

            SubscribeToTopicRequest subscribeRequest = new SubscribeToTopicRequest();
            subscribeRequest.setTopic(topic);
            SubscribeToTopicResponseHandler operationResponseHandler = ipcClient
                    .subscribeToTopic(subscribeRequest, Optional.of(new SubscribeResponseHandler()));
            CompletableFuture<SubscribeToTopicResponse> futureResponse = operationResponseHandler.getResponse();

            try {
                futureResponse.get(10, TimeUnit.SECONDS);
                System.out.println("Successfully subscribed to topic: " + topic);
            } catch (TimeoutException e) {
                System.err.println("Timeout occurred while subscribing to topic: " + topic);
                throw e;
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.println("Unauthorized error while subscribing to topic: " + topic);
                } else {
                    System.err.println("Execution exception while subscribing to topic: " + topic);
                }
                throw e;
            }

            // Keep the main thread alive, or the process will exit.
            try {
                while (true) {
                    Thread.sleep(10000);
                }
            } catch (InterruptedException e) {
                System.out.println("Subscribe interrupted.");
            }
        } catch (Exception e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static class SubscribeResponseHandler implements StreamResponseHandler<SubscriptionResponseMessage> {

        @Override
        public void onStreamEvent(SubscriptionResponseMessage subscriptionResponseMessage) {
            try {
                String message = new String(subscriptionResponseMessage.getBinaryMessage()
                        .getMessage(), StandardCharsets.UTF_8);
                System.out.println("Received new message: " + message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public boolean onStreamError(Throwable error) {
            System.err.println("Received a stream error.");
            error.printStackTrace();
            return false; // Return true to close stream, false to keep stream open.
        }

        @Override
        public void onStreamClosed() {
            System.out.println("Subscribe to topic stream closed.");
        }
    }
}
```

### 예제 게시/구독 게시자(Python, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-publisher-python"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherPython",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherPython:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux"
      },
      "Lifecycle": {
        "install": "python3 -m pip install --user awsiotsdk",
        "Run": "python3 -u {artifacts:path}/pubsub_publisher.py"
      }
    },
    {
      "Platform": {
        "os": "windows"
      },
      "Lifecycle": {
        "install": "py -3 -m pip install --user awsiotsdk",
        "Run": "py -3 -u {artifacts:path}/pubsub_publisher.py"
      }
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubPublisherPython
ComponentVersion: 1.0.0
ComponentDescription: A component that publishes messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        com.example.PubSubPublisherPython:pubsub:1:
          policyDescription: Allows access to publish to all topics.
          operations:
            - aws.greengrass#PublishToTopic
          resources:
            - "*"
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      install: python3 -m pip install --user awsiotsdk
      Run: python3 -u {artifacts:path}/pubsub_publisher.py
  - Platform:
      os: windows
    Lifecycle:
      install: py -3 -m pip install --user awsiotsdk
      Run: py -3 -u {artifacts:path}/pubsub_publisher.py
```

------

다음 예제 Python 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
import concurrent.futures
import sys
import time
import traceback

import awsiot.greengrasscoreipc
from awsiot.greengrasscoreipc.model import (
    PublishToTopicRequest,
    PublishMessage,
    BinaryMessage,
    UnauthorizedError
)

                    
topic = "test/topic/python"
message = "Hello from the pub/sub publisher (Python)."
TIMEOUT = 10

try:
    ipc_client = awsiot.greengrasscoreipc.connect()

    while True:
        request = PublishToTopicRequest()
        request.topic = topic
        publish_message = PublishMessage()
        publish_message.binary_message = BinaryMessage()
        publish_message.binary_message.message = bytes(message, "utf-8")
        request.publish_message = publish_message
        operation = ipc_client.new_publish_to_topic()
        operation.activate(request)
        future_response = operation.get_response()

        try:
            future_response.result(TIMEOUT)
            print('Successfully published to topic: ' + topic)
        except concurrent.futures.TimeoutError:
            print('Timeout occurred while publishing to topic: ' + topic, file=sys.stderr)
        except UnauthorizedError as e:
            print('Unauthorized error while publishing to topic: ' + topic, file=sys.stderr)
            raise e
        except Exception as e:
            print('Exception while publishing to topic: ' + topic, file=sys.stderr)
            raise e
        time.sleep(5)
except InterruptedError:
    print('Publisher interrupted.')
except Exception:
    print('Exception occurred when using IPC.', file=sys.stderr)
    traceback.print_exc()
    exit(1)
```

### 예제 게시/구독 구독자(Python, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-subscriber-python"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberPython",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberPython:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux"
      },
      "Lifecycle": {
        "install": "python3 -m pip install --user awsiotsdk",
        "Run": "python3 -u {artifacts:path}/pubsub_subscriber.py"
      }
    },
    {
      "Platform": {
        "os": "windows"
      },
      "Lifecycle": {
        "install": "py -3 -m pip install --user awsiotsdk",
        "Run": "py -3 -u {artifacts:path}/pubsub_subscriber.py"
      }
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubSubscriberPython
ComponentVersion: 1.0.0
ComponentDescription: A component that subscribes to messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        com.example.PubSubSubscriberPython:pubsub:1:
          policyDescription: Allows access to subscribe to all topics.
          operations:
            - aws.greengrass#SubscribeToTopic
          resources:
            - "*"
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      install: python3 -m pip install --user awsiotsdk
      Run: python3 -u {artifacts:path}/pubsub_subscriber.py
  - Platform:
      os: windows
    Lifecycle:
      install: py -3 -m pip install --user awsiotsdk
      Run: py -3 -u {artifacts:path}/pubsub_subscriber.py
```

------

다음 예제 Python 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
import concurrent.futures
import sys
import time
import traceback

import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import (
    SubscribeToTopicRequest,
    SubscriptionResponseMessage,
    UnauthorizedError
)

topic = "test/topic/python"
TIMEOUT = 10

                    
class StreamHandler(client.SubscribeToTopicStreamHandler):
    def __init__(self):
        super().__init__()

    def on_stream_event(self, event: SubscriptionResponseMessage) -> None:
        try:
            message = str(event.binary_message.message, "utf-8")
            print("Received new message: " + message)
        except:
            traceback.print_exc()

    def on_stream_error(self, error: Exception) -> bool:
        print("Received a stream error.", file=sys.stderr)
        traceback.print_exc()
        return False  # Return True to close stream, False to keep stream open.

    def on_stream_closed(self) -> None:
        print('Subscribe to topic stream closed.')


try:
    ipc_client = awsiot.greengrasscoreipc.connect()

    request = SubscribeToTopicRequest()
    request.topic = topic
    handler = StreamHandler()
    operation = ipc_client.new_subscribe_to_topic(handler)
    operation.activate(request)
    future_response = operation.get_response()
    
    try:
        future_response.result(TIMEOUT)
        print('Successfully subscribed to topic: ' + topic)
    except concurrent.futures.TimeoutError as e:
        print('Timeout occurred while subscribing to topic: ' + topic, file=sys.stderr)
        raise e
    except UnauthorizedError as e:
        print('Unauthorized error while subscribing to topic: ' + topic, file=sys.stderr)
        raise e
    except Exception as e:
        print('Exception while subscribing to topic: ' + topic, file=sys.stderr)
        raise e

    # Keep the main thread alive, or the process will exit.
    try:
        while True:
            time.sleep(10)
    except InterruptedError:
        print('Subscribe interrupted.')
except Exception:
    print('Exception occurred when using IPC.', file=sys.stderr)
    traceback.print_exc()
    exit(1)
```

### 게시/구독 게시자 예제(C\$1\$1, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-publisher-cpp"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherCpp:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "{artifacts:path}/greengrassv2_pubsub_publisher"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubPublisherCpp/1.0.0/greengrassv2_pubsub_publisher",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubPublisherCpp
ComponentVersion: 1.0.0
ComponentDescription: A component that publishes messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        com.example.PubSubPublisherCpp:pubsub:1:
          policyDescription: Allows access to publish to all topics.
          operations:
            - aws.greengrass#PublishToTopic
          resources:
            - "*"
Manifests:
  - Lifecycle:
      Run: "{artifacts:path}/greengrassv2_pubsub_publisher"
    Artifacts:
      - URI: s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubPublisherCpp/1.0.0/greengrassv2_pubsub_publisher
        Permission:
          Execute: OWNER
```

------

다음 예제 C\$1\$1 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        std::cout << "OnConnectCallback" << std::endl;
    }

    void OnDisconnectCallback(RpcError error) override {
        std::cout << "OnDisconnectCallback: " << error.StatusToString() << std::endl;
        exit(-1);
    }

    bool OnErrorCallback(RpcError error) override {
        std::cout << "OnErrorCallback: " << error.StatusToString() << std::endl;
        return true;
    }
};

int main() {
    String message("Hello from the pub/sub publisher (C++).");
    String topic("test/topic/cpp");
    int timeout = 10;

    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    while (true) {
        PublishToTopicRequest request;
        Vector<uint8_t> messageData({message.begin(), message.end()});
        BinaryMessage binaryMessage;
        binaryMessage.SetMessage(messageData);
        PublishMessage publishMessage;
        publishMessage.SetBinaryMessage(binaryMessage);
        request.SetTopic(topic);
        request.SetPublishMessage(publishMessage);

        auto operation = ipcClient.NewPublishToTopic();
        auto activate = operation->Activate(request, nullptr);
        activate.wait();

        auto responseFuture = operation->GetResult();
        if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
            std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
            exit(-1);
        }

        auto response = responseFuture.get();
        if (response) {
            std::cout << "Successfully published to topic: " << topic << std::endl;
        } else {
            // An error occurred.
            std::cout << "Failed to publish to topic: " << topic << std::endl;
            auto errorType = response.GetResultType();
            if (errorType == OPERATION_ERROR) {
                auto *error = response.GetOperationError();
                std::cout << "Operation error: " << error->GetMessage().value() << std::endl;
            } else {
                std::cout << "RPC error: " << response.GetRpcError() << std::endl;
            }
            exit(-1);
        }

        std::this_thread::sleep_for(std::chrono::seconds(5));
    }

    return 0;
}
```

### 구독자 게시/구독 예제(C\$1\$1, IPC 클라이언트 V1)
<a name="ipc-publish-subscribe-example-subscriber-cpp"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberCpp:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "{artifacts:path}/greengrassv2_pub_sub_subscriber"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberCpp/1.0.0/greengrassv2_pub_sub_subscriber",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PubSubSubscriberCpp
ComponentVersion: 1.0.0
ComponentDescription: A component that subscribes to messages.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.pubsub:
        com.example.PubSubSubscriberCpp:pubsub:1:
          policyDescription: Allows access to subscribe to all topics.
          operations:
            - aws.greengrass#SubscribeToTopic
          resources:
            - "*"
Manifests:
  - Lifecycle:
      Run: "{artifacts:path}/greengrassv2_pub_sub_subscriber"
    Artifacts:
      - URI: s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberCpp/1.0.0/greengrassv2_pub_sub_subscriber
        Permission:
          Execute: OWNER
```

------

다음 예제 C\$1\$1 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class SubscribeResponseHandler : public SubscribeToTopicStreamHandler {
    public:
        virtual ~SubscribeResponseHandler() {}

    private:
        void OnStreamEvent(SubscriptionResponseMessage *response) override {
            auto jsonMessage = response->GetJsonMessage();
            if (jsonMessage.has_value() && jsonMessage.value().GetMessage().has_value()) {
                auto messageString = jsonMessage.value().GetMessage().value().View().WriteReadable();
                std::cout << "Received new message: " << messageString << std::endl;
            } else {
                auto binaryMessage = response->GetBinaryMessage();
                if (binaryMessage.has_value() && binaryMessage.value().GetMessage().has_value()) {
                    auto messageBytes = binaryMessage.value().GetMessage().value();
                    std::string messageString(messageBytes.begin(), messageBytes.end());
                    std::cout << "Received new message: " << messageString << std::endl;
                }
            }
        }

        bool OnStreamError(OperationError *error) override {
            std::cout << "Received an operation error: ";
            if (error->GetMessage().has_value()) {
                std::cout << error->GetMessage().value();
            }
            std::cout << std::endl;
            return false; // Return true to close stream, false to keep stream open.
        }

        void OnStreamClosed() override {
            std::cout << "Subscribe to topic stream closed." << std::endl;
        }
};

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        std::cout << "OnConnectCallback" << std::endl;
    }

    void OnDisconnectCallback(RpcError error) override {
        std::cout << "OnDisconnectCallback: " << error.StatusToString() << std::endl;
        exit(-1);
    }

    bool OnErrorCallback(RpcError error) override {
        std::cout << "OnErrorCallback: " << error.StatusToString() << std::endl;
        return true;
    }
};

int main() {
    String topic("test/topic/cpp");
    int timeout = 10;

    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    SubscribeToTopicRequest request;
    request.SetTopic(topic);
    auto streamHandler = MakeShared<SubscribeResponseHandler>(DefaultAllocator());
    auto operation = ipcClient.NewSubscribeToTopic(streamHandler);
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (response) {
        std::cout << "Successfully subscribed to topic: " << topic << std::endl;
    } else {
        // An error occurred.
        std::cout << "Failed to subscribe to topic: " << topic << std::endl;
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            std::cout << "Operation error: " << error->GetMessage().value() << std::endl;
        } else {
            std::cout << "RPC error: " << response.GetRpcError() << std::endl;
        }
        exit(-1);
    }

    // Keep the main thread alive, or the process will exit.
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    operation->Close();
    return 0;
}
```

### 게시/구독 게시자 예제(Rust)
<a name="ipc-publish-subscribe-example-publisher-rust"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherRust",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherRust:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/publish_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubPublisherRust/1.0.0/publish_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 Rust 애플리케이션 예제에서는 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
use gg_sdk::Sdk;

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let message = b"Hello, World";
    let topic = "my/topic";

    sdk.publish_to_topic_binary(topic, message)
        .expect("Failed to publish to topic");

    println!("Successfully published to topic: {topic}");
}
```

### 구독자 게시/구독 예제(Rust)
<a name="ipc-publish-subscribe-example-subscriber-rust"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberRust",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberRust:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/subscribe_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberRust/1.0.0/subscribe_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 Rust 애플리케이션 예제에서는 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
use gg_sdk::{Sdk, SubscribeToTopicPayload};
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let topic = "my/topic";

    let callback = |topic: &str, payload: SubscribeToTopicPayload| match payload
    {
        SubscribeToTopicPayload::Binary(message) => {
            let message = String::from_utf8_lossy(message);
            println!("Received new message on topic {topic}: {message}");
        }
        SubscribeToTopicPayload::Json(_) => {
            println!("Received new message on topic {topic}: (JSON message)");
        }
    };

    let _sub = sdk
        .subscribe_to_topic(topic, &callback)
        .expect("Failed to subscribe to topic");

    println!("Successfully subscribed to topic: {topic}");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

### 게시/구독 게시자 예제(C)
<a name="ipc-publish-subscribe-example-publisher-c"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherC",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherC:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_publish_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubPublisherC/1.0.0/sample_publish_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C 애플리케이션은 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer message = GG_STR("Hello, World");
    GgBuffer topic = GG_STR("my/topic");

    err = ggipc_publish_to_topic_binary(topic, message);
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to publish to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully published to topic: %.*s\n", (int) topic.len, topic.data
    );
}
```

### 구독자 게시/구독 예제(C)
<a name="ipc-publish-subscribe-example-subscriber-c"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberC",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberC:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_subscribe_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberC/1.0.0/sample_subscribe_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C 애플리케이션은 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
#include <assert.h>
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <gg/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx, GgBuffer topic, GgObject payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    if (gg_obj_type(payload) == GG_TYPE_BUF) {
        GgBuffer message = gg_obj_into_buf(payload);
        printf(
            "Received new message on topic %.*s: %.*s\n",
            (int) topic.len,
            topic.data,
            (int) message.len,
            message.data
        );
    } else {
        assert(gg_obj_type(payload) == GG_TYPE_MAP);
        printf(
            "Received new message on topic %.*s: (JSON message)\n",
            (int) topic.len,
            topic.data
        );
    }
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer topic = GG_STR("my/topic");

    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_topic(
        topic, on_subscription_response, NULL, &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to subscribe to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully subscribed to topic: %.*s\n", (int) topic.len, topic.data
    );

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the stream.
    ggipc_close_subscription(handle);
}
```

### 게시/구독 게시자 예제(C\$1\$1, 구성 요소 SDK)
<a name="ipc-publish-subscribe-example-publisher-cpp-component-sdk"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubPublisherCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubPublisherCpp:pubsub:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_cpp_publish_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubPublisherCpp/1.0.0/sample_cpp_publish_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C\$1\$1 애플리케이션에서는 게시/구독 IPC 서비스를 사용하여 메시지를 다른 구성 요소에 게시하는 방법을 보여줍니다.

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view message = "Hello, World";
    std::string_view topic = "my/topic";

    error = client.publish_to_topic(topic, message);
    if (error) {
        std::cerr << "Failed to publish to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully published to topic: " << topic << "\n";
}
```

### 구독자 게시/구독 예제(C\$1\$1, 구성 요소 SDK)
<a name="ipc-publish-subscribe-example-subscriber-cpp-component-sdk"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PubSubSubscriberCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to messages.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.PubSubSubscriberCpp:pubsub:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToTopic"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_cpp_subscribe_to_topic"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.PubSubSubscriberCpp/1.0.0/sample_cpp_subscribe_to_topic",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C\$1\$1 애플리케이션은 게시/구독 IPC 서비스를 사용하여 다른 구성 요소의 메시지를 구독하는 방법을 보여줍니다.

```
#include <gg/ipc/client.hpp>
#include <gg/object.hpp>
#include <unistd.h>
#include <cassert>
#include <iostream>

class ResponseHandler : public gg::ipc::LocalTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Object payload,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        if (payload.index() == GG_TYPE_BUF) {
            std::cout << "Received new message on topic " << topic << ": "
                      << get<gg::Buffer>(payload) << "\n";
        } else {
            assert(payload.index() == GG_TYPE_MAP);
            std::cout << "Received new message on topic " << topic
                      << ": (JSON message)\n";
        }
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view topic = "my/topic";

    static ResponseHandler handler;
    error = client.subscribe_to_topic(topic, handler);
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to topic: " << topic << "\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

# AWS IoT Core MQTT 메시지 게시/구독
<a name="ipc-iot-core-mqtt"></a>

 AWS IoT Core MQTT 메시징 IPC 서비스를 사용하면와 MQTT 메시지를 주고 받을 수 있습니다 AWS IoT Core. 구성 요소는에 메시지를 게시 AWS IoT Core 하고 주제를 구독하여 다른 소스의 MQTT 메시지에 대해 조치를 취할 수 있습니다. MQTT AWS IoT Core 구현에 대한 자세한 내용은 *AWS IoT Core 개발자 안내서*의 [MQTT](https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html)를 참조하세요.

**참고**  
이 MQTT 메시징 IPC 서비스를 사용하면와 메시지를 교환할 수 있습니다 AWS IoT Core. 구성 요소 간에 메시지를 교환하는 방법에 대한 자세한 내용은 [로컬 메시지 게시/구독](ipc-publish-subscribe.md) 섹션을 참조하세요.

**Topics**
+ [최소 SDK 버전](#ipc-iot-core-mqtt-sdk-versions)
+ [권한 부여](#ipc-iot-core-mqtt-authorization)
+ [PublishToIoTCore](#ipc-operation-publishtoiotcore)
+ [SubscribeToIoTCore](#ipc-operation-subscribetoiotcore)
+ [예제](#ipc-iot-core-mqtt-examples)

## 최소 SDK 버전
<a name="ipc-iot-core-mqtt-sdk-versions"></a>

다음 표에는 MQTT 메시지를 게시하고 구독하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다 AWS IoT Core.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-iot-core-mqtt-authorization"></a>

사용자 지정 구성 요소에서 AWS IoT Core MQTT 메시징을 사용하려면 구성 요소가 주제에 대한 메시지를 보내고 받을 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

 AWS IoT Core MQTT 메시징에 대한 권한 부여 정책에는 다음과 같은 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.ipc.mqttproxy`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#PublishToIoTCore`  |  구성 요소가 지정한 MQTT 주제에 대해 AWS IoT Core 에 메시지를 게시하도록 허용합니다.  |  모든 주제에 대한 액세스를 허용하는 주제 문자열(`test/topic` 또는 `*`)입니다. MQTT 주제 와일드카드(`#` 및 `+`)를 사용하여 여러 리소스와 일치시킬 수 있습니다.  | 
|  `aws.greengrass#SubscribeToIoTCore`  |  구성 요소가 지정한 주제에 AWS IoT Core 대해의 메시지를 구독하도록 허용합니다.  |  모든 주제에 대한 액세스를 허용하는 주제 문자열(`test/topic` 또는 `*`)입니다. MQTT 주제 와일드카드(`#` 및 `+`)를 사용하여 여러 리소스와 일치시킬 수 있습니다.  | 
|  `*`  |  구성 요소가 지정한 주제에 대한 AWS IoT Core MQTT 메시지를 게시하고 구독하도록 허용합니다.  |  모든 주제에 대한 액세스를 허용하는 주제 문자열(`test/topic` 또는 `*`)입니다. MQTT 주제 와일드카드(`#` 및 `+`)를 사용하여 여러 리소스와 일치시킬 수 있습니다.  | 

### MQTT 권한 부여 정책의 AWS IoT Core MQTT 와일드카드
<a name="ipc-iot-core-mqtt-authorization-mqtt-wildcards"></a>

MQTT IPC 권한 부여 정책에서 AWS IoT Core MQTT 와일드카드를 사용할 수 있습니다. 구성 요소는 권한 부여 정책에서 허용하는 주제 필터와 일치하는 주제를 게시하고 구독할 수 있습니다. 예를 들어 구성 요소의 권한 부여 정책에서 `test/topic/#`에 대한 액세스 권한을 부여하는 경우 구성 요소는 `test/topic/#`을 구독할 수 있으며 `test/topic/filter`를 게시하고 구독할 수 있습니다.

### AWS IoT Core MQTT 권한 부여 정책의 레시피 변수
<a name="ipc-iot-core-mqtt-authorization-recipe-variables"></a>

[Greengrass nucleus](greengrass-nucleus-component.md)의 v2.6.0 이상을 사용하는 경우 권한 부여 정책에서 `{iot:thingName}` 레시피 변수를 사용할 수 있습니다. 이 기능을 사용하면 코어 디바이스 그룹에 대해 단일 권한 부여 정책을 구성할 수 있고, 이 경우 각 코어 디바이스는 자체 이름이 포함된 주제에만 액세스할 수 있습니다. 예를 들어 다음 주제 리소스에 대한 구성 요소 액세스를 허용할 수 있습니다.

```
devices/{iot:thingName}/messages
```

자세한 내용은 [레시피 변수](component-recipe-reference.md#recipe-variables) 및 [병합 업데이트에서 레시피 변수 사용](update-component-configurations.md#merge-configuration-update-recipe-variables)을(를) 참조하세요.

### 권한 부여 정책 예제
<a name="ipc-iot-core-mqtt-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 제한 없는 액세스를 사용하는 권한 부여 정책 예제**  
다음 권한 부여 정책 예제에서는 구성 요소가 모든 주제를 게시하고 구독할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.mqttproxy": {
      "com.example.MyIoTCorePubSubComponent:mqttproxy:1": {
        "policyDescription": "Allows access to publish/subscribe to all topics.",
        "operations": [
          "aws.greengrass#PublishToIoTCore",
          "aws.greengrass#SubscribeToIoTCore"
        ],
        "resources": [
          "*"
        ]
      }
    }
  }
}
```

```
---
accessControl:
  aws.greengrass.ipc.mqttproxy:
    com.example.MyIoTCorePubSubComponent:mqttproxy:1:
      policyDescription: Allows access to publish/subscribe to all topics.
      operations:
        - aws.greengrass#PublishToIoTCore
        - aws.greengrass#SubscribeToIoTCore
      resources:
        - "*"
```

**Example 제한된 액세스를 사용하는 권한 부여 정책 예제**  
다음 권한 부여 정책 예제에서는 구성 요소가 `factory/1/events` 및 `factory/1/actions`라는 두 가지 주제를 게시하고 구독할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.mqttproxy": {
      "com.example.MyIoTCorePubSubComponent:mqttproxy:1": {
        "policyDescription": "Allows access to publish/subscribe to factory 1 topics.",
        "operations": [
          "aws.greengrass#PublishToIoTCore",
          "aws.greengrass#SubscribeToIoTCore"
        ],
        "resources": [
          "factory/1/actions",
          "factory/1/events"
        ]
      }
    }
  }
}
```

```
---
accessControl:
  aws.greengrass.ipc.mqttproxy:
    "com.example.MyIoTCorePubSubComponent:mqttproxy:1":
      policyDescription: Allows access to publish/subscribe to factory 1 topics.
      operations:
        - aws.greengrass#PublishToIoTCore
        - aws.greengrass#SubscribeToIoTCore
      resources:
        - factory/1/actions
        - factory/1/events
```

**Example 코어 디바이스 그룹에 대한 권한 부여 정책 예제**  
이 예제에서는 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있는 기능을 사용합니다. Greengrass nucleus v2.6.0에서는 구성 요소 구성에서 `{iot:thingName}`과 같은 대부분의 [레시피 변수](component-recipe-reference.md#recipe-variables)에 대한 지원을 추가합니다.
다음 권한 부여 정책 예제에서는 구성 요소가 구성 요소를 실행하는 코어 디바이스의 이름이 포함된 주제를 게시하고 구독할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.mqttproxy": {
      "com.example.MyIoTCorePubSubComponent:mqttproxy:1": {
        "policyDescription": "Allows access to publish/subscribe to all topics.",
        "operations": [
          "aws.greengrass#PublishToIoTCore",
          "aws.greengrass#SubscribeToIoTCore"
        ],
        "resources": [
          "factory/1/devices/{iot:thingName}/controls"
        ]
      }
    }
  }
}
```

```
---
accessControl:
  aws.greengrass.ipc.mqttproxy:
    "com.example.MyIoTCorePubSubComponent:mqttproxy:1":
      policyDescription: Allows access to publish/subscribe to all topics.
      operations:
        - aws.greengrass#PublishToIoTCore
        - aws.greengrass#SubscribeToIoTCore
      resources:
        - factory/1/devices/{iot:thingName}/controls
```

## PublishToIoTCore
<a name="ipc-operation-publishtoiotcore"></a>

주제의 AWS IoT Core 에 MQTT 메시지를 게시합니다.

MQTT 메시지를에 게시할 때 초당 100개의 트랜잭션 할당 AWS IoT Core량이 있습니다. 이 할당량을 초과하면 메시지가 Greengrass 디바이스에서 처리를 위해 대기열에 대기됩니다. 또한 초당 512Kb의 데이터 할당량과 초당 20,000개의 게시(일부에서는 2,000개)의 계정 전체 할당량도 있습니다 AWS 리전. AWS IoT Core에서 MQTT 메시지 브로커 한도에 대한 자세한 내용은 [AWS IoT Core 메시지 브로커와 프로토콜 한도 및 할당량](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits)을 참조하세요.

이러한 할당량을 초과하면 Greengrass 디바이스가 메시지 게시를 제한합니다 AWS IoT Core. 메시지는 메모리의 스풀러에 저장됩니다. 기본적으로 스풀러에 할당된 메모리는 2.5Mb입니다. 스풀러가 채워지면 새 메시지가 거부됩니다. 스풀러의 크기를 늘릴 수 있습니다. 자세한 내용은 [Greengrass nucleus](greengrass-nucleus-component.md) 설명서의 [구성](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration)을(를) 참조하세요. 스풀러가 채워지고 할당된 메모리를 늘려야 하는 상황을 방지하려면 게시 요청을 초당 100개 이하의 요청으로 제한합니다.

애플리케이션에서 메시지를 더 높은 속도로 보내거나 더 큰 메시지를 보내야 하는 경우 [스트림 관리자](stream-manager-component.md)를 사용하여 Kinesis Data Streams로 메시지를 보내는 것이 좋습니다. 스트림 관리자 구성 요소는 AWS 클라우드로 대용량 데이터를 전송하기 위한 것입니다. 자세한 내용은 [Greengrass 코어 디바이스에서 데이터 스트림 관리](manage-data-streams.md) 단원을 참조하십시오.

### 요청
<a name="ipc-operation-publishtoiotcore-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`topicName`(Python: `topic_name`)  
메시지를 게시할 주제입니다.

`qos`  <a name="ipc-iot-core-mqtt-qos"></a>
사용할 MQTT QoS입니다. 이 열거형 `QOS`의 값은 다음과 같습니다.  
+ `AT_MOST_ONCE` – QoS 0. MQTT 메시지가 최대 한 번 전송됩니다.
+ `AT_LEAST_ONCE` – QoS 1. MQTT 메시지가 한 번 이상 전송됩니다.

`payload`  
(선택 사항) Blob인 메시지 페이로드입니다.

MQTT 5를 사용할 때 [Greengrass nucleus](greengrass-nucleus-component.md)의 v2.10.0 이상에서는 다음 기능을 사용할 수 있습니다. MQTT 3.1.1을 사용하는 경우 이러한 기능은 무시됩니다. 다음 표에는 이러한 기능에 액세스하는 데 사용해야 하는 AWS IoT 디바이스 SDK의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
| [AWS IoT Device SDK for Python](https://github.com/aws/aws-iot-device-sdk-python-v2) v2 | v1.15.0 | 
| [AWS IoT Device SDK for Java](https://github.com/aws/aws-iot-device-sdk-java-v2) v2 | v1.13.0 | 
| [AWS IoT Device SDK for C\$1\$1](https://github.com/aws/aws-iot-device-sdk-cpp-v2) v2 | v1.24.0 | 
| [AWS IoT Device SDK for JavaScript](https://github.com/aws/aws-iot-device-sdk-js-v2) v2  | v1.13.0 | 

`payloadFormat`  
(선택 사항) 메시지 페이로드의 형식입니다. `payloadFormat`을 설정하지 않으면 유형은 `BYTES`인 것으로 가정합니다. 이 열거형의 값은 다음과 같습니다.  
+ `BYTES` – 페이로드의 콘텐츠는 이진 bolb입니다.
+ `UTF8` - 페이로드의 콘텐츠는 UTF8 문자열입니다.

`retain`  
(선택 사항) 게시할 때 MQTT 유지 옵션을 `true`로 설정할지 여부를 나타냅니다.

`userProperties`  
(선택 사항) 전송할 애플리케이션별 `UserProperty` 객체의 목록입니다. `UserProperty` 객체는 다음과 같이 정의됩니다.  

```
UserProperty:
  key: string
  value: string
```

`messageExpiryIntervalSeconds`  
(선택 사항) 메시지가 만료되고 서버에 의해 삭제되기 전까지의 시간(초)입니다. 이 값을 설정하지 않으면 메시지가 만료되지 않습니다.

`correlationData`  
(선택 사항) 요청을 응답과 연결하는 데 사용할 수 있는 요청에 추가된 정보입니다.

`responseTopic`  
(선택 사항) 응답 메시지에 사용해야 하는 주제입니다.

`contentType`  
(선택 사항) 메시지의 콘텐츠 유형에 대한 애플리케이션별 식별자입니다.

### 응답
<a name="ipc-operation-publishtoiotcore-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

### 예제
<a name="ipc-operation-publishtoiotcore-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V2) ]

**Example 예: 메시지 게시**  

```
package com.aws.greengrass.docs.samples.ipc;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.model.PublishToIoTCoreRequest;
import software.amazon.awssdk.aws.greengrass.model.QOS;
import java.nio.charset.StandardCharsets;

public class PublishToIoTCore {

    public static void main(String[] args) {
        String topic = args[0];
        String message = args[1];
        QOS qos = QOS.get(args[2]);

        try (GreengrassCoreIPCClientV2 ipcClientV2 = GreengrassCoreIPCClientV2.builder().build()) {
            ipcClientV2.publishToIoTCore(new PublishToIoTCoreRequest()
                    .withTopicName(topic)
                    .withPayload(message.getBytes(StandardCharsets.UTF_8))
                    .withQos(qos));
            System.out.println("Successfully published to topic: " + topic);
        } catch (Exception e) {
            System.err.println("Exception occurred.");
            e.printStackTrace();
            System.exit(1);
        }
    }
}
```

------
#### [ Python (IPC client V2) ]

**Example 예: 메시지 게시**  
이 예제에서는 Python v2 AWS IoT Device SDK 용의 버전 1.5.4 이상을 사용하고 있다고 가정합니다.

```
import awsiot.greengrasscoreipc.clientv2 as clientV2
                    
topic = 'my/topic'
qos = '1'
payload = 'Hello, World'

ipc_client = clientV2.GreengrassCoreIPCClientV2()
resp = ipc_client.publish_to_iot_core(topic_name=topic, qos=qos, payload=payload)
ipc_client.close()
```

------
#### [ Java (IPC client V1) ]

**Example 예: 메시지 게시**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.PublishToIoTCoreResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.PublishToIoTCoreRequest;
import software.amazon.awssdk.aws.greengrass.model.PublishToIoTCoreResponse;
import software.amazon.awssdk.aws.greengrass.model.QOS;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class PublishToIoTCore {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        String topic = args[0];
        String message = args[1];
        QOS qos = QOS.get(args[2]);
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            PublishToIoTCoreResponseHandler responseHandler =
                    PublishToIoTCore.publishBinaryMessageToTopic(ipcClient, topic, message, qos);
            CompletableFuture<PublishToIoTCoreResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                System.out.println("Successfully published to topic: " + topic);
            } catch (TimeoutException e) {
                System.err.println("Timeout occurred while publishing to topic: " + topic);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.println("Unauthorized error while publishing to topic: " + topic);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static PublishToIoTCoreResponseHandler publishBinaryMessageToTopic(GreengrassCoreIPCClient greengrassCoreIPCClient, String topic, String message, QOS qos) {
        PublishToIoTCoreRequest publishToIoTCoreRequest = new PublishToIoTCoreRequest();
        publishToIoTCoreRequest.setTopicName(topic);
        publishToIoTCoreRequest.setPayload(message.getBytes(StandardCharsets.UTF_8));
        publishToIoTCoreRequest.setQos(qos);
        return greengrassCoreIPCClient.publishToIoTCore(publishToIoTCoreRequest, Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 메시지 게시**  
이 예제에서는 Python v2 AWS IoT Device SDK 용의 버전 1.5.4 이상을 사용하고 있다고 가정합니다.

```
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import (
    QOS,
    PublishToIoTCoreRequest
)

TIMEOUT = 10

ipc_client = awsiot.greengrasscoreipc.connect()
                    
topic = "my/topic"
message = "Hello, World"
qos = QOS.AT_LEAST_ONCE

request = PublishToIoTCoreRequest()
request.topic_name = topic
request.payload = bytes(message, "utf-8")
request.qos = qos
operation = ipc_client.new_publish_to_iot_core()
operation.activate(request)
future_response = operation.get_response()
future_response.result(TIMEOUT)
```

------
#### [ C\$1\$1 (IPC client V1) ]

**Example 예: 메시지 게시**  

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        // Handle connection to IPC service.
    }

    void OnDisconnectCallback(RpcError error) override {
        // Handle disconnection from IPC service.
    }

    bool OnErrorCallback(RpcError error) override {
        // Handle IPC service connection error.
        return true;
    }
};

int main() {
    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    String message("Hello, World!");
    String topic("my/topic");
    QOS qos = QOS_AT_MOST_ONCE;
    int timeout = 10;

    PublishToIoTCoreRequest request;
    Vector<uint8_t> messageData({message.begin(), message.end()});
    request.SetTopicName(topic);
    request.SetPayload(messageData);
    request.SetQos(qos);

    auto operation = ipcClient.NewPublishToIoTCore();
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (!response) {
        // Handle error.
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            (void)error;
            // Handle operation error.
        } else {
            // Handle RPC error.
        }
    }

    return 0;
}
```

------
#### [ JavaScript ]

**Example 예: 메시지 게시**  

```
    
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
import {QOS, PublishToIoTCoreRequest} from "aws-iot-device-sdk-v2/dist/greengrasscoreipc/model";
 
class PublishToIoTCore {
    private ipcClient: greengrasscoreipc.Client
    private readonly topic: string;
 
    constructor() {
        // define your own constructor, e.g.
        this.topic = "<define_your_topic>";
        this.publishToIoTCore().then(r => console.log("Started workflow"));
    }
 
    private async publishToIoTCore() {
        try {
            const request: PublishToIoTCoreRequest = {
                topicName: this.topic,
                qos: QOS.AT_LEAST_ONCE, // you can change this depending on your use case
            }
 
            this.ipcClient = await getIpcClient();
 
            await this.ipcClient.publishToIoTCore(request);
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
// starting point
const publishToIoTCore = new PublishToIoTCore();
```

------
#### [ Rust ]

**Example 예: 메시지 게시**  

```
use gg_sdk::{Qos, Sdk};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let message = b"Hello, World";
    let topic = "my/topic";
    let qos = Qos::AtLeastOnce;

    sdk.publish_to_iot_core(topic, message, qos)
        .expect("Failed to publish to topic");

    println!("Successfully published to topic: {topic}");
}
```

------
#### [ C ]

**Example 예: 메시지 게시**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer message = GG_STR("Hello, World");
    GgBuffer topic = GG_STR("my/topic");
    uint8_t qos = 1;

    err = ggipc_publish_to_iot_core(topic, message, qos);
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to publish to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully published to topic: %.*s\n", (int) topic.len, topic.data
    );
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 메시지 게시**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view message = "Hello, World";
    std::string_view topic = "my/topic";
    uint8_t qos = 1;

    error = client.publish_to_iot_core(topic, message, qos);
    if (error) {
        std::cerr << "Failed to publish to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully published to topic: " << topic << "\n";
}
```

------

## SubscribeToIoTCore
<a name="ipc-operation-subscribetoiotcore"></a>

주제 또는 주제 필터 AWS IoT Core 에서의 MQTT 메시지를 구독합니다. AWS IoT Greengrass 코어 소프트웨어는 구성 요소가 수명 주기 종료에 도달하면 구독을 제거합니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `IoTCoreMessage`

### 요청
<a name="ipc-operation-subscribetoiotcore-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`topicName`(Python: `topic_name`)  
구독할 주제입니다. MQTT 주제 와일드카드(`#` 및 `+`)를 사용하여 여러 주제를 구독할 수 있습니다.

`qos`  <a name="ipc-iot-core-mqtt-qos"></a>
사용할 MQTT QoS입니다. 이 열거형 `QOS`의 값은 다음과 같습니다.  
+ `AT_MOST_ONCE` – QoS 0. MQTT 메시지가 최대 한 번 전송됩니다.
+ `AT_LEAST_ONCE` – QoS 1. MQTT 메시지가 한 번 이상 전송됩니다.

### 응답
<a name="ipc-operation-subscribetoiotcore-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
MQTT 메시지의 스트림입니다. 이 객체 `IoTCoreMessage`에는 다음 정보가 포함됩니다.    
`message`  
MQTT 메시지입니다. 이 객체 `MQTTMessage`에는 다음 정보가 포함됩니다.    
`topicName`(Python: `topic_name`)  
메시지가 게시된 주제입니다.  
`payload`  
(선택 사항) Blob인 메시지 페이로드입니다.
MQTT 5를 사용할 때 [Greengrass nucleus](greengrass-nucleus-component.md)의 v2.10.0 이상에서는 다음 기능을 사용할 수 있습니다. MQTT 3.1.1을 사용하는 경우 이러한 기능은 무시됩니다. 다음 표에는 이러한 기능에 액세스하는 데 사용해야 하는 AWS IoT 디바이스 SDK의 최소 버전이 나열되어 있습니다.      
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-iot-core-mqtt.html)  
`payloadFormat`  
(선택 사항) 메시지 페이로드의 형식입니다. `payloadFormat`을 설정하지 않으면 유형은 `BYTES`인 것으로 가정합니다. 이 열거형의 값은 다음과 같습니다.  
+ `BYTES` – 페이로드의 콘텐츠는 이진 bolb입니다.
+ `UTF8` - 페이로드의 콘텐츠는 UTF8 문자열입니다.  
`retain`  
(선택 사항) 게시할 때 MQTT 유지 옵션을 `true`로 설정할지 여부를 나타냅니다.  
`userProperties`  
(선택 사항) 전송할 애플리케이션별 `UserProperty` 객체의 목록입니다. `UserProperty` 객체는 다음과 같이 정의됩니다.  

```
UserProperty:
  key: string
  value: string
```  
`messageExpiryIntervalSeconds`  
(선택 사항) 메시지가 만료되고 서버에 의해 삭제되기 전까지의 시간(초)입니다. 이 값을 설정하지 않으면 메시지가 만료되지 않습니다.  
`correlationData`  
(선택 사항) 요청을 응답과 연결하는 데 사용할 수 있는 요청에 추가된 정보입니다.  
`responseTopic`  
(선택 사항) 응답 메시지에 사용해야 하는 주제입니다.  
`contentType`  
(선택 사항) 메시지의 콘텐츠 유형에 대한 애플리케이션별 식별자입니다.

### 예제
<a name="ipc-operation-subscribetoiotcore-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V2) ]

**Example 예: 메시지 구독**  

```
package com.aws.greengrass.docs.samples.ipc;

import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.SubscribeToIoTCoreResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.QOS;
import software.amazon.awssdk.aws.greengrass.model.IoTCoreMessage;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToIoTCoreRequest;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToIoTCoreResponse;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;


public class SubscribeToIoTCore {

    public static void main(String[] args) {
        String topic = args[0];
        QOS qos = QOS.get(args[1]);

        Consumer<IoTCoreMessage> onStreamEvent = ioTCoreMessage ->
                System.out.printf("Received new message on topic %s: %s%n",
                        ioTCoreMessage.getMessage().getTopicName(),
                        new String(ioTCoreMessage.getMessage().getPayload(), StandardCharsets.UTF_8));

        Optional<Function<Throwable, Boolean>> onStreamError =
                Optional.of(e -> {
                    System.err.println("Received a stream error.");
                    e.printStackTrace();
                    return false;
                });

        Optional<Runnable> onStreamClosed = Optional.of(() ->
                System.out.println("Subscribe to IoT Core stream closed."));

        try (GreengrassCoreIPCClientV2 ipcClientV2 = GreengrassCoreIPCClientV2.builder().build()) {
            SubscribeToIoTCoreRequest request = new SubscribeToIoTCoreRequest()
                    .withTopicName(topic)
                    .withQos(qos);

            GreengrassCoreIPCClientV2.StreamingResponse<SubscribeToIoTCoreResponse, SubscribeToIoTCoreResponseHandler>
                    streamingResponse = ipcClientV2.subscribeToIoTCore(request, onStreamEvent, onStreamError, onStreamClosed);

            streamingResponse.getResponse();
            System.out.println("Successfully subscribed to topic: " + topic);

            // Keep the main thread alive, or the process will exit.
            while (true) {
                Thread.sleep(10000);
            }

            // To stop subscribing, close the stream.
            streamingResponse.getHandler().closeStream();
        } catch (InterruptedException e) {
            System.out.println("Subscribe interrupted.");
        } catch (Exception e) {
            System.err.println("Exception occurred.");
            e.printStackTrace();
            System.exit(1);
        }
    }
}
```

------
#### [ Python (IPC client V2) ]

**Example 예: 메시지 구독**  
이 예제에서는 Python v2 AWS IoT Device SDK 용의 버전 1.5.4 이상을 사용하고 있다고 가정합니다.

```
import threading
import traceback

import awsiot.greengrasscoreipc.clientv2 as clientV2
                    
topic = 'my/topic'
qos = '1'

def on_stream_event(event):
    try:
        topic_name = event.message.topic_name
        message = str(event.message.payload, 'utf-8')
        print(f'Received new message on topic {topic_name}:  {message}')
    except:
        traceback.print_exc()

def on_stream_error(error):
    # Return True to close stream, False to keep stream open.
    return True  

def on_stream_closed():
    pass

ipc_client = clientV2.GreengrassCoreIPCClientV2()
resp, operation = ipc_client.subscribe_to_iot_core(
    topic_name=topic,
    qos=qos, 
    on_stream_event=on_stream_event,
    on_stream_error=on_stream_error,
    on_stream_closed=on_stream_closed
)

# Keep the main thread alive, or the process will exit.
event = threading.Event()
event.wait()

# To stop subscribing, close the operation stream.
operation.close()
ipc_client.close()
```

------
#### [ Java (IPC client V1) ]

**Example 예: 메시지 구독**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.SubscribeToIoTCoreResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.*;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;
import software.amazon.awssdk.eventstreamrpc.StreamResponseHandler;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class SubscribeToIoTCore {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        String topic = args[0];
        QOS qos = QOS.get(args[1]);
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            StreamResponseHandler<IoTCoreMessage> streamResponseHandler =
                    new SubscriptionResponseHandler();
            SubscribeToIoTCoreResponseHandler responseHandler =
                    SubscribeToIoTCore.subscribeToIoTCore(ipcClient, topic, qos,
                            streamResponseHandler);
            CompletableFuture<SubscribeToIoTCoreResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                System.out.println("Successfully subscribed to topic: " + topic);
            } catch (TimeoutException e) {
                System.err.println("Timeout occurred while subscribing to topic: " + topic);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.println("Unauthorized error while subscribing to topic: " + topic);
                } else {
                    throw e;
                }
            }

            // Keep the main thread alive, or the process will exit.
            try {
                while (true) {
                    Thread.sleep(10000);
                }
            } catch (InterruptedException e) {
                System.out.println("Subscribe interrupted.");
            }

            // To stop subscribing, close the stream.
            responseHandler.closeStream();
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static SubscribeToIoTCoreResponseHandler subscribeToIoTCore(GreengrassCoreIPCClient greengrassCoreIPCClient, String topic, QOS qos, StreamResponseHandler<IoTCoreMessage> streamResponseHandler) {
        SubscribeToIoTCoreRequest subscribeToIoTCoreRequest = new SubscribeToIoTCoreRequest();
        subscribeToIoTCoreRequest.setTopicName(topic);
        subscribeToIoTCoreRequest.setQos(qos);
        return greengrassCoreIPCClient.subscribeToIoTCore(subscribeToIoTCoreRequest,
                Optional.of(streamResponseHandler));
    }

    public static class SubscriptionResponseHandler implements StreamResponseHandler<IoTCoreMessage> {

        @Override
        public void onStreamEvent(IoTCoreMessage ioTCoreMessage) {
            try {
                String topic = ioTCoreMessage.getMessage().getTopicName();
                String message = new String(ioTCoreMessage.getMessage().getPayload(),
                        StandardCharsets.UTF_8);
                System.out.printf("Received new message on topic %s: %s%n", topic, message);
            } catch (Exception e) {
                System.err.println("Exception occurred while processing subscription response " +
                        "message.");
                e.printStackTrace();
            }
        }

        @Override
        public boolean onStreamError(Throwable error) {
            System.err.println("Received a stream error.");
            error.printStackTrace();
            return false;
        }

        @Override
        public void onStreamClosed() {
            System.out.println("Subscribe to IoT Core stream closed.");
        }
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 메시지 구독**  
이 예제에서는 Python v2 AWS IoT Device SDK 용의 버전 1.5.4 이상을 사용하고 있다고 가정합니다.

```
import time
import traceback

import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import (
    IoTCoreMessage,
    QOS,
    SubscribeToIoTCoreRequest
)

TIMEOUT = 10

ipc_client = awsiot.greengrasscoreipc.connect()

class StreamHandler(client.SubscribeToIoTCoreStreamHandler):
    def __init__(self):
        super().__init__()

    def on_stream_event(self, event: IoTCoreMessage) -> None:
        try:
            message = str(event.message.payload, "utf-8")
            topic_name = event.message.topic_name
            # Handle message.
        except:
            traceback.print_exc()

    def on_stream_error(self, error: Exception) -> bool:
        # Handle error.
        return True  # Return True to close stream, False to keep stream open.

    def on_stream_closed(self) -> None:
        # Handle close.
        pass


topic = "my/topic"
qos = QOS.AT_MOST_ONCE

request = SubscribeToIoTCoreRequest()
request.topic_name = topic
request.qos = qos
handler = StreamHandler()
operation = ipc_client.new_subscribe_to_iot_core(handler)
operation.activate(request)
future_response = operation.get_response() 
future_response.result(TIMEOUT)

# Keep the main thread alive, or the process will exit.
while True:
    time.sleep(10)
                  
# To stop subscribing, close the operation stream.
operation.close()
```

------
#### [ C\$1\$1 (IPC client V1) ]

**Example 예: 메시지 구독**  

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IoTCoreResponseHandler : public SubscribeToIoTCoreStreamHandler {

    public:
        virtual ~IoTCoreResponseHandler() {}

    private:
        void OnStreamEvent(IoTCoreMessage *response) override {
            auto message = response->GetMessage();
            if (message.has_value() && message.value().GetPayload().has_value()) {
                auto messageBytes = message.value().GetPayload().value();
                std::string messageString(messageBytes.begin(), messageBytes.end());
                std::string topicName = message.value().GetTopicName().value().c_str();
                // Handle message.
            }
        }

        bool OnStreamError(OperationError *error) override {
            // Handle error.
            return false; // Return true to close stream, false to keep stream open.
        }

        void OnStreamClosed() override {
            // Handle close.
        }
};

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        // Handle connection to IPC service.
    }

    void OnDisconnectCallback(RpcError error) override {
        // Handle disconnection from IPC service.
    }

    bool OnErrorCallback(RpcError error) override {
        // Handle IPC service connection error.
        return true;
    }
};

int main() {
    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    String topic("my/topic");
    QOS qos = QOS_AT_MOST_ONCE;
    int timeout = 10;

    SubscribeToIoTCoreRequest request;
    request.SetTopicName(topic);
    request.SetQos(qos);
    auto streamHandler = MakeShared<IoTCoreResponseHandler>(DefaultAllocator());
    auto operation = ipcClient.NewSubscribeToIoTCore(streamHandler);
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (!response) {
        // Handle error.
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            (void)error;
            // Handle operation error.
        } else {
            // Handle RPC error.
        }
        exit(-1);
    }

    // Keep the main thread alive, or the process will exit.
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    operation->Close();
    return 0;
}
```

------
#### [ JavaScript ]

**Example 예: 메시지 구독**  

```
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
import {IoTCoreMessage, QOS, SubscribeToIoTCoreRequest} from "aws-iot-device-sdk-v2/dist/greengrasscoreipc/model";
import {RpcError} from "aws-iot-device-sdk-v2/dist/eventstream_rpc";
 
class SubscribeToIoTCore {
    private ipcClient: greengrasscoreipc.Client
    private readonly topic: string;
 
    constructor() {
        // define your own constructor, e.g.
        this.topic = "<define_your_topic>";
        this.subscribeToIoTCore().then(r => console.log("Started workflow"));
    }
 
    private async subscribeToIoTCore() {
        try {
            const request: SubscribeToIoTCoreRequest = {
                topicName: this.topic,
                qos: QOS.AT_LEAST_ONCE, // you can change this depending on your use case
            }
 
            this.ipcClient = await getIpcClient();
 
            const streamingOperation = this.ipcClient.subscribeToIoTCore(request);
 
            streamingOperation.on('message', (message: IoTCoreMessage) => {
                // parse the message depending on your use cases, e.g.
                if (message.message && message.message.payload) {
                    const receivedMessage = message.message.payload.toString();
                }
            });
 
            streamingOperation.on('streamError', (error : RpcError) => {
                // define your own error handling logic
            });
 
            streamingOperation.on('ended', () => {
                // define your own logic
            });
 
            await streamingOperation.activate();
 
            // Keep the main thread alive, or the process will exit.
            await new Promise((resolve) => setTimeout(resolve, 10000))
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
// starting point
const subscribeToIoTCore = new SubscribeToIoTCore();
```

------
#### [ Rust ]

**Example 예: 메시지 구독**  

```
use gg_sdk::{Qos, Sdk};
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let topic = "my/topic";
    let qos = Qos::AtLeastOnce;

    let callback = |topic: &str, payload: &[u8]| {
        let message = String::from_utf8_lossy(payload);
        println!("Received new message on topic {topic}: {message}");
    };

    let _sub = sdk
        .subscribe_to_iot_core(topic, qos, &callback)
        .expect("Failed to subscribe to topic");

    println!("Successfully subscribed to topic: {topic}");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

------
#### [ C ]

**Example 예: 메시지 구독**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx, GgBuffer topic, GgBuffer payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    printf(
        "Received new message on topic %.*s: %.*s\n",
        (int) topic.len,
        topic.data,
        (int) payload.len,
        payload.data
    );
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer topic = GG_STR("my/topic");
    uint8_t qos = 1;

    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_iot_core(
        topic, qos, on_subscription_response, NULL, &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to subscribe to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully subscribed to topic: %.*s\n", (int) topic.len, topic.data
    );

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the subscription handle.
    ggipc_close_subscription(handle);
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 메시지 구독**  

```
#include <gg/ipc/client.hpp>
#include <unistd.h>
#include <iostream>

class ResponseHandler : public gg::ipc::IotTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Buffer payload,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        std::cout << "Received new message on topic " << topic << ": "
                  << payload << "\n";
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view topic = "my/topic";
    uint8_t qos = 1;

    static ResponseHandler handler;
    error = client.subscribe_to_iot_core(topic, qos, handler);
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to topic: " << topic << "\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

------

## 예제
<a name="ipc-iot-core-mqtt-examples"></a>

다음 예제를 사용하여 구성 요소에서 AWS IoT Core MQTT IPC 서비스를 사용하는 방법을 알아봅니다.

### 예제 AWS IoT Core MQTT 게시자(C\$1\$1, IPC 클라이언트 V1)
<a name="ipc-iot-core-mqtt-example-publisher-cpp"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCorePublisherCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes MQTT messages to IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCorePublisherCpp:mqttproxy:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": [
              "aws.greengrass#PublishToIoTCore"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "{artifacts:path}/greengrassv2_iotcore_publisher"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCorePublisherCpp/1.0.0/greengrassv2_iotcore_publisher",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.IoTCorePublisherCpp
ComponentVersion: 1.0.0
ComponentDescription: A component that publishes MQTT messages to IoT Core.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.mqttproxy:
        com.example.IoTCorePublisherCpp:mqttproxy:1:
          policyDescription: Allows access to publish to all topics.
          operations:
            - aws.greengrass#PublishToIoTCore
          resources:
            - "*"
Manifests:
  - Lifecycle:
      Run: "{artifacts:path}/greengrassv2_iotcore_publisher"
    Artifacts:
      - URI: s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCorePublisherCpp/1.0.0/greengrassv2_iotcore_publisher
        Permission:
          Execute: OWNER
```

------

다음 예제 C\$1\$1 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 게시하는 방법을 보여줍니다 AWS IoT Core.

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        std::cout << "OnConnectCallback" << std::endl;
    }

    void OnDisconnectCallback(RpcError error) override {
        std::cout << "OnDisconnectCallback: " << error.StatusToString() << std::endl;
        exit(-1);
    }

    bool OnErrorCallback(RpcError error) override {
        std::cout << "OnErrorCallback: " << error.StatusToString() << std::endl;
        return true;
    }
};

int main() {
    String message("Hello from the Greengrass IPC MQTT publisher (C++).");
    String topic("test/topic/cpp");
    QOS qos = QOS_AT_LEAST_ONCE;
    int timeout = 10;

    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    while (true) {
        PublishToIoTCoreRequest request;
        Vector<uint8_t> messageData({message.begin(), message.end()});
        request.SetTopicName(topic);
        request.SetPayload(messageData);
        request.SetQos(qos);

        auto operation = ipcClient.NewPublishToIoTCore();
        auto activate = operation->Activate(request, nullptr);
        activate.wait();

        auto responseFuture = operation->GetResult();
        if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
            std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
            exit(-1);
        }

        auto response = responseFuture.get();
        if (response) {
            std::cout << "Successfully published to topic: " << topic << std::endl;
        } else {
            // An error occurred.
            std::cout << "Failed to publish to topic: " << topic << std::endl;
            auto errorType = response.GetResultType();
            if (errorType == OPERATION_ERROR) {
                auto *error = response.GetOperationError();
                std::cout << "Operation error: " << error->GetMessage().value() << std::endl;
            } else {
                std::cout << "RPC error: " << response.GetRpcError() << std::endl;
            }
            exit(-1);
        }

        std::this_thread::sleep_for(std::chrono::seconds(5));
    }

    return 0;
}
```

### AWS IoT Core MQTT 구독자 예제(C\$1\$1, IPC 클라이언트 V1)
<a name="ipc-iot-core-mqtt-example-subscriber-cpp"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCoreSubscriberCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to MQTT messages from IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCoreSubscriberCpp:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": [
              "aws.greengrass#SubscribeToIoTCore"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Lifecycle": {
        "Run": "{artifacts:path}/greengrassv2_iotcore_subscriber"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCoreSubscriberCpp/1.0.0/greengrassv2_iotcore_subscriber",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.IoTCoreSubscriberCpp
ComponentVersion: 1.0.0
ComponentDescription: A component that subscribes to MQTT messages from IoT Core.
ComponentPublisher: Amazon
ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.mqttproxy:
        com.example.IoTCoreSubscriberCpp:mqttproxy:1:
          policyDescription: Allows access to subscribe to all topics.
          operations:
            - aws.greengrass#SubscribeToIoTCore
          resources:
            - "*"
Manifests:
  - Lifecycle:
      Run: "{artifacts:path}/greengrassv2_iotcore_subscriber"
    Artifacts:
      - URI: s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCoreSubscriberCpp/1.0.0/greengrassv2_iotcore_subscriber
        Permission:
          Execute: OWNER
```

------

다음 예제 C\$1\$1 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 구독하는 방법을 보여줍니다 AWS IoT Core.

```
#include <iostream>

#include <aws/crt/Api.h>
#include <aws/greengrass/GreengrassCoreIpcClient.h>

using namespace Aws::Crt;
using namespace Aws::Greengrass;

class IoTCoreResponseHandler : public SubscribeToIoTCoreStreamHandler {

    public:
        virtual ~IoTCoreResponseHandler() {}

    private:

        void OnStreamEvent(IoTCoreMessage *response) override {
            auto message = response->GetMessage();
            if (message.has_value() && message.value().GetPayload().has_value()) {
                auto messageBytes = message.value().GetPayload().value();
                std::string messageString(messageBytes.begin(), messageBytes.end());
                std::string messageTopic = message.value().GetTopicName().value().c_str();
                std::cout << "Received new message on topic: " << messageTopic << std::endl;
                std::cout << "Message: " << messageString << std::endl;
            }
        }

        bool OnStreamError(OperationError *error) override {
            std::cout << "Received an operation error: ";
            if (error->GetMessage().has_value()) {
                std::cout << error->GetMessage().value();
            }
            std::cout << std::endl;
            return false; // Return true to close stream, false to keep stream open.
        }

        void OnStreamClosed() override {
            std::cout << "Subscribe to IoT Core stream closed." << std::endl;
        }
};

class IpcClientLifecycleHandler : public ConnectionLifecycleHandler {
    void OnConnectCallback() override {
        std::cout << "OnConnectCallback" << std::endl;
    }

    void OnDisconnectCallback(RpcError error) override {
        std::cout << "OnDisconnectCallback: " << error.StatusToString() << std::endl;
        exit(-1);
    }

    bool OnErrorCallback(RpcError error) override {
        std::cout << "OnErrorCallback: " << error.StatusToString() << std::endl;
        return true;
    }
};

int main() {
    String topic("test/topic/cpp");
    QOS qos = QOS_AT_LEAST_ONCE;
    int timeout = 10;

    ApiHandle apiHandle(g_allocator);
    Io::EventLoopGroup eventLoopGroup(1);
    Io::DefaultHostResolver socketResolver(eventLoopGroup, 64, 30);
    Io::ClientBootstrap bootstrap(eventLoopGroup, socketResolver);
    IpcClientLifecycleHandler ipcLifecycleHandler;
    GreengrassCoreIpcClient ipcClient(bootstrap);
    auto connectionStatus = ipcClient.Connect(ipcLifecycleHandler).get();
    if (!connectionStatus) {
        std::cerr << "Failed to establish IPC connection: " << connectionStatus.StatusToString() << std::endl;
        exit(-1);
    }

    SubscribeToIoTCoreRequest request;
    request.SetTopicName(topic);
    request.SetQos(qos);
    auto streamHandler = MakeShared<IoTCoreResponseHandler>(DefaultAllocator());
    auto operation = ipcClient.NewSubscribeToIoTCore(streamHandler);
    auto activate = operation->Activate(request, nullptr);
    activate.wait();

    auto responseFuture = operation->GetResult();
    if (responseFuture.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) {
        std::cerr << "Operation timed out while waiting for response from Greengrass Core." << std::endl;
        exit(-1);
    }

    auto response = responseFuture.get();
    if (response) {
        std::cout << "Successfully subscribed to topic: " << topic << std::endl;
    } else {
        // An error occurred.
        std::cout << "Failed to subscribe to topic: " << topic << std::endl;
        auto errorType = response.GetResultType();
        if (errorType == OPERATION_ERROR) {
            auto *error = response.GetOperationError();
            std::cout << "Operation error: " << error->GetMessage().value() << std::endl;
        } else {
            std::cout << "RPC error: " << response.GetRpcError() << std::endl;
        }
        exit(-1);
    }

    // Keep the main thread alive, or the process will exit.
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    operation->Close();
    return 0;
}
```

### AWS IoT Core 예제 MQTT 게시자(Rust)
<a name="ipc-iot-core-mqtt-example-publisher-rust"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCorePublisherRust",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes MQTT messages to IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCorePublisherRust:mqttproxy:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/publish_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCorePublisherRust/1.0.0/publish_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 Rust 애플리케이션 예제에서는 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 게시하는 방법을 보여줍니다 AWS IoT Core.

```
use gg_sdk::{Qos, Sdk};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let message = b"Hello, World";
    let topic = "my/topic";
    let qos = Qos::AtLeastOnce;

    sdk.publish_to_iot_core(topic, message, qos)
        .expect("Failed to publish to topic");

    println!("Successfully published to topic: {topic}");
}
```

### AWS IoT Core MQTT 구독자 예제(Rust)
<a name="ipc-iot-core-mqtt-example-subscriber-rust"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCoreSubscriberRust",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to MQTT messages from IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCoreSubscriberRust:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/subscribe_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCoreSubscriberRust/1.0.0/subscribe_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 Rust 애플리케이션 예제에서는 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 구독하는 방법을 보여줍니다 AWS IoT Core.

```
use gg_sdk::{Qos, Sdk};
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let topic = "my/topic";
    let qos = Qos::AtLeastOnce;

    let callback = |topic: &str, payload: &[u8]| {
        let message = String::from_utf8_lossy(payload);
        println!("Received new message on topic {topic}: {message}");
    };

    let _sub = sdk
        .subscribe_to_iot_core(topic, qos, &callback)
        .expect("Failed to subscribe to topic");

    println!("Successfully subscribed to topic: {topic}");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

### 예제 AWS IoT Core MQTT 게시자(C)
<a name="ipc-iot-core-mqtt-example-publisher-c"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCorePublisherC",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes MQTT messages to IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCorePublisherC:mqttproxy:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_publish_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCorePublisherC/1.0.0/sample_publish_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 게시하는 방법을 보여줍니다 AWS IoT Core.

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer message = GG_STR("Hello, World");
    GgBuffer topic = GG_STR("my/topic");
    uint8_t qos = 1;

    err = ggipc_publish_to_iot_core(topic, message, qos);
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to publish to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully published to topic: %.*s\n", (int) topic.len, topic.data
    );
}
```

### AWS IoT Core 예제 MQTT 구독자(C)
<a name="ipc-iot-core-mqtt-example-subscriber-c"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCoreSubscriberC",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to MQTT messages from IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCoreSubscriberC:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_subscribe_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCoreSubscriberC/1.0.0/sample_subscribe_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 구독하는 방법을 보여줍니다 AWS IoT Core.

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx, GgBuffer topic, GgBuffer payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    printf(
        "Received new message on topic %.*s: %.*s\n",
        (int) topic.len,
        topic.data,
        (int) payload.len,
        payload.data
    );
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer topic = GG_STR("my/topic");
    uint8_t qos = 1;

    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_iot_core(
        topic, qos, on_subscription_response, NULL, &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to subscribe to topic: %.*s\n",
            (int) topic.len,
            topic.data
        );
        exit(-1);
    }

    printf(
        "Successfully subscribed to topic: %.*s\n", (int) topic.len, topic.data
    );

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the subscription handle.
    ggipc_close_subscription(handle);
}
```

### 예제 AWS IoT Core MQTT 게시자(C\$1\$1, 구성 요소 SDK)
<a name="ipc-iot-core-mqtt-example-publisher-cpp-component-sdk"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제에 게시할 수 있도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCorePublisherCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that publishes MQTT messages to IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCorePublisherCpp:mqttproxy:1": {
            "policyDescription": "Allows access to publish to all topics.",
            "operations": ["aws.greengrass#PublishToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_cpp_publish_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCorePublisherCpp/1.0.0/sample_cpp_publish_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C\$1\$1 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 게시하는 방법을 보여줍니다 AWS IoT Core.

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view message = "Hello, World";
    std::string_view topic = "my/topic";
    uint8_t qos = 1;

    error = client.publish_to_iot_core(topic, message, qos);
    if (error) {
        std::cerr << "Failed to publish to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully published to topic: " << topic << "\n";
}
```

### 예제 AWS IoT Core MQTT 구독자(C\$1\$1, 구성 요소 SDK)
<a name="ipc-iot-core-mqtt-example-subscriber-cpp-component-sdk"></a>

다음 예제 레시피에서는 구성 요소가 모든 주제를 구독하도록 허용합니다.

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.IoTCoreSubscriberCpp",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "A component that subscribes to MQTT messages from IoT Core.",
  "ComponentPublisher": "Amazon",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.IoTCoreSubscriberCpp:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to all topics.",
            "operations": ["aws.greengrass#SubscribeToIoTCore"],
            "resources": ["*"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/sample_cpp_subscribe_to_iot_core"
      },
      "Artifacts": [
        {
          "URI": "s3://amzn-s3-demo-bucket/artifacts/com.example.IoTCoreSubscriberCpp/1.0.0/sample_cpp_subscribe_to_iot_core",
          "Permission": {
            "Execute": "OWNER"
          }
        }
      ]
    }
  ]
}
```

다음 예제 C\$1\$1 애플리케이션은 AWS IoT Core MQTT IPC 서비스를 사용하여 메시지를 구독하는 방법을 보여줍니다 AWS IoT Core.

```
#include <gg/ipc/client.hpp>
#include <unistd.h>
#include <iostream>

class ResponseHandler : public gg::ipc::IotTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Buffer payload,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        std::cout << "Received new message on topic " << topic << ": "
                  << payload << "\n";
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view topic = "my/topic";
    uint8_t qos = 1;

    static ResponseHandler handler;
    error = client.subscribe_to_iot_core(topic, qos, handler);
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << topic << "\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to topic: " << topic << "\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

# 구성 요소 수명 주기와 연동
<a name="ipc-component-lifecycle"></a>

구성 요소 수명 주기 IPC 서비스를 사용하여 다음을 수행할 수 있습니다.
+ 코어 디바이스의 구성 요소 상태를 업데이트합니다.
+ 구성 요소 상태 업데이트를 구독합니다.
+ 배포 중에 업데이트를 적용할 구성 요소를 nucleus가 중지하지 못하게 합니다.
+ 구성 요소 프로세스 일시 중지하고 다시 시작합니다.

**Topics**
+ [최소 SDK 버전](#ipc-component-lifecycle-sdk-versions)
+ [권한 부여](#ipc-component-lifecycle-authorization)
+ [UpdateState](#ipc-operation-updatestate)
+ [SubscribeToComponentUpdates](#ipc-operation-subscribetocomponentupdates)
+ [DeferComponentUpdate](#ipc-operation-defercomponentupdate)
+ [PauseComponent](#ipc-operation-pausecomponent)
+ [ResumeComponent](#ipc-operation-resumecomponent)

## 최소 SDK 버전
<a name="ipc-component-lifecycle-sdk-versions"></a>

다음 표에는 구성 요소 수명 주기와 상호 작용하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-component-lifecycle-authorization"></a>

사용자 지정 구성 요소에서 다른 구성 요소를 일시 중지하거나 다시 시작하려면 구성 요소가 다른 구성 요소를 관리할 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

구성 요소 수명 주기 관리를 위한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.ipc.lifecycle`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#PauseComponent`  |  구성 요소가 지정하는 구성 요소를 일시 중지하도록 허용합니다.  |  구성 요소 이름 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`  | 
|  `aws.greengrass#ResumeComponent`  |  구성 요소가 지정하는 구성 요소를 다시 시작하도록 허용합니다.  |  구성 요소 이름 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`  | 
|  `*`  |  구성 요소가 지정하는 구성 요소를 일시 중지 및 다시 시작하도록 허용합니다.  |  구성 요소 이름 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`  | 

### 권한 부여 정책 예제
<a name="ipc-component-lifecycle-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 권한 부여 정책 예제**  
다음 예제 권한 부여 정책에서는 구성 요소가 모든 구성 요소를 일시 중지 및 다시 시작할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.lifecycle": {
      "com.example.MyLocalLifecycleComponent:lifecycle:1": {
        "policyDescription": "Allows access to pause/resume all components.",
        "operations": [
          "aws.greengrass#PauseComponent",
          "aws.greengrass#ResumeComponent"
        ],
        "resources": [
          "*"
        ]
      }
    }
  }
}
```

## UpdateState
<a name="ipc-operation-updatestate"></a>

코어 디바이스에서 구성 요소의 상태를 업데이트합니다.

### 요청
<a name="ipc-operation-updatestate-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`state`  
설정할 상태입니다. 이 열거형 `LifecycleState`의 값은 다음과 같습니다.  
+ `RUNNING`
+ `ERRORED`

### 응답
<a name="ipc-operation-updatestate-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

### 예제
<a name="ipc-operation-updatestate-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Rust ]

**Example 예: 상태 업데이트**  

```
use gg_sdk::{ComponentState, Sdk};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Update component state to RUNNING
    sdk.update_state(ComponentState::Running)
        .expect("Failed to update component state");

    println!("Successfully updated component state to RUNNING.");
}
```

------
#### [ C ]

**Example 예: 상태 업데이트**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Update component state to RUNNING
    err = ggipc_update_state(GG_COMPONENT_STATE_RUNNING);
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to update component state.\n");
        exit(-1);
    }

    printf("Successfully updated component state to RUNNING.\n");
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 상태 업데이트**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Update component state to RUNNING
    error = client.update_component_state(GG_COMPONENT_STATE_RUNNING);
    if (error) {
        std::cerr << "Failed to update component state.\n";
        exit(-1);
    }

    std::cout << "Successfully updated component state to RUNNING.\n";
}
```

------

## SubscribeToComponentUpdates
<a name="ipc-operation-subscribetocomponentupdates"></a>

 AWS IoT Greengrass 코어 소프트웨어가 구성 요소를 업데이트하기 전에 알림을 수신하도록 구독합니다. 알림에서는 업데이트의 일부로 nucleus가 다시 시작되는지 여부를 지정합니다.

배포의 구성 요소 업데이트 정책에서 구성 요소에 알리도록 지정하는 경우에만 nucleus가 업데이트 알림을 보냅니다. 기본 동작은 구성 요소에 알리는 것입니다. 자세한 내용은 [배포 만들기](create-deployments.md) 섹션 및 [CreateDeployment](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_CreateDeployment.html) 작업을 직접 호출할 때 제공할 수 있는 [DeploymentComponentUpdatePolicy](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_DeploymentComponentUpdatePolicy.html) 객체를 참조하세요.

**중요**  
로컬 배포에서는 업데이트 전에 구성 요소에 알리지 않습니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `ComponentUpdatePolicyEvents`

**작은 정보**  
자습서에 따라 조건부로 구성 요소 업데이트를 연기하는 구성 요소를 개발하는 방법을 알아볼 수 있습니다. 자세한 내용은 [자습서: 구성 요소 업데이트가 지연되는 Greengrass 구성 요소 개발](defer-component-updates-tutorial.md) 단원을 참조하십시오.

### 요청
<a name="ipc-operation-subscribetocomponentupdates-request"></a>

이 작업의 요청에는 파라미터가 없습니다.

### 응답
<a name="ipc-operation-subscribetocomponentupdates-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
알림 메시지의 스트림입니다. 이 객체 `ComponentUpdatePolicyEvents`에는 다음 정보가 포함됩니다.    
`preUpdateEvent`(Python: `pre_update_event`)  
(선택 사항) Nucleus가 구성 요소를 업데이트하려고 함을 나타내는 이벤트입니다. 구성 요소가 다시 시작될 준비가 될 때까지 [DeferComponentUpdate](#ipc-operation-defercomponentupdate) 작업에 응답하여 업데이트를 승인하거나 연기할 수 있습니다. 이 객체 `PreComponentUpdateEvent`에는 다음 정보가 포함됩니다.    
`deploymentId`(Python: `deployment_id`)  
구성 요소를 업데이트하는 AWS IoT Greengrass 배포의 ID입니다.  
`isGgcRestarting`(Python: `is_ggc_restarting`)  
업데이트를 적용하기 위해 nucleus를 다시 시작해야 하는지 여부입니다.  
`postUpdateEvent`(Python: `post_update_event`)  
(선택 사항) Nucleus가 구성 요소를 업데이트했음을 나타내는 이벤트입니다. 이 객체 `PostComponentUpdateEvent`에는 다음 정보가 포함됩니다.    
`deploymentId`(Python: `deployment_id`)  
구성 요소를 업데이트한 AWS IoT Greengrass 배포의 ID입니다.  
이 기능은 Greengrass nucleus 구성 요소의 v2.7.0 이상에서 사용할 수 있습니다.

## DeferComponentUpdate
<a name="ipc-operation-defercomponentupdate"></a>

[SubscribeToComponentUpdates](#ipc-operation-subscribetocomponentupdates)로 검색하는 구성 요소 업데이트를 승인하거나 연기합니다. 구성 요소가 구성 요소 업데이트를 진행할 준비가 되었는지 nucleus가 다시 확인하기 전까지 기다릴 시간을 지정합니다. 이 작업을 사용하여 구성 요소가 업데이트 준비가 되었음을 nucleus에 알릴 수도 있습니다.

구성 요소가 구성 업데이트 알림에 응답하지 않으면 nucleus는 배포의 구성 업데이트 정책에 지정한 시간을 기다립니다. 이 제한 시간이 지나면 nucleus는 배포를 진행합니다. 기본 구성 요소 업데이트 제한 시간은 60초입니다. 자세한 내용은 [배포 만들기](create-deployments.md) 섹션 및 [CreateDeployment](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_CreateDeployment.html) 작업을 직접 호출할 때 제공할 수 있는 [DeploymentComponentUpdatePolicy](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_DeploymentComponentUpdatePolicy.html) 객체를 참조하세요.

**작은 정보**  
자습서에 따라 조건부로 구성 요소 업데이트를 연기하는 구성 요소를 개발하는 방법을 알아볼 수 있습니다. 자세한 내용은 [자습서: 구성 요소 업데이트가 지연되는 Greengrass 구성 요소 개발](defer-component-updates-tutorial.md) 단원을 참조하십시오.

### 요청
<a name="ipc-operation-defercomponentupdate-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`deploymentId`(Python: `deployment_id`)  
연기할 AWS IoT Greengrass 배포의 ID입니다.

`message`  
(선택 사항) 업데이트를 연기할 구성 요소의 이름입니다.  
기본값은 요청을 하는 구성 요소의 이름입니다.

`recheckAfterMs`(Python: `recheck_after_ms`)  
업데이트를 연기할 시간(밀리초)입니다. Nucleus는 이 시간 동안 기다린 다음 [SubscribeToComponentUpdates](#ipc-operation-subscribetocomponentupdates)로 검색할 수 있는 다른 `PreComponentUpdateEvent`를 보냅니다.  
업데이트를 승인하려면 `0`을 지정합니다. 이렇게 하면 구성 요소의 업데이트가 준비되었음을 nucleus에 알립니다.  
기본값은 0밀리초이며, 업데이트를 승인하는 것을 나타냅니다.

### 응답
<a name="ipc-operation-defercomponentupdate-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

## PauseComponent
<a name="ipc-operation-pausecomponent"></a>

이 기능은 [Greengrass nucleus 구성 요소의](greengrass-nucleus-component.md) v2.4.0 이상에서 사용할 수 있습니다. AWS IoT Greengrass 는 현재 Windows 코어 디바이스에서이 기능을 지원하지 않습니다.

코어 디바이스에서 구성 요소의 프로세스를 일시 중지합니다. 구성 요소를 다시 시작하려면 [ResumeComponent](#ipc-operation-resumecomponent) 작업을 사용합니다.

일반 구성 요소만 일시 중지할 수 있습니다. 다른 유형의 구성 요소를 일시 중지하려고 하면 이 작업에서 `InvalidRequestError`를 throw합니다.

**참고**  
이 작업은 Docker 컨테이너와 같은 컨테이너화된 프로세스를 일시 중지할 수 없습니다. Docker 컨테이너를 일시 중지하고 다시 시작하려면 [도커 일시 중지](https://docs.docker.com/engine/reference/commandline/pause/) 및 [도커 일시 중지 해제](https://docs.docker.com/engine/reference/commandline/unpause/) 명령을 사용할 수 있습니다.

이 작업은 구성 요소 종속성 또는 일시 중지하는 구성 요소에 종속된 구성 요소를 일시 중지하지 않습니다. 이 동작은 다른 구성 요소의 종속성인 구성 요소를 일시 중지할 때 사용하는 것이 좋습니다. 해당 종속성이 일시 중지되면 종속 구성 요소에 문제가 발생할 수 있기 때문입니다.

일시 중지된 구성 요소를 배포 등을 통해 다시 시작하거나 종료하면 Greengrass nucleus는 구성 요소를 다시 시작하고 해당 종료 수명 주기를 실행합니다. 구성 요소 다시 시작에 대한 자세한 내용은 [RestartComponent](ipc-local-deployments-components.md#ipc-operation-restartcomponent) 섹션을 참조하세요.

**중요**  
이 작업을 사용하려면 이 작업을 사용할 수 있는 권한을 부여하는 권한 부여 정책을 정의해야 합니다. 자세한 내용은 [권한 부여](#ipc-component-lifecycle-authorization) 단원을 참조하십시오.

### 최소 SDK 버전
<a name="ipc-operation-pausecomponent-sdk-versions"></a>

다음 표에는 구성 요소를 일시 중지하고 재개하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |   v1.4.3  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.6.2  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.13.1  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

### 요청
<a name="ipc-operation-defercomponentupdate-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  
일시 중지할 구성 요소의 이름이며, 일반 구성 요소여야 합니다. 자세한 내용은 [구성 요소 유형](develop-greengrass-components.md#component-types) 단원을 참조하십시오.

### 응답
<a name="ipc-operation-defercomponentupdate-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

## ResumeComponent
<a name="ipc-operation-resumecomponent"></a>

이 기능은 [Greengrass nucleus 구성 요소의](greengrass-nucleus-component.md) v2.4.0 이상에서 사용할 수 있습니다. AWS IoT Greengrass 는 현재 Windows 코어 디바이스에서이 기능을 지원하지 않습니다.

코어 디바이스에서 구성 요소의 프로세스를 다시 시작합니다. 구성 요소를 일시 중지하려면 [PauseComponent](#ipc-operation-pausecomponent) 작업을 사용합니다.

일시 중지된 구성 요소만 다시 시작할 수 있습니다. 일시 중지되지 않은 구성 요소를 다시 시작하려고 하면 이 작업은 `InvalidRequestError`를 발생시킵니다.

**중요**  
이 작업을 사용하려면 이 작업을 수행할 수 있는 권한을 부여하는 권한 부여 정책을 정의해야 합니다. 자세한 내용은 [권한 부여](#ipc-component-lifecycle-authorization) 단원을 참조하십시오.

### 최소 SDK 버전
<a name="ipc-operation-resumecomponent-sdk-versions"></a>

다음 표에는 구성 요소를 일시 중지하고 재개하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |   v1.4.3  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.6.2  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.13.1  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

### 요청
<a name="ipc-operation-defercomponentupdate-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  
다시 시작할 구성 요소의 이름입니다.

### 응답
<a name="ipc-operation-defercomponentupdate-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

# 구성 요소 구성과 연동
<a name="ipc-component-configuration"></a>

구성 요소 구성 IPC 서비스를 사용하여 다음을 수행할 수 있습니다.
+ 구성 요소 구성 파라미터를 가져오고 설정합니다.
+ 구성 요소 구성 업데이트를 구독합니다.
+ nucleus에서 구성 요소 구성 업데이트를 적용하기 전에 검증합니다.

**Topics**
+ [최소 SDK 버전](#ipc-component-configuration-sdk-versions)
+ [GetConfiguration](#ipc-operation-getconfiguration)
+ [UpdateConfiguration](#ipc-operation-updateconfiguration)
+ [SubscribeToConfigurationUpdate](#ipc-operation-subscribetoconfigurationupdate)
+ [SubscribeToValidateConfigurationUpdates](#ipc-operation-subscribetovalidateconfigurationupdates)
+ [SendConfigurationValidityReport](#ipc-operation-sendconfigurationvalidityreport)

## 최소 SDK 버전
<a name="ipc-component-configuration-sdk-versions"></a>

다음 표에는 구성 요소 구성과 상호 작용하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## GetConfiguration
<a name="ipc-operation-getconfiguration"></a>

코어 디바이스의 구성 요소에 대한 구성 값을 가져옵니다. 구성 값을 가져올 키 경로를 지정합니다.

### 요청
<a name="ipc-operation-getconfiguration-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  <a name="ipc-configuration-request-component-name"></a>
(선택 사항) 구성 요소의 이름입니다.  
기본값은 요청을 하는 구성 요소의 이름입니다.

`keyPath`(Python: `key_path`)  
구성 값의 키 경로입니다. 각 항목이 구성 객체에서 단일 수준에 대한 키인 목록을 지정합니다. 예를 들어 다음 구성에서 `port`의 값을 가져오려면 `["mqtt", "port"]`를 지정합니다.  

```
{
  "mqtt": {
    "port": 443
  }
}
```
구성 요소의 전체 구성을 가져오려면 빈 목록을 지정합니다.

### 응답
<a name="ipc-operation-getconfiguration-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`componentName`(Python: `component_name`)  <a name="ipc-configuration-response-component-name"></a>
구성 요소의 이름입니다.

`value`  
객체인 요청된 구성입니다.

### 예제
<a name="ipc-operation-getconfiguration-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Rust ]

**Example 예: 구성 가져오기**  

```
use core::mem::MaybeUninit;
use gg_sdk::{Sdk, UnpackedObject};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Get a configuration value at key path ["mqtt", "port"]
    let mut buf = [MaybeUninit::uninit(); 1024];

    let value = sdk
        .get_config(&["mqtt", "port"], None, &mut buf)
        .expect("Failed to get configuration");

    if let UnpackedObject::I64(port) = value.unpack() {
        println!("Configuration value: {port}");
    }
}
```

------
#### [ C ]

**Example 예: 구성 가져오기**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Get a configuration value at key path ["mqtt", "port"]
    uint8_t response_mem[1024];
    GgObject value;

    err = ggipc_get_config(
        GG_BUF_LIST(GG_STR("mqtt"), GG_STR("port")),
        NULL, // component_name (NULL = current component)
        GG_BUF(response_mem),
        &value
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to get configuration.\n");
        exit(-1);
    }

    if (gg_obj_type(value) == GG_TYPE_I64) {
        printf("Configuration value: %" PRId64 "\n", gg_obj_into_i64(value));
    } else if (gg_obj_type(value) == GG_TYPE_BUF) {
        GgBuffer buf = gg_obj_into_buf(value);
        printf("Configuration value: %.*s\n", (int) buf.len, buf.data);
    } else {
        printf("Configuration value is of unexpected type.\n");
    }
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 구성 가져오기**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Get a configuration value at key path ["mqtt", "port"]
    std::array key_path = { gg::Buffer { "mqtt" }, gg::Buffer { "port" } };
    int64_t value = 0;

    error = client.get_config(key_path, std::nullopt, value);
    if (error) {
        std::cerr << "Failed to get configuration.\n";
        exit(-1);
    }

    std::cout << "Configuration value: " << value << "\n";
}
```

------

## UpdateConfiguration
<a name="ipc-operation-updateconfiguration"></a>

코어 디바이스에서 이 구성 요소에 대한 구성 값을 업데이트합니다.

### 요청
<a name="ipc-operation-updateconfiguration-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`keyPath`(Python: `key_path`)  
(선택 사항) 업데이트할 컨테이너 노드(객체)의 키 경로입니다. 각 항목이 구성 객체에서 단일 수준에 대한 키인 목록을 지정합니다. 예를 들어 다음 구성에서 `port`의 값을 설정하려면 키 경로 `["mqtt"]` 및 병합 값 `{ "port": 443 }`을 지정합니다.  

```
{
  "mqtt": {
    "port": 443
  }
}
```
키 경로는 구성의 컨테이너 노드(객체)를 지정해야 합니다. 노드가 구성 요소의 구성에 없는 경우 이 작업은 노드를 생성하고 해당 값을 `valueToMerge`의 객체로 설정합니다.  
기본값은 구성 객체의 루트입니다.

`timestamp`  
현재 Unix epoch 시간(밀리초)입니다. 이 작업은 이 타임스탬프를 사용하여 키에 대한 동시 업데이트를 해결합니다. 구성 요소 구성의 키의 타임스탬프가 요청의 타임스탬프보다 크면 요청이 실패합니다.

`valueToMerge`(Python: `value_to_merge`)  
`keyPath`에서 지정하는 위치에서 병합할 구성 객체입니다. 자세한 내용은 [구성 요소 구성 업데이트](update-component-configurations.md) 단원을 참조하십시오.

### 응답
<a name="ipc-operation-updateconfiguration-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

### 예제
<a name="ipc-operation-updateconfiguration-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Rust ]

**Example 예: 구성 업데이트**  

```
use gg_sdk::Sdk;

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Update configuration value at key path ["mqtt", "port"] to 443
    sdk.update_config(&["mqtt", "port"], None, 443)
        .expect("Failed to update configuration");

    println!("Successfully updated configuration.");
}
```

------
#### [ C ]

**Example 예: 구성 업데이트**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Update configuration value at key path ["mqtt", "port"] to 443
    err = ggipc_update_config(
        GG_BUF_LIST(GG_STR("mqtt"), GG_STR("port")),
        NULL, // timestamp (NULL = current time)
        gg_obj_i64(443)
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to update configuration.\n");
        exit(-1);
    }

    printf("Successfully updated configuration.\n");
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 구성 업데이트**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Update configuration value at key path ["mqtt", "port"] to 443
    std::array key_path = { gg::Buffer { "mqtt" }, gg::Buffer { "port" } };

    error = client.update_config(key_path, 443);
    if (error) {
        std::cerr << "Failed to update configuration.\n";
        exit(-1);
    }

    std::cout << "Successfully updated configuration.\n";
}
```

------

## SubscribeToConfigurationUpdate
<a name="ipc-operation-subscribetoconfigurationupdate"></a>

구성 요소의 구성이 업데이트될 때 알림을 수신하려면 구독합니다. 키를 구독하는 경우 해당 키의 하위 키가 업데이트되면 알림을 받습니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `ConfigurationUpdateEvents`

### 요청
<a name="ipc-operation-subscribetoconfigurationupdate-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  <a name="ipc-configuration-request-component-name"></a>
(선택 사항) 구성 요소의 이름입니다.  
기본값은 요청을 하는 구성 요소의 이름입니다.

`keyPath`(Python: `key_path`)  
구독할 구성 값의 키 경로입니다. 각 항목이 구성 객체에서 단일 수준에 대한 키인 목록을 지정합니다. 예를 들어 다음 구성에서 `port`의 값을 가져오려면 `["mqtt", "port"]`를 지정합니다.  

```
{
  "mqtt": {
    "port": 443
  }
}
```
구성 요소 구성에서 모든 값에 대한 업데이트를 구독하려면 빈 목록을 지정합니다.

### 응답
<a name="ipc-operation-subscribetoconfigurationupdate-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
알림 메시지의 스트림입니다. 이 객체 `ConfigurationUpdateEvents`에는 다음 정보가 포함됩니다.    
`configurationUpdateEvent`(Python: `configuration_update_event`)  
구성 업데이트 이벤트입니다. 이 객체 `ConfigurationUpdateEvent`에는 다음 정보가 포함됩니다.    
`componentName`(Python: `component_name`)  <a name="ipc-configuration-response-component-name"></a>
구성 요소의 이름입니다.  
`keyPath`(Python: `key_path`)  
업데이트된 구성 값의 키 경로입니다.

### 예제
<a name="ipc-operation-subscribetoconfigurationupdate-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Rust ]

**Example 예: 구성 업데이트 구독**  

```
use gg_sdk::Sdk;
use std::{thread, time::Duration};

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    // Subscribe to configuration updates for key path ["mqtt"]
    let callback = |component_name: &str, key_path: &[&str]| {
        println!(
            "Received configuration update for component: {component_name}"
        );
        println!("Key path: {key_path:?}");
    };

    let _sub = sdk
        .subscribe_to_configuration_update(None, &["mqtt"], &callback)
        .expect("Failed to subscribe to configuration updates");

    println!("Successfully subscribed to configuration updates.");

    // Keep the main thread alive, or the process will exit.
    loop {
        thread::sleep(Duration::from_secs(10));
    }
}
```

------
#### [ C ]

**Example 예: 구성 업데이트 구독**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

static void on_subscription_response(
    void *ctx,
    GgBuffer component_name,
    GgList key_path,
    GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) handle;

    printf(
        "Received configuration update for component: %.*s\n",
        (int) component_name.len,
        component_name.data
    );

    printf("Key path: [");
    for (size_t i = 0; i < key_path.len; i++) {
        if (i > 0) {
            printf(", ");
        }
        GgObject *obj = &key_path.items[i];
        if (gg_obj_type(*obj) == GG_TYPE_BUF) {
            GgBuffer key = gg_obj_into_buf(*obj);
            printf("\"%.*s\"", (int) key.len, key.data);
        }
    }
    printf("]\n");
}

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    // Subscribe to configuration updates for key path ["mqtt"]
    GgIpcSubscriptionHandle handle;
    err = ggipc_subscribe_to_configuration_update(
        NULL, // component_name (NULL = current component)
        GG_BUF_LIST(GG_STR("mqtt")),
        on_subscription_response,
        NULL,
        &handle
    );
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to subscribe to configuration updates.\n");
        exit(-1);
    }

    printf("Successfully subscribed to configuration updates.\n");

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }

    // To stop subscribing, close the stream.
    ggipc_close_subscription(handle);
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 구성 업데이트 구독**  

```
#include <gg/ipc/client.hpp>
#include <unistd.h>
#include <iostream>

class ResponseHandler : public gg::ipc::ConfigurationUpdateCallback {
    void operator()(
        std::string_view component_name,
        gg::List key_path,
        gg::ipc::Subscription &handle
    ) override {
        (void) handle;
        std::cout << "Received configuration update for component: "
                  << component_name << "\n";
        std::cout << "Key path: [";
        for (size_t i = 0; i < key_path.size(); i++) {
            if (i > 0) {
                std::cout << ", ";
            }
            std::cout << "\"" << get<gg::Buffer>(key_path[i]) << "\"";
        }
        std::cout << "]\n";
    }
};

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    // Subscribe to configuration updates for key path ["mqtt"]
    std::array key_path = { gg::Buffer { "mqtt" } };

    static ResponseHandler handler;
    error = client.subscribe_to_configuration_update(
        key_path, std::nullopt, handler
    );
    if (error) {
        std::cerr << "Failed to subscribe to configuration updates.\n";
        exit(-1);
    }

    std::cout << "Successfully subscribed to configuration updates.\n";

    // Keep the main thread alive, or the process will exit.
    while (1) {
        sleep(10);
    }
}
```

------

## SubscribeToValidateConfigurationUpdates
<a name="ipc-operation-subscribetovalidateconfigurationupdates"></a>

이 구성 요소의 구성이 업데이트되기 전에 알림을 수신하려면 구독합니다. 그러면 구성 요소가 자체 구성에 대한 업데이트를 검증할 수 있습니다. [SendConfigurationValidityReport](#ipc-operation-sendconfigurationvalidityreport) 작업을 사용하면 구성이 유효한지 여부를 nucleus에 알립니다.

**중요**  
로컬 배포에서는 업데이트에 대해 구성 요소에 알리지 않습니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `ValidateConfigurationUpdateEvents`

### 요청
<a name="ipc-operation-subscribetovalidateconfigurationupdates-request"></a>

이 작업의 요청에는 파라미터가 없습니다.

### 응답
<a name="ipc-operation-subscribetovalidateconfigurationupdates-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
알림 메시지의 스트림입니다. 이 객체 `ValidateConfigurationUpdateEvents`에는 다음 정보가 포함됩니다.    
`validateConfigurationUpdateEvent`(Python: `validate_configuration_update_event`)  
구성 업데이트 이벤트입니다. 이 객체 `ValidateConfigurationUpdateEvent`에는 다음 정보가 포함됩니다.    
`deploymentId`(Python: `deployment_id`)  
구성 요소를 업데이트하는 AWS IoT Greengrass 배포의 ID입니다.  
`configuration`  
새 구성을 포함하는 객체입니다.

## SendConfigurationValidityReport
<a name="ipc-operation-sendconfigurationvalidityreport"></a>

이 구성 요소에 대한 구성 업데이트가 유효한지 여부를 nucleus에 알립니다. 새 구성이 유효하지 않다고 nucleus에 알리면 배포가 실패합니다. [SubscribeToValidateConfigurationUpdates](#ipc-operation-subscribetovalidateconfigurationupdates) 작업을 사용하면 구성 업데이트 검증을 구독할 수 있습니다.

구성 요소가 구성 업데이트 검증 알림에 응답하지 않으면 nucleus는 배포의 구성 검증 정책에 지정한 시간을 기다립니다. 이 제한 시간이 지나면 nucleus는 배포를 진행합니다. 기본 구성 요소 검증 제한 시간은 20초입니다. 자세한 내용은 [배포 만들기](create-deployments.md) 섹션 및 [CreateDeployment](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_CreateDeployment.html) 작업을 직접 호출할 때 제공할 수 있는 [DeploymentConfigurationValidationPolicy](https://docs.aws.amazon.com/greengrass/v2/APIReference/API_DeploymentConfigurationValidationPolicy.html) 객체를 참조하세요.

### 요청
<a name="ipc-operation-sendconfigurationvalidityreport-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`configurationValidityReport`(Python: `configuration_validity_report`)  
구성 업데이트가 유효한지 여부를 nucleus에 알려주는 보고서입니다. 이 객체 `ConfigurationValidityReport`에는 다음 정보가 포함됩니다.    
`status`  
유효성 상태입니다. 이 열거형 `ConfigurationValidityStatus`의 값은 다음과 같습니다.  
+ `ACCEPTED` - 구성이 유효하며 nucleus가 이 구성 요소에 적용할 수 있습니다.
+ `REJECTED` - 구성이 유효하지 않고 배포가 실패합니다.  
`deploymentId`(Python: `deployment_id`)  
구성 업데이트를 요청한 AWS IoT Greengrass 배포의 ID입니다.  
`message`  
(선택 사항) 구성이 유효하지 않은 이유를 보고하는 메시지입니다.

### 응답
<a name="ipc-operation-sendconfigurationvalidityreport-response"></a>

이 작업의 응답에는 어떠한 정보도 제공하지 않습니다.

# 보안 암호 값 검색
<a name="ipc-secret-manager"></a>

보안 암호 관리자 IPC 서비스를 사용하여 코어 디바이스의 보안 암호에서 보안 암호 값을 검색할 수 있습니다. [보안 암호 관리자 구성 요소](secret-manager-component.md)를 사용하여 암호화된 보안 암호를 코어 디바이스에 배포합니다. 그런 다음 IPC 작업을 사용하여 보안 암호를 복호화하고 사용자 지정 구성 요소에서 해당 값을 사용할 수 있습니다.

**Topics**
+ [최소 SDK 버전](#ipc-secret-manager-sdk-versions)
+ [권한 부여](#ipc-secret-manager-authorization)
+ [GetSecretValue](#ipc-operation-getsecretvalue)
+ [예제](#ipc-secret-manager-examples)

## 최소 SDK 버전
<a name="ipc-secret-manager-sdk-versions"></a>

다음 표에는 코어 디바이스의 보안 암호에서 보안 암호 값을 검색하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-secret-manager-authorization"></a>

사용자 지정 구성 요소에서 보안 암호 관리자를 사용하려면 구성 요소가 코어 디바이스에 저장하는 보안 암호의 값을 가져올 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

보안 암호 관리자에 대한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.SecretManager`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#GetSecretValue` 또는 `*`  |  구성 요소가 코어 디바이스에서 암호화된 보안 암호의 값을 가져올 수 있도록 허용합니다.  |  Secrets Manager 보안 암호 ARN 또는 모든 보안 암호에 대한 액세스를 허용하려면 `*`입니다.  | 

### 권한 부여 정책 예제
<a name="ipc-secret-manager-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 권한 부여 정책 예제**  
다음 예제 권한 부여 정책에서는 구성 요소가 코어 디바이스에서 보안 암호 값을 가져올 수 있도록 허용합니다.  
프로덕션 환경에서는 구성 요소가 사용하는 보안 암호만 검색하도록 권한 부여 정책의 범위를 줄이는 것이 좋습니다. 구성 요소를 배포할 때 `*` 와일드카드를 보안 암호 ARN 목록으로 변경할 수 있습니다.

```
{
  "accessControl": {
    "aws.greengrass.SecretManager": {
      "com.example.MySecretComponent:secrets:1": {
        "policyDescription": "Allows access to a secret.",
        "operations": [
          "aws.greengrass#GetSecretValue"
        ],
        "resources": [
          "*"
        ]
      }
    }
  }
}
```

## GetSecretValue
<a name="ipc-operation-getsecretvalue"></a>

코어 디바이스에 저장하는 보안 암호의 값을 가져옵니다.

이 작업은 AWS 클라우드에서 보안 암호의 값을 가져오는 데 사용할 수 있는 Secrets Manager 작업과 유사합니다. 자세한 내용은 *AWS Secrets Manager API 참조*의 [GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)를 참조하세요.

### 요청
<a name="ipc-operation-getsecretvalue-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`refresh`(Python: `refresh`)  
(선택 사항): 요청된 보안 암호를 AWS Secrets Manager 서비스의 최신 값과 동기화할지 여부입니다.  
true로 설정하면 보안 암호 관리자가 지정된 보안 암호 레이블의 최신 값을 AWS Secrets Manager 서비스에 요청하고 해당 값을 응답으로 반환합니다. 그렇지 않으면 로컬에 저장된 보안 암호 값이 반환됩니다.  
 이 파라미터는 요청의 `versionId` 파라미터와 함께 사용할 수 없습니다. 이 파라미터는 Nucleus 2.13.0 이상과 함께 사용할 때 작동합니다.

`secretId`(Python: `secret_id`)  
가져올 보안 암호의 이름입니다. Amazon 리소스 이름(ARN) 또는 보안 암호의 표시 이름을 지정할 수 있습니다.

`versionId`(Python: `version_id`)  
(선택 사항) 가져올 버전의 ID입니다.  
`versionId` 또는 `versionStage`를 지정할 수 있습니다.  
`versionId` 또는 `versionStage`를 지정하지 않으면 이 작업의 기본값은 `AWSCURRENT` 레이블이 있는 버전입니다.

`versionStage`(Python: `version_stage`)  
(선택 사항) 가져올 버전의 스테이징 레이블입니다.  
`versionId` 또는 `versionStage`를 지정할 수 있습니다.  
`versionId` 또는 `versionStage`를 지정하지 않으면 이 작업의 기본값은 `AWSCURRENT` 레이블이 있는 버전입니다.

### 응답
<a name="ipc-operation-getsecretvalue-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`secretId`(Python: `secret_id`)  
보안 암호의 ID입니다.

`versionId`(Python: `version_id`)  
이 보안 암호 버전의 ID입니다.

`versionStage`(Python: `version_stage`)  
이 보안 암호 버전에 연결된 스테이징 레이블의 목록입니다.

`secretValue`(Python: `secret_value`)  
이 보안 암호 버전의 값입니다. 이 객체 `SecretValue`에는 다음 정보가 포함됩니다.    
`secretString`(Python: `secret_string`)  
Secrets Manager에 문자열로 제공한 보호된 보안 암호 정보의 복호화된 부분입니다.  
`secretBinary`(Python: `secret_binary`)  
(선택 사항) Secrets Manager에 바이트 배열 형식의 이진 데이터로 제공한 보호된 보안 암호 정보의 복호화된 부분입니다. 이 속성에는 base64로 인코딩된 문자열인 이진 데이터가 포함됩니다.  
Secrets Manager 콘솔에서 보안 암호를 생성한 경우 이 속성은 사용되지 않습니다.

### 예제
<a name="ipc-operation-getsecretvalue-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V1) ]

**Example 예: 보안 암호 값 가져오기**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GetSecretValueResponseHandler;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.model.GetSecretValueRequest;
import software.amazon.awssdk.aws.greengrass.model.GetSecretValueResponse;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class GetSecretValue {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        String secretArn = args[0];
        String versionStage = args[1];
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            GetSecretValueResponseHandler responseHandler =
                    GetSecretValue.getSecretValue(ipcClient, secretArn, versionStage);
            CompletableFuture<GetSecretValueResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                GetSecretValueResponse response = futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                response.getSecretValue().postFromJson();
                String secretString = response.getSecretValue().getSecretString();
                System.out.println("Successfully retrieved secret value: " + secretString);
            } catch (TimeoutException e) {
                System.err.println("Timeout occurred while retrieving secret: " + secretArn);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.println("Unauthorized error while retrieving secret: " + secretArn);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static GetSecretValueResponseHandler getSecretValue(GreengrassCoreIPCClient greengrassCoreIPCClient, String secretArn, String versionStage) {
        GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest();
        getSecretValueRequest.setSecretId(secretArn);
        getSecretValueRequest.setVersionStage(versionStage);
        return greengrassCoreIPCClient.getSecretValue(getSecretValueRequest, Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 보안 암호 값 가져오기**  
이 예제에서는 Python v2 AWS IoT Device SDK 용의 버전 1.5.4 이상을 사용하고 있다고 가정합니다.

```
import json

import awsiot.greengrasscoreipc
from awsiot.greengrasscoreipc.model import (
    GetSecretValueRequest,
    GetSecretValueResponse,
    UnauthorizedError
)

secret_id = 'arn:aws:secretsmanager:us-west-2:123456789012:secret:MyGreengrassSecret-abcdef'
TIMEOUT = 10

ipc_client = awsiot.greengrasscoreipc.connect()

request = GetSecretValueRequest()
request.secret_id = secret_id
request.version_stage = 'AWSCURRENT'
operation = ipc_client.new_get_secret_value()
operation.activate(request)
future_response = operation.get_response()
response = future_response.result(TIMEOUT)
secret_json = json.loads(response.secret_value.secret_string)
# Handle secret value.
```

------
#### [ JavaScript ]

**Example 예: 보안 암호 값 가져오기**  

```
import {
    GetSecretValueRequest,
} from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model';
import * as greengrasscoreipc from "aws-iot-device-sdk-v2/dist/greengrasscoreipc";
 
class GetSecretValue {
    private readonly secretId : string;
    private readonly versionStage : string;
    private ipcClient : greengrasscoreipc.Client
 
    constructor() {
        this.secretId = "<define_your_own_secretId>"
        this.versionStage = "<define_your_own_versionStage>"
 
        this.getSecretValue().then(r => console.log("Started workflow"));
    }
 
    private async getSecretValue() {
        try {
            this.ipcClient = await getIpcClient();
 
            const getSecretValueRequest : GetSecretValueRequest = {
                secretId: this.secretId,
                versionStage: this.versionStage,
            };
 
            const result = await this.ipcClient.getSecretValue(getSecretValueRequest);
            const secretString = result.secretValue.secretString;
            console.log("Successfully retrieved secret value: " + secretString)
        } catch (e) {
            // parse the error depending on your use cases
            throw e
        }
    }
}
 
export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}
 
const getSecretValue = new GetSecretValue();
```

------

## 예제
<a name="ipc-secret-manager-examples"></a>

다음 예제를 사용하여 구성 요소에서 보안 암호 관리자 IPC 서비스를 사용하는 방법을 알아봅니다.

### 예: 보안 암호 출력(Python, IPC 클라이언트 V1)
<a name="ipc-secret-manager-example-print-secret-python"></a>

이 예제 구성 요소에서는 코어 디바이스에 배포하는 보안 암호의 값을 출력합니다.

**중요**  
이 예제 구성 요소는 보안 암호의 값을 출력하므로 테스트 데이터를 저장하는 보안 암호로만 사용하세요. 중요한 정보를 저장하는 보안 암호의 값을 출력하기 위해 이 구성 요소를 사용하지 마세요.

**Topics**
+ [방법](#ipc-secret-manager-example-print-secret-python-recipe)
+ [아티팩트](#ipc-secret-manager-example-print-secret-python-artifacts)
+ [사용법](#ipc-secret-manager-example-print-secret-python-usage)

#### 방법
<a name="ipc-secret-manager-example-print-secret-python-recipe"></a>

다음 예제 레시피에서는 보안 암호 ARN 구성 파라미터를 정의하고 구성 요소가 코어 디바이스에서 임의의 보안 암호 값을 가져올 수 있도록 허용합니다.

**참고**  <a name="ipc-secret-manager-authorization-policy-resource-wildcard"></a>
프로덕션 환경에서는 구성 요소가 사용하는 보안 암호만 검색하도록 권한 부여 정책의 범위를 줄이는 것이 좋습니다. 구성 요소를 배포할 때 `*` 와일드카드를 보안 암호 ARN 목록으로 변경할 수 있습니다.

------
#### [ JSON ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.PrintSecret",
  "ComponentVersion": "1.0.0",
  "ComponentDescription": "Prints the value of an AWS Secrets Manager secret.",
  "ComponentPublisher": "Amazon",
  "ComponentDependencies": {
    "aws.greengrass.SecretManager": {
      "VersionRequirement": "^2.0.0",
      "DependencyType": "HARD"
    }
  },
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "SecretArn": "",
      "accessControl": {
        "aws.greengrass.SecretManager": {
          "com.example.PrintSecret:secrets:1": {
            "policyDescription": "Allows access to a secret.",
            "operations": [
              "aws.greengrass#GetSecretValue"
            ],
            "resources": [
              "*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux"
      },
      "Lifecycle": {
        "install": "python3 -m pip install --user awsiotsdk",
        "Run": "python3 -u {artifacts:path}/print_secret.py \"{configuration:/SecretArn}\""
      }
    },
    {
      "Platform": {
        "os": "windows"
      },
      "Lifecycle": {
        "install": "py -3 -m pip install --user awsiotsdk",
        "Run": "py -3 -u {artifacts:path}/print_secret.py \"{configuration:/SecretArn}\""
      }
    }
  ]
}
```

------
#### [ YAML ]

```
---
RecipeFormatVersion: '2020-01-25'
ComponentName: com.example.PrintSecret
ComponentVersion: 1.0.0
ComponentDescription: Prints the value of a Secrets Manager secret.
ComponentPublisher: Amazon
ComponentDependencies:
  aws.greengrass.SecretManager:
    VersionRequirement: "^2.0.0"
    DependencyType: HARD
ComponentConfiguration:
  DefaultConfiguration:
    SecretArn: ''
    accessControl:
      aws.greengrass.SecretManager:
        com.example.PrintSecret:secrets:1:
          policyDescription: Allows access to a secret.
          operations:
            - aws.greengrass#GetSecretValue
          resources:
            - "*"
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      install: python3 -m pip install --user awsiotsdk
      Run: python3 -u {artifacts:path}/print_secret.py "{configuration:/SecretArn}"
  - Platform:
      os: windows
    Lifecycle:
      install: py -3 -m pip install --user awsiotsdk
      Run: py -3 -u {artifacts:path}/print_secret.py "{configuration:/SecretArn}"
```

------

#### 아티팩트
<a name="ipc-secret-manager-example-print-secret-python-artifacts"></a>

다음 예제 Python 애플리케이션에서는 보안 암호 관리자 IPC 서비스를 사용하여 코어 디바이스에서 보안 암호 값을 가져오는 방법을 보여줍니다.

```
import concurrent.futures
import json
import sys
import traceback

import awsiot.greengrasscoreipc
from awsiot.greengrasscoreipc.model import (
    GetSecretValueRequest,
    GetSecretValueResponse,
    UnauthorizedError
)

TIMEOUT = 10

if len(sys.argv) == 1:
    print('Provide SecretArn in the component configuration.', file=sys.stdout)
    exit(1)

secret_id = sys.argv[1]

try:
    ipc_client = awsiot.greengrasscoreipc.connect()

    request = GetSecretValueRequest()
    request.secret_id = secret_id
    operation = ipc_client.new_get_secret_value()
    operation.activate(request)
    future_response = operation.get_response()

    try:
        response = future_response.result(TIMEOUT)
        secret_json = json.loads(response.secret_value.secret_string)
        print('Successfully got secret: ' + secret_id)
        print('Secret value: ' + str(secret_json))
    except concurrent.futures.TimeoutError:
        print('Timeout occurred while getting secret: ' + secret_id, file=sys.stderr)
    except UnauthorizedError as e:
        print('Unauthorized error while getting secret: ' + secret_id, file=sys.stderr)
        raise e
    except Exception as e:
        print('Exception while getting secret: ' + secret_id, file=sys.stderr)
        raise e
except Exception:
    print('Exception occurred when using IPC.', file=sys.stderr)
    traceback.print_exc()
    exit(1)
```

#### 사용법
<a name="ipc-secret-manager-example-print-secret-python-usage"></a>

이 예제 구성 요소를 [보안 암호 관리자 구성 요소](secret-manager-component.md)와 함께 사용하여 코어 디바이스의 보안 암호 값을 배포하고 출력할 수 있습니다.

**테스트 보안 암호를 생성, 배포 및 출력하려면**

1. 테스트 데이터를 사용하여 Secrets Manager 보안 암호를 생성합니다.

------
#### [ Linux or Unix ]

   ```
   aws secretsmanager create-secret \
     --name MyTestGreengrassSecret \
     --secret-string '{"my-secret-key": "my-secret-value"}'
   ```

------
#### [ Windows Command Prompt (CMD) ]

   ```
   aws secretsmanager create-secret ^
     --name MyTestGreengrassSecret ^
     --secret-string '{"my-secret-key": "my-secret-value"}'
   ```

------
#### [ PowerShell ]

   ```
   aws secretsmanager create-secret `
     --name MyTestGreengrassSecret `
     --secret-string '{"my-secret-key": "my-secret-value"}'
   ```

------

   다음 단계에서 사용할 보안 암호의 ARN을 저장합니다.

   자세한 내용은 *AWS Secrets Manager 사용 설명서*의 [보안 암호 생성](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html)을 참조하세요.

1. 다음 구성 병합 업데이트를 사용하여 [보안 암호 관리자 구성 요소](secret-manager-component.md)(`aws.greengrass.SecretManager`)를 배포합니다. 이전에 생성한 보안 암호의 ARN을 지정합니다.

   ```
   {
     "cloudSecrets": [
       {
         "arn": "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestGreengrassSecret-abcdef"
       }
     ]
   }
   ```

   자세한 내용은 [디바이스에 AWS IoT Greengrass 구성 요소 배포](manage-deployments.md) 또는 [Greengrass CLI deployment 명령](gg-cli-deployment.md)을 참조하세요.

1. 다음 구성 병합 업데이트를 사용하여 이 섹션의 예제 구성 요소를 생성하고 배포합니다. 이전에 생성한 보안 암호의 ARN을 지정합니다.

   ```
   {
     "SecretArn": "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestGreengrassSecret",
     "accessControl": {
       "aws.greengrass.SecretManager": {
         "com.example.PrintSecret:secrets:1": {
           "policyDescription": "Allows access to a secret.",
           "operations": [
             "aws.greengrass#GetSecretValue"
           ],
           "resources": [
             "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestGreengrassSecret-abcdef"
           ]
         }
       }
     }
   }
   ```

   자세한 내용은 [AWS IoT Greengrass 구성 요소 생성](create-components.md) 섹션을 참조하세요.

1.  AWS IoT Greengrass 코어 소프트웨어 로그를 보고 배포가 성공했는지 확인하고 구성 `com.example.PrintSecret` 요소 로그를 보고 인쇄된 보안 암호 값을 확인합니다. 자세한 내용은 [AWS IoT Greengrass 로그 모니터링](monitor-logs.md) 단원을 참조하십시오.

# 로컬 섀도와 연동
<a name="ipc-local-shadows"></a>

섀도 IPC 서비스를 사용하여 디바이스의 로컬 섀도와 연동합니다. 연동할 디바이스로 코어 디바이스나 연결된 클라이언트 디바이스를 선택할 수 있습니다.

이러한 IPC 작업을 사용하려면 [섀도 관리자 구성 요소](shadow-manager-component.md)를 사용자 지정 구성 요소의 종속성으로 포함합니다. 그런 다음 사용자 지정 구성 요소에서 IPC 작업을 사용하여 섀도 관리자를 통해 디바이스의 로컬 섀도와 연동할 수 있습니다. 사용자 지정 구성 요소가 로컬 섀도 상태 변경에 대응할 수 있도록 하려면 게시/구독 IPC 서비스를 사용하여 섀도 이벤트를 구독할 수도 있습니다. 게시/구독 서비스 사용에 대한 자세한 내용은 [로컬 메시지 게시/구독](ipc-publish-subscribe.md) 섹션을 참조하세요.

**참고**  <a name="note-requirement-enable-shadow-manager-client-devices"></a>
코어 디바이스가 클라이언트 디바이스 섀도와 연동할 수 있도록 하려면 MQTT 브리지 구성 요소도 구성하고 배포해야 합니다. 자세한 내용은 [섀도 관리자가 클라이언트 디바이스와 통신할 수 있도록 설정](work-with-client-device-shadows.md)을 참조하세요.

**Topics**
+ [최소 SDK 버전](#ipc-local-shadows-sdk-versions)
+ [권한 부여](#ipc-local-shadow-authorization)
+ [GetThingShadow](#ipc-operation-getthingshadow)
+ [UpdateThingShadow](#ipc-operation-updatethingshadow)
+ [DeleteThingShadow](#ipc-operation-deletethingshadow)
+ [ListNamedShadowsForThing](#ipc-operation-listnamedshadowsforthing)

## 최소 SDK 버전
<a name="ipc-local-shadows-sdk-versions"></a>

다음 표에는 로컬 섀도와 상호 작용하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.4.0  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.6.0  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-local-shadow-authorization"></a>

사용자 지정 구성 요소에서 섀도 IPC 서비스를 사용하려면 구성 요소가 섀도와 연동할 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

섀도 연동에 대한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.ShadowManager`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#GetThingShadow`  |  구성 요소가 사물의 섀도를 검색할 수 있도록 허용합니다.  |  다음 문자열 중 하나입니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#UpdateThingShadow`  |  구성 요소가 사물의 섀도를 업데이트할 수 있도록 허용합니다.  |  다음 문자열 중 하나입니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#DeleteThingShadow`  |  구성 요소가 사물의 섀도를 삭제할 수 있도록 허용합니다.  |  다음 문자열 중 하나입니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#ListNamedShadowsForThing`  |  구성 요소가 사물의 이름 지정된 섀도 목록을 검색할 수 있도록 허용합니다.  |  섀도를 사물에 액세스하여 해당 섀도를 나열하도록 허용하는 사물 이름 문자열입니다. 모든 사물에 대한 액세스를 허용하려면 `*`를 사용합니다.  | 

**IPC 서비스 식별자:** `aws.greengrass.ipc.pubsub`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#SubscribeToTopic`  |  구성 요소가 에서 지정하는 주제에 대한 메시지를 구독할 수 있도록 허용합니다.  |  다음 주제 문자열 중 하나입니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-local-shadows.html) 주제 접두사 `shadowTopicPrefix`의 값은 섀도 유형에 따라 달라집니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/greengrass/v2/developerguide/ipc-local-shadows.html) 모든 주제에 대한 액세스를 허용하려면 `*`를 사용합니다. <a name="ipc-local-publish-subscribe-authorization-mqtt-wildcards"></a>[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상에서는 MQTT 주제 와일드카드(`#` 및 `+`)가 포함된 주제를 구독할 수 있습니다. 이 주제 문자열은 MQTT 주제 와일드카드를 리터럴 문자로 지원합니다. 예를 들어 구성 요소의 권한 부여 정책에서 `test/topic/#`에 대한 액세스 권한을 부여하는 경우 구성 요소는 `test/topic/#`는 구독할 수 있지만 `test/topic/filter`는 구독할 수 없습니다.  | 

### 로컬 섀도 권한 부여 정책의 레시피 변수
<a name="ipc-local-shadow-authorization-recipe-variables"></a>

[Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상을 사용하고 Greengrass nucleus의 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 구성 옵션을 `true`로 설정한 경우 권한 부여 정책에서 `{iot:thingName}` [레시피 변수](component-recipe-reference.md#recipe-variables)를 사용할 수 있습니다. 이 기능을 사용하면 코어 디바이스 그룹에 대해 단일 권한 부여 정책을 구성할 수 있고, 이 경우 각 코어 디바이스는 자체 섀도만 액세스할 수 있습니다. 예를 들어 섀도 IPC 작업을 위해 다음 리소스에 대한 구성 요소 액세스를 허용할 수 있습니다.

```
$aws/things/{iot:thingName}/shadow/
```

### 권한 부여 정책 예제
<a name="ipc-local-shadow-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 예: 코어 디바이스 그룹이 로컬 섀도와 연동하도록 허용**  
 <a name="phrase-example-uses-recipe-variables-in-configuration"></a>이 예제에서는 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있는 기능을 사용합니다. Greengrass nucleus v2.6.0에서는 구성 요소 구성에서 `{iot:thingName}`과 같은 대부분의 [레시피 변수](component-recipe-reference.md#recipe-variables)에 대한 지원을 추가합니다. 이 기능을 활성화하려면 Greengrass nucleus의 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 구성 옵션을 `true`로 설정합니다. Greengrass nucleus의 모든 버전에서 작동하는 예제는 [단일 코어 디바이스에 대한 예제 권한 부여 정책](#ipc-local-shadows-authorization-example-single-device)을 참조하세요.
다음 예제 권한 부여 정책에서는 구성 요소 `com.example.MyShadowInteractionComponent`가 구성 요소를 실행하는 코어 디바이스의 클래식 디바이스 섀도 및 이름 지정된 섀도 `myNamedShadow`와 연동할 수 있도록 허용합니다. 또한 이 정책에서는 이 구성 요소가 이러한 섀도의 로컬 주제에 대한 메시지를 수신하도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ShadowManager": {
      "com.example.MyShadowInteractionComponent:shadow:1": {
        "policyDescription": "Allows access to shadows",
        "operations": [
          "aws.greengrass#GetThingShadow",
          "aws.greengrass#UpdateThingShadow",
          "aws.greengrass#DeleteThingShadow"
        ],
        "resources": [
          "$aws/things/{iot:thingName}/shadow",
          "$aws/things/{iot:thingName}/shadow/name/myNamedShadow"
        ]
      },
      "com.example.MyShadowInteractionComponent:shadow:2": {
        "policyDescription": "Allows access to things with shadows",
        "operations": [
          "aws.greengrass#ListNamedShadowsForThing"
        ],
        "resources": [
          "{iot:thingName}"
        ]
      }    
    },
    "aws.greengrass.ipc.pubsub": {
      "com.example.MyShadowInteractionComponent:pubsub:1": {
        "policyDescription": "Allows access to shadow pubsub topics",
        "operations": [
          "aws.greengrass#SubscribeToTopic"
        ],
        "resources": [
          "$aws/things/{iot:thingName}/shadow/get/accepted",
          "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted"
        ]
      }
    }
  }
}
```

```
accessControl:
  aws.greengrass.ShadowManager:
    'com.example.MyShadowInteractionComponent:shadow:1':
      policyDescription: 'Allows access to shadows'
      operations:
        - 'aws.greengrass#GetThingShadow'
        - 'aws.greengrass#UpdateThingShadow'
        - 'aws.greengrass#DeleteThingShadow'
      resources:
        - $aws/things/{iot:thingName}/shadow
        - $aws/things/{iot:thingName}/shadow/name/myNamedShadow
    'com.example.MyShadowInteractionComponent:shadow:2':
      policyDescription: 'Allows access to things with shadows'
      operations:
        - 'aws.greengrass#ListNamedShadowsForThing'
      resources:
        - '{iot:thingName}'
  aws.greengrass.ipc.pubsub:
    'com.example.MyShadowInteractionComponent:pubsub:1':
      policyDescription: 'Allows access to shadow pubsub topics'
      operations:
        - 'aws.greengrass#SubscribeToTopic'
      resources:
        - $aws/things/{iot:thingName}/shadow/get/accepted
        - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted
```

**Example 예: 코어 디바이스 그룹이 클라이언트 디바이스 섀도와 연동하도록 허용**  
이 기능에는 [Greengrass nucleus](greengrass-nucleus-component.md) v2.6.0 이상, [섀도 관리자](shadow-manager-component.md) v2.2.0 이상 및 [MQTT 브리지](mqtt-bridge-component.md) v2.2.0 이상이 필요합니다. [섀도 관리자가 클라이언트 디바이스와 통신할 수 있도록](work-with-client-device-shadows.md#enable-shadow-manager-client-devices) MQTT 브리지를 구성해야 합니다.
다음 예제 권한 부여 정책에서는 구성 요소 `com.example.MyShadowInteractionComponent`가 이름이 `MyClientDevice`로 시작하는 클라이언트 디바이스의 모든 디바이스 섀도와 연동할 수 있도록 허용합니다.  
코어 디바이스가 클라이언트 디바이스 섀도와 연동할 수 있도록 하려면 MQTT 브리지 구성 요소도 구성하고 배포해야 합니다. 자세한 내용은 [섀도 관리자가 클라이언트 디바이스와 통신할 수 있도록 설정](work-with-client-device-shadows.md)을 참조하세요.

```
{
  "accessControl": {
    "aws.greengrass.ShadowManager": {
      "com.example.MyShadowInteractionComponent:shadow:1": {
        "policyDescription": "Allows access to shadows",
        "operations": [
          "aws.greengrass#GetThingShadow",
          "aws.greengrass#UpdateThingShadow",
          "aws.greengrass#DeleteThingShadow"
        ],
        "resources": [
          "$aws/things/MyClientDevice*/shadow",
          "$aws/things/MyClientDevice*/shadow/name/*"
        ]
      },
      "com.example.MyShadowInteractionComponent:shadow:2": {
        "policyDescription": "Allows access to things with shadows",
        "operations": [
          "aws.greengrass#ListNamedShadowsForThing"
        ],
        "resources": [
          "MyClientDevice*"
        ]
      }    
    }
  }
}
```

```
accessControl:
  aws.greengrass.ShadowManager:
    'com.example.MyShadowInteractionComponent:shadow:1':
      policyDescription: 'Allows access to shadows'
      operations:
        - 'aws.greengrass#GetThingShadow'
        - 'aws.greengrass#UpdateThingShadow'
        - 'aws.greengrass#DeleteThingShadow'
      resources:
        - $aws/things/MyClientDevice*/shadow
        - $aws/things/MyClientDevice*/shadow/name/*
    'com.example.MyShadowInteractionComponent:shadow:2':
      policyDescription: 'Allows access to things with shadows'
      operations:
        - 'aws.greengrass#ListNamedShadowsForThing'
      resources:
        - MyClientDevice*
```<a name="ipc-local-shadows-authorization-example-single-device"></a>

**Example 예: 단일 코어 디바이스가 로컬 섀도와 연동하도록 허용**  
다음 예제 권한 부여 정책에서는 구성 요소 `com.example.MyShadowInteractionComponent`가 디바이스 `MyThingName`의 클래식 디바이스 섀도 및 이름 지정된 섀도 `myNamedShadow`와 연동할 수 있도록 허용합니다. 또한 이 정책에서는 이 구성 요소가 이러한 섀도의 로컬 주제에 대한 메시지를 수신하도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ShadowManager": {
      "com.example.MyShadowInteractionComponent:shadow:1": {
        "policyDescription": "Allows access to shadows",
        "operations": [
          "aws.greengrass#GetThingShadow",
          "aws.greengrass#UpdateThingShadow",
          "aws.greengrass#DeleteThingShadow"
        ],
        "resources": [
          "$aws/things/MyThingName/shadow",
          "$aws/things/MyThingName/shadow/name/myNamedShadow"
        ]
      },
      "com.example.MyShadowInteractionComponent:shadow:2": {
        "policyDescription": "Allows access to things with shadows",
        "operations": [
          "aws.greengrass#ListNamedShadowsForThing"
        ],
        "resources": [
          "MyThingName"
        ]
      }    
    },
    "aws.greengrass.ipc.pubsub": {
      "com.example.MyShadowInteractionComponent:pubsub:1": {
        "policyDescription": "Allows access to shadow pubsub topics",
        "operations": [
          "aws.greengrass#SubscribeToTopic"
        ],
        "resources": [
          "$aws/things/MyThingName/shadow/get/accepted",
          "$aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted"
        ]
      }
    }
  }
}
```

```
accessControl:
  aws.greengrass.ShadowManager:
    'com.example.MyShadowInteractionComponent:shadow:1':
      policyDescription: 'Allows access to shadows'
      operations:
        - 'aws.greengrass#GetThingShadow'
        - 'aws.greengrass#UpdateThingShadow'
        - 'aws.greengrass#DeleteThingShadow'
      resources:
        - $aws/things/MyThingName/shadow
        - $aws/things/MyThingName/shadow/name/myNamedShadow
    'com.example.MyShadowInteractionComponent:shadow:2':
      policyDescription: 'Allows access to things with shadows'
      operations:
        - 'aws.greengrass#ListNamedShadowsForThing'
      resources:
        - MyThingName
  aws.greengrass.ipc.pubsub:
    'com.example.MyShadowInteractionComponent:pubsub:1':
      policyDescription: 'Allows access to shadow pubsub topics'
      operations:
        - 'aws.greengrass#SubscribeToTopic'
      resources:
        - $aws/things/MyThingName/shadow/get/accepted
        - $aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted
```<a name="interact-with-shadows-react-example-authorization-policies"></a>

**Example 예: 코어 디바이스 그룹이 로컬 섀도 상태 변경에 대응하도록 허용**  
 <a name="phrase-example-uses-recipe-variables-in-configuration"></a>이 예제에서는 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있는 기능을 사용합니다. Greengrass nucleus v2.6.0에서는 구성 요소 구성에서 `{iot:thingName}`과 같은 대부분의 [레시피 변수](component-recipe-reference.md#recipe-variables)에 대한 지원을 추가합니다. 이 기능을 활성화하려면 Greengrass nucleus의 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 구성 옵션을 `true`로 설정합니다. Greengrass nucleus의 모든 버전에서 작동하는 예제는 [단일 코어 디바이스에 대한 예제 권한 부여 정책](#interact-with-shadows-react-example-authorization-policy-single-device)을 참조하세요.
다음 예제 액세스 제어 정책에서는 구성 요소 `com.example.MyShadowReactiveComponent`가 구성 요소를 실행하는 각 코어 디바이스에서 클래식 디바이스 섀도 및 이름 지정된 섀도 `myNamedShadow`의 `/update/delta` 주제에 대한 메시지를 수신할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.pubsub": {
      "com.example.MyShadowReactiveComponent:pubsub:1": {
        "policyDescription": "Allows access to shadow pubsub topics",
        "operations": [
          "aws.greengrass#SubscribeToTopic"
        ],
        "resources": [
          "$aws/things/{iot:thingName}/shadow/update/delta",
          "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta"
        ]
      }
    }
  }
}
```

```
accessControl:
  aws.greengrass.ipc.pubsub:
    "com.example.MyShadowReactiveComponent:pubsub:1":
      policyDescription: Allows access to shadow pubsub topics
      operations:
        - 'aws.greengrass#SubscribeToTopic'
      resources:
        - $aws/things/{iot:thingName}/shadow/update/delta
        - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta
```<a name="interact-with-shadows-react-example-authorization-policy-single-device"></a>

**Example 예: 단일 코어 디바이스가 로컬 섀도 상태 변경에 대응하도록 허용**  
다음 예제 액세스 제어 정책에서는 구성 요소 `com.example.MyShadowReactiveComponent`가 디바이스 `MyThingName`의 클래식 디바이스 섀도 및 이름 지정된 섀도 `myNamedShadow`의 `/update/delta` 주제에 대한 메시지를 수신할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.ipc.pubsub": {
      "com.example.MyShadowReactiveComponent:pubsub:1": {
        "policyDescription": "Allows access to shadow pubsub topics",
        "operations": [
          "aws.greengrass#SubscribeToTopic"
        ],
        "resources": [
          "$aws/things/MyThingName/shadow/update/delta",
          "$aws/things/MyThingName/shadow/name/myNamedShadow/update/delta"
        ]
      }
    }
  }
}
```

```
accessControl:
  aws.greengrass.ipc.pubsub:
    "com.example.MyShadowReactiveComponent:pubsub:1":
      policyDescription: Allows access to shadow pubsub topics
      operations:
        - 'aws.greengrass#SubscribeToTopic'
      resources:
        - $aws/things/MyThingName/shadow/update/delta
        - $aws/things/MyThingName/shadow/name/myNamedShadow/update/delta
```

## GetThingShadow
<a name="ipc-operation-getthingshadow"></a>

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

### 요청
<a name="ipc-operation-getthingshadow-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`thingName`(Python: `thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
 사물의 이름입니다.  
유형: `string`

`shadowName`(Python: `shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
섀도의 이름입니다. 사물의 클래식 섀도를 지정하려면 이 파라미터를 빈 문자열(`""`)로 설정합니다.  
 AWS IoT Greengrass 서비스는 `AWSManagedGreengrassV2Deployment`명명된 섀도우를 사용하여 개별 코어 디바이스를 대상으로 하는 배포를 관리합니다. 이 명명된 섀도우는 AWS IoT Greengrass 서비스에서 사용하도록 예약되어 있습니다. 이 이름이 지정된 섀도를 업데이트하거나 삭제하지 마세요.
유형: `string`

### 응답
<a name="ipc-operation-getthingshadow-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`payload`  
Blob인 응답 상태 문서입니다.  
유형: 다음 정보를 포함하는 `object`입니다.    
`state`  
상태 정보입니다.  
이 객체에는 다음 정보가 포함됩니다.    
`desired`  
디바이스에서 업데이트하도록 요청된 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`reported`  
디바이스에서 보고한 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`delta`  
상태 속성 및 값의 원하는 상태와 보고된 상태 사이의 차이입니다. 이 속성은 `desired` 및 `reported` 상태가 다른 경우에만 있습니다.  
유형: 키-값 페어의 `map`  
`metadata`  
언제 상태가 업데이트되었는지 확인할 수 있는 `desired` 및 `reported` 섹션의 각 속성에 대한 타임스탬프입니다.  
유형: `string`  
`timestamp`  
응답이 생성된 epoch 날짜 및 시간입니다.  
유형: `integer`  
`clientToken`(Python: `clientToken`)  
요청과 해당 응답을 일치시키는 데 사용되는 토큰입니다.  
유형: `string`  
`version`  
로컬 섀도 문서의 버전입니다.  
유형: `integer`

### 오류
<a name="ipc-operation-getthingshadow-errors"></a>

이 작업은 다음 오류를 반환할 수 있습니다.

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>로컬 섀도 서비스에서 요청 파라미터를 검증할 수 없습니다. 요청에 잘못된 형식의 JSON 또는 지원되지 않는 문자가 포함된 경우 발생할 수 있습니다.

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
요청된 로컬 섀도 문서를 찾을 수 없습니다.

`ServiceError`  <a name="ipc-serviceerror"></a>
내부 서비스 오류가 발생했거나, IPC 서비스에 대한 요청 수가 섀도 관리자 구성 요소의 `maxLocalRequestsPerSecondPerThing` 및 `maxTotalLocalRequestsRate` 구성 파라미터에 지정된 제한을 초과했습니다.

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
구성 요소의 권한 부여 정책에 이 작업에 필요한 권한이 포함되어 있지 않습니다.

### 예제
<a name="ipc-operation-getthingshadow-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V1) ]

**Example 예: 사물 섀도 가져오기**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GetThingShadowResponseHandler;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.model.GetThingShadowRequest;
import software.amazon.awssdk.aws.greengrass.model.GetThingShadowResponse;
import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class GetThingShadow {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        // Use the current core device's name if thing name isn't set.
        String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0];
        String shadowName = args[1];
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            GetThingShadowResponseHandler responseHandler =
                    GetThingShadow.getThingShadow(ipcClient, thingName, shadowName);
            CompletableFuture<GetThingShadowResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                GetThingShadowResponse response = futureResponse.get(TIMEOUT_SECONDS,
                        TimeUnit.SECONDS);
                String shadowPayload = new String(response.getPayload(), StandardCharsets.UTF_8);
                System.out.printf("Successfully got shadow %s/%s: %s%n", thingName, shadowName,
                        shadowPayload);
            } catch (TimeoutException e) {
                System.err.printf("Timeout occurred while getting shadow: %s/%s%n", thingName,
                        shadowName);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.printf("Unauthorized error while getting shadow: %s/%s%n",
                            thingName, shadowName);
                } else if (e.getCause() instanceof ResourceNotFoundError) {
                    System.err.printf("Unable to find shadow to get: %s/%s%n", thingName,
                            shadowName);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static GetThingShadowResponseHandler getThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) {
        GetThingShadowRequest getThingShadowRequest = new GetThingShadowRequest();
        getThingShadowRequest.setThingName(thingName);
        getThingShadowRequest.setShadowName(shadowName);
        return greengrassCoreIPCClient.getThingShadow(getThingShadowRequest, Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 사물 섀도 가져오기**  

```
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import GetThingShadowRequest

TIMEOUT = 10

def sample_get_thing_shadow_request(thingName, shadowName):
    try:
        # set up IPC client to connect to the IPC server
        ipc_client = awsiot.greengrasscoreipc.connect()
                
        # create the GetThingShadow request
        get_thing_shadow_request = GetThingShadowRequest()
        get_thing_shadow_request.thing_name = thingName
        get_thing_shadow_request.shadow_name = shadowName
        
        # retrieve the GetThingShadow response after sending the request to the IPC server
        op = ipc_client.new_get_thing_shadow()
        op.activate(get_thing_shadow_request)
        fut = op.get_response()
        
        result = fut.result(TIMEOUT)
        return result.payload
        
    except InvalidArgumentsError as e:
        # add error handling
        ...
    # except ResourceNotFoundError | UnauthorizedError | ServiceError
```

------
#### [ JavaScript ]

**Example 예: 사물 섀도 가져오기**  

```
import {
    GetThingShadowRequest
} from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model';
import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc';

class GetThingShadow {
    private ipcClient: greengrasscoreipc.Client;
    private thingName: string;
    private shadowName: string;

    constructor() {
        // Define args parameters here           
        this.thingName = "<define_your_own_thingName>";
        this.shadowName = "<define_your_own_shadowName>";
        this.bootstrap();
    }

    async bootstrap() {
        try {
            this.ipcClient = await getIpcClient();
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
        
        try {
            await this.handleGetThingShadowOperation(this.thingName,
                this.shadowName);
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
    }

    async handleGetThingShadowOperation(
        thingName: string,
        shadowName: string
    ) {
        const request: GetThingShadowRequest = {
            thingName: thingName,
            shadowName: shadowName
        };
        const response = await this.ipcClient.getThingShadow(request);
    }
}

export async function getIpcClient() {
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use caseså
        throw err
    }
}

const startScript = new GetThingShadow();
```

------

## UpdateThingShadow
<a name="ipc-operation-updatethingshadow"></a>

지정된 사물의 섀도를 업데이트합니다. 섀도가 존재하지 않을 경우 섀도가 생성됩니다.

### 요청
<a name="ipc-operation-updatethingshadow-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`thingName`(Python: `thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
 사물의 이름입니다.  
유형: `string`

`shadowName`(Python: `shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
섀도의 이름입니다. 사물의 클래식 섀도를 지정하려면 이 파라미터를 빈 문자열(`""`)로 설정합니다.  
 AWS IoT Greengrass 서비스는 `AWSManagedGreengrassV2Deployment`명명된 섀도우를 사용하여 개별 코어 디바이스를 대상으로 하는 배포를 관리합니다. 이 명명된 섀도우는 AWS IoT Greengrass 서비스에서 사용하도록 예약되어 있습니다. 이 이름이 지정된 섀도를 업데이트하거나 삭제하지 마세요.
유형: `string`

`payload`  
Blob인 요청 상태 문서입니다.  
유형: 다음 정보를 포함하는 `object`입니다.    
`state`  
업데이트할 상태 정보입니다. 이 IPC 작업은 지정된 필드에만 영향을 미칩니다.  
이 객체에는 다음 정보가 포함됩니다. 일반적으로 `desired` 또는 `reported` 속성 중 하나를 사용하지만 동일한 요청에서는 둘 다 사용하지는 않습니다.    
`desired`  
디바이스에서 업데이트하도록 요청된 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`reported`  
디바이스에서 보고한 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`clientToken`(Python: `client_token`)  
(선택 사항) 클라이언트 토큰으로 요청과 해당 응답을 일치시키는 데 사용되는 토큰입니다.  
유형: `string`  
`version`  
(선택 사항) 업데이트할 로컬 섀도 문서의 버전입니다. 섀도 서비스에서는 지정된 버전이 서비스에서 보유하는 최신 버전과 일치하는 경우에만 업데이트를 처리합니다.  
유형: `integer`

### 응답
<a name="ipc-operation-updatethingshadow-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`payload`  
Blob인 응답 상태 문서입니다.  
유형: 다음 정보를 포함하는 `object`입니다.    
`state`  
상태 정보입니다.  
이 객체에는 다음 정보가 포함됩니다.    
`desired`  
디바이스에서 업데이트하도록 요청된 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`reported`  
디바이스에서 보고한 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`delta`  
디바이스에서 보고한 상태 속성 및 값입니다.  
유형: 키-값 페어의 `map`  
`metadata`  
언제 상태가 업데이트되었는지 확인할 수 있는 `desired` 및 `reported` 섹션의 각 속성에 대한 타임스탬프입니다.  
유형: `string`  
`timestamp`  
응답이 생성된 epoch 날짜 및 시간입니다.  
유형: `integer`  
`clientToken`(Python: `client_token`)  
요청과 해당 응답을 일치시키는 데 사용되는 토큰입니다.  
유형: `string`  
`version`  
업데이트가 완료된 후 로컬 섀도 문서의 버전입니다.  
유형: `integer`

### 오류
<a name="ipc-operation-updatethingshadow-errors"></a>

이 작업은 다음 오류를 반환할 수 있습니다.

`ConflictError`  
업데이트 작업 중에 로컬 섀도 서비스에서 버전 충돌이 발생했습니다. 요청 페이로드의 버전이 사용 가능한 최신 로컬 섀도 문서의 버전과 일치하지 않을 경우 발생합니다.

`InvalidArgumentsError`  
<a name="ipc-invalidargumentserror-para"></a>로컬 섀도 서비스에서 요청 파라미터를 검증할 수 없습니다. 요청에 잘못된 형식의 JSON 또는 지원되지 않는 문자가 포함된 경우 발생할 수 있습니다.  
유효한 `payload`의 속성은 다음과 같습니다.  
+ `state` 노드가 있고 `desired` 또는 `reported` 상태 정보를 포함하는 객체입니다.
+ `desired` 및 `reported` 노드는 객체 또는 null입니다. 이러한 객체 중 하나 이상에 유효한 상태 정보가 포함되어 있어야 합니다.
+ `desired` 및 `reported` 객체의 깊이는 8개 노드를 초과할 수 없습니다.
+ `clientToken` 값의 길이는 64자를 초과할 수 없습니다.
+  `version` 값은 `1` 이상이어야 합니다.

`ServiceError`  <a name="ipc-serviceerror"></a>
내부 서비스 오류가 발생했거나, IPC 서비스에 대한 요청 수가 섀도 관리자 구성 요소의 `maxLocalRequestsPerSecondPerThing` 및 `maxTotalLocalRequestsRate` 구성 파라미터에 지정된 제한을 초과했습니다.

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
구성 요소의 권한 부여 정책에 이 작업에 필요한 권한이 포함되어 있지 않습니다.

### 예제
<a name="ipc-operation-updatethingshadow-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V1) ]

**Example 예: 사물 섀도 업데이트**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.UpdateThingShadowResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowRequest;
import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowResponse;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class UpdateThingShadow {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        // Use the current core device's name if thing name isn't set.
        String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0];
        String shadowName = args[1];
        byte[] shadowPayload = args[2].getBytes(StandardCharsets.UTF_8);
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            UpdateThingShadowResponseHandler responseHandler =
                    UpdateThingShadow.updateThingShadow(ipcClient, thingName, shadowName,
                            shadowPayload);
            CompletableFuture<UpdateThingShadowResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                System.out.printf("Successfully updated shadow: %s/%s%n", thingName, shadowName);
            } catch (TimeoutException e) {
                System.err.printf("Timeout occurred while updating shadow: %s/%s%n", thingName,
                        shadowName);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.printf("Unauthorized error while updating shadow: %s/%s%n",
                            thingName, shadowName);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static UpdateThingShadowResponseHandler updateThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName, byte[] shadowPayload) {
        UpdateThingShadowRequest updateThingShadowRequest = new UpdateThingShadowRequest();
        updateThingShadowRequest.setThingName(thingName);
        updateThingShadowRequest.setShadowName(shadowName);
        updateThingShadowRequest.setPayload(shadowPayload);
        return greengrassCoreIPCClient.updateThingShadow(updateThingShadowRequest,
                Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 사물 섀도 업데이트**  

```
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import UpdateThingShadowRequest

TIMEOUT = 10

def sample_update_thing_shadow_request(thingName, shadowName, payload):
    try:
        # set up IPC client to connect to the IPC server
        ipc_client = awsiot.greengrasscoreipc.connect()
                
        # create the UpdateThingShadow request
        update_thing_shadow_request = UpdateThingShadowRequest()
        update_thing_shadow_request.thing_name = thingName
        update_thing_shadow_request.shadow_name = shadowName
        update_thing_shadow_request.payload = payload
                        
        # retrieve the UpdateThingShadow response after sending the request to the IPC server
        op = ipc_client.new_update_thing_shadow()
        op.activate(update_thing_shadow_request)
        fut = op.get_response()
        
        result = fut.result(TIMEOUT)
        return result.payload
        
    except InvalidArgumentsError as e:
        # add error handling
    ...
    # except ConflictError | UnauthorizedError | ServiceError
```

------
#### [ JavaScript ]

**Example 예: 사물 섀도 업데이트**  

```
import {
    UpdateThingShadowRequest
} from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model';
import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc';

class UpdateThingShadow {
    private ipcClient: greengrasscoreipc.Client;
    private thingName: string;
    private shadowName: string;
    private shadowDocumentStr: string;

    constructor() {
        // Define args parameters here

        this.thingName = "<define_your_own_thingName>";
        this.shadowName = "<define_your_own_shadowName>";
        this.shadowDocumentStr = "<define_your_own_payload>";

        this.bootstrap();
    }

    async bootstrap() {
        try {
            this.ipcClient = await getIpcClient();
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }

        try {
            await this.handleUpdateThingShadowOperation(
                this.thingName,
                this.shadowName,
                this.shadowDocumentStr);
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
    }

    async handleUpdateThingShadowOperation(
        thingName: string,
        shadowName: string,
        payloadStr: string
    ) {
        const request: UpdateThingShadowRequest = {
            thingName: thingName,
            shadowName: shadowName,
            payload: payloadStr
        }
        // make the UpdateThingShadow request
        const response = await this.ipcClient.updateThingShadow(request);
    }
}

export async function getIpcClient() {
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}

const startScript = new UpdateThingShadow();
```

------

## DeleteThingShadow
<a name="ipc-operation-deletethingshadow"></a>

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

섀도 관리자 v2.0.4부터 섀도를 삭제하면 버전 번호가 증가합니다. 예를 들어 버전 1에서 섀도 `MyThingShadow`를 삭제하면 삭제된 섀도의 버전은 2입니다. 그런 다음 이름이 `MyThingShadow`인 섀도를 다시 생성하면 해당 섀도의 버전은 3입니다.

### 요청
<a name="ipc-operation-deletethingshadow-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`thingName`(Python: `thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
 사물의 이름입니다.  
유형: `string`

`shadowName`(Python: `shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
섀도의 이름입니다. 사물의 클래식 섀도를 지정하려면 이 파라미터를 빈 문자열(`""`)로 설정합니다.  
 AWS IoT Greengrass 서비스는 `AWSManagedGreengrassV2Deployment`명명된 섀도우를 사용하여 개별 코어 디바이스를 대상으로 하는 배포를 관리합니다. 이 명명된 섀도우는 AWS IoT Greengrass 서비스에서 사용하도록 예약되어 있습니다. 이 이름이 지정된 섀도를 업데이트하거나 삭제하지 마세요.
유형: `string`

### 응답
<a name="ipc-operation-deletethingshadow-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`payload`  
빈 응답 상태 문서입니다.

### 오류
<a name="ipc-operation-deletethingshadow-errors"></a>

이 작업은 다음 오류를 반환할 수 있습니다.

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>로컬 섀도 서비스에서 요청 파라미터를 검증할 수 없습니다. 요청에 잘못된 형식의 JSON 또는 지원되지 않는 문자가 포함된 경우 발생할 수 있습니다.

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
요청된 로컬 섀도 문서를 찾을 수 없습니다.

`ServiceError`  <a name="ipc-serviceerror"></a>
내부 서비스 오류가 발생했거나, IPC 서비스에 대한 요청 수가 섀도 관리자 구성 요소의 `maxLocalRequestsPerSecondPerThing` 및 `maxTotalLocalRequestsRate` 구성 파라미터에 지정된 제한을 초과했습니다.

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
구성 요소의 권한 부여 정책에 이 작업에 필요한 권한이 포함되어 있지 않습니다.

### 예제
<a name="ipc-operation-deletethingshadow-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V1) ]

**Example 예: 사물 섀도 삭제**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.DeleteThingShadowResponseHandler;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowRequest;
import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowResponse;
import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class DeleteThingShadow {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        // Use the current core device's name if thing name isn't set.
        String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0];
        String shadowName = args[1];
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            DeleteThingShadowResponseHandler responseHandler =
                    DeleteThingShadow.deleteThingShadow(ipcClient, thingName, shadowName);
            CompletableFuture<DeleteThingShadowResponse> futureResponse =
                    responseHandler.getResponse();
            try {
                futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                System.out.printf("Successfully deleted shadow: %s/%s%n", thingName, shadowName);
            } catch (TimeoutException e) {
                System.err.printf("Timeout occurred while deleting shadow: %s/%s%n", thingName,
                        shadowName);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.printf("Unauthorized error while deleting shadow: %s/%s%n",
                            thingName, shadowName);
                } else if (e.getCause() instanceof ResourceNotFoundError) {
                    System.err.printf("Unable to find shadow to delete: %s/%s%n", thingName,
                            shadowName);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static DeleteThingShadowResponseHandler deleteThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) {
        DeleteThingShadowRequest deleteThingShadowRequest = new DeleteThingShadowRequest();
        deleteThingShadowRequest.setThingName(thingName);
        deleteThingShadowRequest.setShadowName(shadowName);
        return greengrassCoreIPCClient.deleteThingShadow(deleteThingShadowRequest,
                Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 사물 섀도 삭제**  

```
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import DeleteThingShadowRequest

TIMEOUT = 10

def sample_delete_thing_shadow_request(thingName, shadowName):
    try:
        # set up IPC client to connect to the IPC server
        ipc_client = awsiot.greengrasscoreipc.connect()
                
        # create the DeleteThingShadow request
        delete_thing_shadow_request = DeleteThingShadowRequest()
        delete_thing_shadow_request.thing_name = thingName
        delete_thing_shadow_request.shadow_name = shadowName
                        
        # retrieve the DeleteThingShadow response after sending the request to the IPC server
        op = ipc_client.new_delete_thing_shadow()
        op.activate(delete_thing_shadow_request)
        fut = op.get_response()
        
        result = fut.result(TIMEOUT)
        return result.payload
        
    except InvalidArgumentsError as e:
        # add error handling
    ...
    # except ResourceNotFoundError | UnauthorizedError | ServiceError
```

------
#### [ JavaScript ]

**Example 예: 사물 섀도 삭제**  

```
import {
    DeleteThingShadowRequest
} from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model';
import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc';

class DeleteThingShadow {
    private ipcClient: greengrasscoreipc.Client;
    private thingName: string;
    private shadowName: string;

    constructor() {
        // Define args parameters here
        this.thingName = "<define_your_own_thingName>";
        this.shadowName = "<define_your_own_shadowName>";
        this.bootstrap();
    }

    async bootstrap() {
        try {
            this.ipcClient = await getIpcClient();
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }

        try {
            await this.handleDeleteThingShadowOperation(this.thingName, this.shadowName)
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
    }

    async handleDeleteThingShadowOperation(thingName: string, shadowName: string) {
        const request: DeleteThingShadowRequest = {
            thingName: thingName,
            shadowName: shadowName
        }
        // make the DeleteThingShadow request
        const response = await this.ipcClient.deleteThingShadow(request);
    }
}

export async function getIpcClient() {
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}

const startScript = new DeleteThingShadow();
```

------

## ListNamedShadowsForThing
<a name="ipc-operation-listnamedshadowsforthing"></a>

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

### 요청
<a name="ipc-operation-listnamedshadowsforthing-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`thingName`(Python: `thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
 사물의 이름입니다.  
유형: `string`

`pageSize`(Python: `page_size`)  
(선택 사항) 각 호출에서 반환할 섀도 이름의 수입니다.  
유형: `integer`  
기본값: 25  
최대: 100

`nextToken`(Python: `next_token`)  
(선택 사항) 다음 결과 집합을 검색하기 위한 토큰입니다. 이 값은 페이징된 결과에서 반환되며 다음 페이지를 반환하는 호출에 사용됩니다.  
유형: `string`

### 응답
<a name="ipc-operation-listnamedshadowsforthing-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`results`  
섀도 이름 목록입니다.  
유형: `array`

`timestamp`  
(선택 사항) 응답이 생성된 날짜 및 시간입니다.  
유형: `integer`

`nextToken`(Python: `next_token`)  
(선택 사항) 시퀀스의 다음 페이지를 검색하기 위해 페이징된 요청에 사용할 토큰 값입니다. 반환할 섀도 이름이 더 이상 없는 경우에는 이 속성이 없습니다.  
유형: `string`  
요청된 페이지 크기가 응답의 섀도 이름 수와 정확히 일치하면 이 토큰이 있지만, 사용 시 빈 목록을 반환합니다.

### 오류
<a name="ipc-operation-listnamedshadowsforthing-errors"></a>

이 작업은 다음 오류를 반환할 수 있습니다.

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>로컬 섀도 서비스에서 요청 파라미터를 검증할 수 없습니다. 요청에 잘못된 형식의 JSON 또는 지원되지 않는 문자가 포함된 경우 발생할 수 있습니다.

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
요청된 로컬 섀도 문서를 찾을 수 없습니다.

`ServiceError`  <a name="ipc-serviceerror"></a>
내부 서비스 오류가 발생했거나, IPC 서비스에 대한 요청 수가 섀도 관리자 구성 요소의 `maxLocalRequestsPerSecondPerThing` 및 `maxTotalLocalRequestsRate` 구성 파라미터에 지정된 제한을 초과했습니다.

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
구성 요소의 권한 부여 정책에 이 작업에 필요한 권한이 포함되어 있지 않습니다.

### 예제
<a name="ipc-operation-listnamedshadowsforthing-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Java (IPC client V1) ]

**Example 예: 사물의 이름 지정된 섀도 나열**  
이 예제에서는 `IPCUtils` 클래스를 사용하여 AWS IoT Greengrass 코어 IPC 서비스에 대한 연결을 생성합니다. 자세한 내용은 [AWS IoT Greengrass 코어 IPC 서비스에 연결](interprocess-communication.md#ipc-service-connect) 단원을 참조하십시오.

```
package com.aws.greengrass.docs.samples.ipc;

import com.aws.greengrass.docs.samples.ipc.util.IPCUtils;
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient;
import software.amazon.awssdk.aws.greengrass.ListNamedShadowsForThingResponseHandler;
import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingRequest;
import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingResponse;
import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError;
import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError;
import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ListNamedShadowsForThing {

    public static final int TIMEOUT_SECONDS = 10;

    public static void main(String[] args) {
        // Use the current core device's name if thing name isn't set.
        String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0];
        try (EventStreamRPCConnection eventStreamRPCConnection =
                     IPCUtils.getEventStreamRpcConnection()) {
            GreengrassCoreIPCClient ipcClient =
                    new GreengrassCoreIPCClient(eventStreamRPCConnection);
            List<String> namedShadows = new ArrayList<>();
            String nextToken = null;
            try {
                // Send additional requests until there's no pagination token in the response.
                do {
                    ListNamedShadowsForThingResponseHandler responseHandler =
                            ListNamedShadowsForThing.listNamedShadowsForThing(ipcClient, thingName,
                                    nextToken, 25);
                    CompletableFuture<ListNamedShadowsForThingResponse> futureResponse =
                            responseHandler.getResponse();
                    ListNamedShadowsForThingResponse response =
                            futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                    List<String> responseNamedShadows = response.getResults();
                    namedShadows.addAll(responseNamedShadows);
                    nextToken = response.getNextToken();
                } while (nextToken != null);
                System.out.printf("Successfully got named shadows for thing %s: %s%n", thingName,
                        String.join(",", namedShadows));
            } catch (TimeoutException e) {
                System.err.println("Timeout occurred while listing named shadows for thing: " + thingName);
            } catch (ExecutionException e) {
                if (e.getCause() instanceof UnauthorizedError) {
                    System.err.println("Unauthorized error while listing named shadows for " +
                            "thing: " + thingName);
                } else if (e.getCause() instanceof ResourceNotFoundError) {
                    System.err.println("Unable to find thing to list named shadows: " + thingName);
                } else {
                    throw e;
                }
            }
        } catch (InterruptedException e) {
            System.out.println("IPC interrupted.");
        } catch (ExecutionException e) {
            System.err.println("Exception occurred when using IPC.");
            e.printStackTrace();
            System.exit(1);
        }
    }

    public static ListNamedShadowsForThingResponseHandler listNamedShadowsForThing(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String nextToken, int pageSize) {
        ListNamedShadowsForThingRequest listNamedShadowsForThingRequest =
                new ListNamedShadowsForThingRequest();
        listNamedShadowsForThingRequest.setThingName(thingName);
        listNamedShadowsForThingRequest.setNextToken(nextToken);
        listNamedShadowsForThingRequest.setPageSize(pageSize);
        return greengrassCoreIPCClient.listNamedShadowsForThing(listNamedShadowsForThingRequest,
                Optional.empty());
    }
}
```

------
#### [ Python (IPC client V1) ]

**Example 예: 사물의 이름 지정된 섀도 나열**  

```
import awsiot.greengrasscoreipc
import awsiot.greengrasscoreipc.client as client
from awsiot.greengrasscoreipc.model import ListNamedShadowsForThingRequest

TIMEOUT = 10

def sample_list_named_shadows_for_thing_request(thingName, nextToken, pageSize):
    try:
        # set up IPC client to connect to the IPC server
        ipc_client = awsiot.greengrasscoreipc.connect()
                
        # create the ListNamedShadowsForThingRequest request
        list_named_shadows_for_thing_request = ListNamedShadowsForThingRequest()
        list_named_shadows_for_thing_request.thing_name = thingName
        list_named_shadows_for_thing_request.next_token = nextToken
        list_named_shadows_for_thing_request.page_size = pageSize
        
        # retrieve the ListNamedShadowsForThingRequest response after sending the request to the IPC server
        op = ipc_client.new_list_named_shadows_for_thing()
        op.activate(list_named_shadows_for_thing_request)
        fut = op.get_response()
        
        list_result = fut.result(TIMEOUT)
        
        # additional returned fields
        timestamp = list_result.timestamp
        next_token = result.next_token
        named_shadow_list = list_result.results
        
        return named_shadow_list, next_token, timestamp
                
    except InvalidArgumentsError as e:
        # add error handling
    ...
    # except ResourceNotFoundError | UnauthorizedError | ServiceError
```

------
#### [ JavaScript ]

**Example 예: 사물의 이름 지정된 섀도 나열**  

```
import {
    ListNamedShadowsForThingRequest
} from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model';
import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc';

class listNamedShadowsForThing {
    private ipcClient: greengrasscoreipc.Client;
    private thingName: string;
    private pageSizeStr: string;
    private nextToken: string;

    constructor() {
        // Define args parameters here
        this.thingName = "<define_your_own_thingName>";
        this.pageSizeStr = "<define_your_own_pageSize>";
        this.nextToken = "<define_your_own_token>";
        this.bootstrap();
    }

    async bootstrap() {
        try {
            this.ipcClient = await getIpcClient();
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
        
        try {
            await this.handleListNamedShadowsForThingOperation(this.thingName,
                this.nextToken, this.pageSizeStr);
        } catch (err) {
            // parse the error depending on your use cases
            throw err
        }
    }

    async handleListNamedShadowsForThingOperation(
        thingName: string,
        nextToken: string,
        pageSizeStr: string
    ) {
        let request: ListNamedShadowsForThingRequest = {
            thingName: thingName,
            nextToken: nextToken,
        };
        if (pageSizeStr) {
            request.pageSize = parseInt(pageSizeStr);
        }
        // make the ListNamedShadowsForThing request
        const response = await this.ipcClient.listNamedShadowsForThing(request);
        const shadowNames = response.results;
    }
}

export async function getIpcClient(){
    try {
        const ipcClient = greengrasscoreipc.createClient();
        await ipcClient.connect()
            .catch(error => {
                // parse the error depending on your use cases
                throw error;
            });
        return ipcClient
    } catch (err) {
        // parse the error depending on your use cases
        throw err
    }
}

const startScript = new listNamedShadowsForThing();
```

------

# 로컬 배포 및 구성 요소 관리
<a name="ipc-local-deployments-components"></a>

**참고**  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다.

Greengrass CLI IPC 서비스를 사용하여 코어 디바이스에서 로컬 배포 및 Greengrass 구성 요소를 관리할 수 있습니다.

이러한 IPC 작업을 사용하려면 [Greengrass CLI 구성 요소](greengrass-cli-component.md) 버전 2.6.0 이상을 사용자 지정 구성 요소에 종속성으로 포함합니다. 그런 다음 사용자 지정 구성 요소에서 IPC 작업을 사용하여 다음을 수행할 수 있습니다.
+ 로컬 배포를 생성하여 코어 디바이스에서 Greengrass 구성 요소를 수정하고 구성합니다.
+ 코어 디바이스에서 Greengrass 구성 요소를 다시 시작하고 중지합니다.
+ [로컬 디버그 콘솔 ](local-debug-console-component.md)에 로그인하는 데 사용할 수 있는 암호를 생성합니다.

**Topics**
+ [최소 SDK 버전](#ipc-local-deployments-components-sdk-versions)
+ [권한 부여](#ipc-local-deployments-components-authorization)
+ [CreateLocalDeployment](#ipc-operation-createlocaldeployment)
+ [ListLocalDeployments](#ipc-operation-listlocaldeployments)
+ [GetLocalDeploymentStatus](#ipc-operation-getlocaldeploymentstatus)
+ [ListComponents](#ipc-operation-listcomponents)
+ [GetComponentDetails](#ipc-operation-getcomponentdetails)
+ [RestartComponent](#ipc-operation-restartcomponent)
+ [StopComponent](#ipc-operation-stopcomponent)
+ [CreateDebugPassword](#ipc-operation-createdebugpassword)

## 최소 SDK 버전
<a name="ipc-local-deployments-components-sdk-versions"></a>

다음 표에는 Greengrass CLI IPC 서비스와 상호 작용하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.2.10  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.5.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.17.0  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-local-deployments-components-authorization"></a>

사용자 지정 구성 요소에서 Greengrass CLI IPC 서비스를 사용하려면 구성 요소가 로컬 배포 및 구성 요소를 관리할 수 있도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

Greengrass CLI에 대한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.Cli`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#CreateLocalDeployment`  |  구성 요소가 코어 디바이스에서 로컬 배포를 생성할 수 있도록 허용합니다.  |  `*`  | 
|  `aws.greengrass#ListLocalDeployments`  |  구성 요소가 코어 디바이스의 로컬 배포를 나열할 수 있도록 허용합니다.  |  `*`  | 
|  `aws.greengrass#GetLocalDeploymentStatus`  |  구성 요소가 코어 디바이스에서 로컬 배포 상태를 가져올 수 있도록 허용합니다.  |  로컬 배포 ID 또는 모든 로컬 배포에 대한 액세스를 허용하려면 `*`입니다.  | 
|  `aws.greengrass#ListComponents`  |  구성 요소가 코어 디바이스의 구성 요소를 나열할 수 있도록 허용합니다.  |  `*`  | 
|  `aws.greengrass#GetComponentDetails`  |  구성 요소가 코어 디바이스의 구성 요소에 대한 세부 정보를 가져올 수 있도록 허용합니다.  |  구성 요소 이름(예: `com.example.HelloWorld`) 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`입니다.  | 
|  `aws.greengrass#RestartComponent`  |  구성 요소가 코어 디바이스에서 구성 요소를 다시 시작할 수 있도록 허용합니다.  |  구성 요소 이름(예: `com.example.HelloWorld`) 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`입니다.  | 
|  `aws.greengrass#StopComponent`  |  구성 요소가 코어 디바이스에서 구성 요소를 중지할 수 있도록 허용합니다.  |  구성 요소 이름(예: `com.example.HelloWorld`) 또는 모든 구성 요소에 대한 액세스를 허용하려면 `*`입니다.  | 
|  `aws.greengrass#CreateDebugPassword`  |  구성 요소가 [로컬 디버그 콘솔 구성 요소](local-debug-console-component.md)에 로그인하는 데 사용할 암호를 생성할 수 있도록 허용합니다.  |  `*`  | 

**Example 권한 부여 정책 예제**  
다음 권한 부여 정책 예제에서는 구성 요소가 로컬 배포를 생성하고, 모든 로컬 배포 및 구성 요소를 보고, `com.example.HelloWorld`라는 구성 요소를 다시 시작하고 중지할 수 있도록 허용합니다.  

```
{
  "accessControl": {
    "aws.greengrass.Cli": {
      "com.example.MyLocalManagerComponent:cli:1": {
        "policyDescription": "Allows access to create local deployments and view deployments and components.",
        "operations": [
          "aws.greengrass#CreateLocalDeployment",
          "aws.greengrass#ListLocalDeployments",
          "aws.greengrass#GetLocalDeploymentStatus",
          "aws.greengrass#ListComponents",
          "aws.greengrass#GetComponentDetails"
        ],
        "resources": [
          "*"
        ]
      }
    },
    "aws.greengrass.Cli": {
      "com.example.MyLocalManagerComponent:cli:2": {
        "policyDescription": "Allows access to restart and stop the Hello World component.",
        "operations": [
          "aws.greengrass#RestartComponent",
          "aws.greengrass#StopComponent"
        ],
        "resources": [
          "com.example.HelloWorld"
        ]
      }
    }
  }
}
```

## CreateLocalDeployment
<a name="ipc-operation-createlocaldeployment"></a>

지정된 구성 요소 레시피, 아티팩트 및 런타임 인수를 사용하여 로컬 배포를 생성하거나 업데이트합니다.

이 작업은 Greengrass CLI의 [deployment create 명령](gg-cli-deployment.md#deployment-create)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-createlocaldeployment-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`recipeDirectoryPath`(Python: `recipe_directory_path`)  
(선택 사항) 구성 요소 레시피 파일이 포함된 폴더의 절대 경로입니다.

`artifactDirectoryPath`(Python: `artifact_directory_path`)  
(선택 사항) 배포에 포함할 아티팩트 파일이 포함된 폴더의 절대 경로입니다. 아티팩트 폴더에는 다음 폴더 구조를 포함해야 합니다.  

```
/path/to/artifact/folder/component-name/component-version/artifacts
```

`rootComponentVersionsToAdd`(Python: `root_component_versions_to_add`)  
(선택 사항) 코어 디바이스에 설치할 구성 요소 버전입니다. 이 객체 `ComponentToVersionMap`는 다음 키-값 페어를 포함하는 맵입니다.    
`key`  
구성 요소의 이름입니다.  
`value`  
구성 요소의 버전입니다.

`rootComponentsToRemove`(Python: `root_components_to_remove`)  
(선택 사항) 코어 디바이스에서 제거할 구성 요소입니다. 각 항목이 구성 요소의 이름인 목록을 지정합니다.

`componentToConfiguration`(Python: `component_to_configuration`)  
(선택 사항) 배포의 각 구성 요소에 대한 구성 업데이트입니다. 이 객체 `ComponentToConfiguration`는 다음 키-값 페어를 포함하는 맵입니다.    
`key`  
구성 요소의 이름입니다.  
`value`  
구성 요소에 대한 구성 업데이트 JSON 객체입니다. JSON 객체는 다음 형식이어야 합니다.  

```
{ 
  "MERGE": {
    "config-key": "config-value"
  },
  "RESET": [
    "path/to/reset/"
  ]
}
```
구성 업데이트에 대한 자세한 내용은 [구성 요소 구성 업데이트](update-component-configurations.md) 섹션을 참조하세요.

`componentToRunWithInfo`(Python: `component_to_run_with_info`)  
(선택 사항) 배포의 각 구성 요소에 대한 런타임 구성입니다. 이 구성에는 각 구성 요소의 프로세스를 소유하는 시스템 사용자와 각 구성 요소에 적용할 시스템 제한이 포함됩니다. 이 객체 `ComponentToRunWithInfo`는 다음 키-값 페어를 포함하는 맵입니다.    
`key`  
구성 요소의 이름입니다.  
`value`  
구성 요소의 런타임 구성입니다. 런타임 구성 파라미터를 생략하면 AWS IoT Greengrass 코어 소프트웨어는 [Greengrass nucleus](greengrass-nucleus-component.md)에서 구성하는 기본값을 사용합니다. 이 객체 `RunWithInfo`에는 다음 정보가 포함됩니다.    
`posixUser`(Python: `posix_user`)  
(선택 사항) <a name="deployment-posix-user-definition"></a>Linux 코어 디바이스에서 이 구성 요소를 실행하는 데 사용할 POSIX 시스템 사용자와 그룹(선택 사항)입니다. 사용자와 그룹(지정된 경우)이 각 Linux 코어 디바이스에 있어야 합니다. `user:group` 형식으로 사용자와 그룹을 콜론(`:`)으로 구분하여 지정합니다. 그룹은 선택 사항입니다. 그룹을 지정하지 않으면 AWS IoT Greengrass 코어 소프트웨어는 사용자의 기본 그룹을 사용합니다. 자세한 내용은 단원을 참조하십시오[구성 요소를 실행하는 사용자 구성](configure-greengrass-core-v2.md#configure-component-user).  
`windowsUser`(Python: `windows_user`)  
(선택 사항) <a name="deployment-windows-user-definition"></a>Windows 코어 디바이스에서 이 구성 요소를 실행하는 데 사용할 Windows 사용자입니다. 사용자가 각 Windows 코어 디바이스에 있어야 하며, 해당 이름과 암호가 LocalSystem 계정의 Credentials Manager 인스턴스에 저장되어야 합니다. 자세한 내용은 [구성 요소를 실행하는 사용자 구성](configure-greengrass-core-v2.md#configure-component-user) 섹션을 참조하세요.  
`systemResourceLimits`(Python: `system_resource_limits`)  
(선택 사항) <a name="deployment-system-resource-limits-definition"></a>이 구성 요소의 프로세스에 적용할 시스템 리소스 제한입니다. 기본적으로 일반 및 컨테이너화되지 않은 Lambda 구성 요소에 시스템 리소스 제한을 적용할 수 있습니다. 자세한 내용은 단원을 참조하십시오[구성 요소에 대한 시스템 리소스 제한 구성](configure-greengrass-core-v2.md#configure-component-system-resource-limits).  
AWS IoT Greengrass 는 현재 Windows 코어 디바이스에서이 기능을 지원하지 않습니다.  
이 객체 `SystemResourceLimits`에는 다음 정보가 포함됩니다.    
`cpus`  
(선택 사항) <a name="system-resource-limits-cpu-definition-this"></a>이 구성 요소의 프로세스가 코어 디바이스에서 사용할 수 있는 최대 CPU 시간입니다. 코어 디바이스의 총 CPU 시간은 디바이스의 CPU 코어 수와 같습니다. 예를 들어 CPU 코어가 4개인 코어 디바이스에서 이 값을 `2`로 설정하여 이 구성 요소 프로세스를 각 CPU 코어의 50% 사용량으로 제한할 수 있습니다. CPU 코어가 1개인 디바이스에서 이 값을 `0.25`로 설정하여 이 구성 요소 프로세스를 CPU의 25% 사용량으로 제한할 수 있습니다. 이 값을 CPU 코어 수보다 큰 수로 설정하면 AWS IoT Greengrass 코어 소프트웨어가 구성 요소의 CPU 사용량을 제한하지 않습니다.  
`memory`  
(선택 사항) <a name="system-resource-limits-memory-definition-this"></a>이 구성 요소의 프로세스가 코어 디바이스에서 사용할 수 있는 최대 RAM(KB 단위)입니다.

`groupName`(Python: `group_name`)  
(선택 사항) 이 배포에서 대상으로 지정할 사물 그룹의 이름입니다.

### 응답
<a name="ipc-operation-createlocaldeployment-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`deploymentId`(Python: `deployment_id`)  
요청이 생성한 로컬 배포의 ID입니다.

## ListLocalDeployments
<a name="ipc-operation-listlocaldeployments"></a>

마지막 10개 로컬 배포의 상태를 가져옵니다.

이 작업은 Greengrass CLI의 [deployment list 명령](gg-cli-deployment.md#deployment-list)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-listlocaldeployments-request"></a>

이 작업의 요청에는 파라미터가 없습니다.

### 응답
<a name="ipc-operation-listlocaldeployments-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`localDeployments`(Python: `local_deployments`)  
로컬 배포 목록입니다. 이 목록의 각 객체는 `LocalDeployment` 객체이며, 여기에는 다음 정보가 포함됩니다.  <a name="ipc-local-deployment-object-shape"></a>  
`deploymentId`(Python: `deployment_id`)  
로컬 배포의 ID입니다.  
`status`  
로컬 배포의 상태입니다. 이 열거형 `DeploymentStatus`의 값은 다음과 같습니다.  
+ `QUEUED`
+ `IN_PROGRESS`
+ `SUCCEEDED`
+ `FAILED`

## GetLocalDeploymentStatus
<a name="ipc-operation-getlocaldeploymentstatus"></a>

로컬 배포의 상태를 가져옵니다.

이 작업은 Greengrass CLI의 [deployment status 명령](gg-cli-deployment.md#deployment-status)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-getlocaldeploymentstatus-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`deploymentId`(Python: `deployment_id`)  
가져올 로컬 배포의 ID입니다.

### 응답
<a name="ipc-operation-getlocaldeploymentstatus-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`deployment`  
로컬 배포입니다. 이 객체 `LocalDeployment`에는 다음 정보가 포함됩니다.  <a name="ipc-local-deployment-object-shape"></a>  
`deploymentId`(Python: `deployment_id`)  
로컬 배포의 ID입니다.  
`status`  
로컬 배포의 상태입니다. 이 열거형 `DeploymentStatus`의 값은 다음과 같습니다.  
+ `QUEUED`
+ `IN_PROGRESS`
+ `SUCCEEDED`
+ `FAILED`

## ListComponents
<a name="ipc-operation-listcomponents"></a>

코어 디바이스에서 각 루트 구성 요소의 이름, 버전, 상태 및 구성을 가져옵니다. *루트 구성 요소*는 배포에서 지정하는 구성 요소입니다. 이 응답에는 다른 구성 요소의 종속성으로 설치된 구성 요소는 포함되지 않습니다.

이 작업은 Greengrass CLI의 [component list 명령](gg-cli-component.md#component-list)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-listcomponents-request"></a>

이 작업의 요청에는 파라미터가 없습니다.

### 응답
<a name="ipc-operation-listcomponents-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`components`  
코어 디바이스의 루트 구성 요소 목록입니다. 이 목록의 각 객체는 `ComponentDetails` 객체이며, 여기에는 다음 정보가 포함됩니다.  <a name="ipc-component-details-object-shape"></a>  
`componentName`(Python: `component_name`)  
구성 요소의 이름입니다.  
`version`  
구성 요소의 버전입니다.  
`state`  
구성 요소의 상태입니다. 이 상태는 다음 중 하나일 수 있습니다.  
+ `BROKEN`
+ `ERRORED`
+ `FINISHED`
+ `INSTALLED`
+ `NEW`
+ `RUNNING`
+ `STARTING`
+ `STOPPING`  
`configuration`  
JSON 객체인 구성 요소의 구성입니다.

## GetComponentDetails
<a name="ipc-operation-getcomponentdetails"></a>

코어 디바이스에서 구성 요소의 버전, 상태 및 구성을 가져옵니다.

이 작업은 Greengrass CLI의 [component details 명령](gg-cli-component.md#component-details)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-getcomponentdetails-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  
가져올 구성 요소의 이름입니다.

### 응답
<a name="ipc-operation-getcomponentdetails-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`componentDetails`(Python: `component_details`)  
구성 요소의 세부 정보입니다. 이 객체 `ComponentDetails`에는 다음 정보가 포함됩니다.  <a name="ipc-component-details-object-shape"></a>  
`componentName`(Python: `component_name`)  
구성 요소의 이름입니다.  
`version`  
구성 요소의 버전입니다.  
`state`  
구성 요소의 상태입니다. 이 상태는 다음 중 하나일 수 있습니다.  
+ `BROKEN`
+ `ERRORED`
+ `FINISHED`
+ `INSTALLED`
+ `NEW`
+ `RUNNING`
+ `STARTING`
+ `STOPPING`  
`configuration`  
JSON 객체인 구성 요소의 구성입니다.

## RestartComponent
<a name="ipc-operation-restartcomponent"></a>

코어 디바이스에서 구성 요소를 다시 시작합니다.

**참고**  
어느 구성 요소든 다시 시작할 수 있지만 [일반 구성 요소](develop-greengrass-components.md#component-types)만 다시 시작하는 것이 좋습니다.

이 작업은 Greengrass CLI의 [component restart 명령](gg-cli-component.md#component-restart)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-restartcomponent-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  
구성 요소의 이름입니다.

### 응답
<a name="ipc-operation-restartcomponent-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`restartStatus`(Python: `restart_status`)  
다시 시작 요청의 상태입니다. 요청 상태는 다음 중 하나일 수 있습니다.  
+ `SUCCEEDED`
+ `FAILED`

`message`  
요청이 실패한 경우 구성 요소를 다시 시작하지 못한 이유에 대한 메시지입니다.

### 예제
<a name="ipc-operation-restartcomponent-examples"></a>

다음 예제에서는 사용자 지정 구성 요소 코드에서 이 작업을 직접 호출하는 방법을 보여줍니다.

------
#### [ Rust ]

**Example 예: 구성 요소 다시 시작**  

```
use gg_sdk::Sdk;

fn main() {
    let sdk = Sdk::init();
    sdk.connect().expect("Failed to establish IPC connection");

    let component_name = "com.example.HelloWorld";

    sdk.restart_component(component_name)
        .expect("Failed to restart component");

    println!("Successfully requested restart for component: {component_name}");
}
```

------
#### [ C ]

**Example 예: 구성 요소 다시 시작**  

```
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/sdk.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    gg_sdk_init();

    GgError err = ggipc_connect();
    if (err != GG_ERR_OK) {
        fprintf(stderr, "Failed to establish IPC connection.\n");
        exit(-1);
    }

    GgBuffer component_name = GG_STR("com.example.HelloWorld");

    err = ggipc_restart_component(component_name);
    if (err != GG_ERR_OK) {
        fprintf(
            stderr,
            "Failed to restart component: %.*s\n",
            (int) component_name.len,
            component_name.data
        );
        exit(-1);
    }

    printf(
        "Successfully requested restart for component: %.*s\n",
        (int) component_name.len,
        component_name.data
    );
}
```

------
#### [ C\$1\$1 (Component SDK) ]

**Example 예: 구성 요소 다시 시작**  

```
#include <gg/ipc/client.hpp>
#include <iostream>

int main() {
    auto &client = gg::ipc::Client::get();

    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to establish IPC connection.\n";
        exit(-1);
    }

    std::string_view component_name = "com.example.HelloWorld";

    error = client.restart_component(component_name);
    if (error) {
        std::cerr << "Failed to restart component: " << component_name << "\n";
        exit(-1);
    }

    std::cout << "Successfully requested restart for component: "
              << component_name << "\n";
}
```

------

## StopComponent
<a name="ipc-operation-stopcomponent"></a>

코어 디바이스에서 구성 요소의 프로세스를 중지합니다.

**참고**  
어느 구성 요소든 중지할 수 있지만 [일반 구성 요소](develop-greengrass-components.md#component-types)만 중지하는 것이 좋습니다.

이 작업은 Greengrass CLI의 [component stop 명령](gg-cli-component.md#component-stop)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-stopcomponent-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`componentName`(Python: `component_name`)  
구성 요소의 이름입니다.

### 응답
<a name="ipc-operation-stopcomponent-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`stopStatus`(Python: `stop_status`)  
중지 요청의 상태입니다. 요청 상태는 다음 중 하나일 수 있습니다.  
+ `SUCCEEDED`
+ `FAILED`

`message`  
요청이 실패한 경우 구성 요소를 중지하지 못한 이유에 대한 메시지입니다.

## CreateDebugPassword
<a name="ipc-operation-createdebugpassword"></a>

[로컬 디버그 콘솔 구성 요소](local-debug-console-component.md)에 로그인하는 데 사용할 수 있는 임의 암호를 생성합니다. 암호는 생성되고 8시간 후에 만료됩니다.

이 작업은 Greengrass CLI의 [get-debug-password 명령](gg-cli-get-debug-password.md)과 동일한 기능을 제공합니다.

### 요청
<a name="ipc-operation-createdebugpassword-request"></a>

이 작업의 요청에는 파라미터가 없습니다.

### 응답
<a name="ipc-operation-createdebugpassword-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`username`  
로그인에 사용할 사용자 이름입니다.

`password`  
로그인에 사용할 암호입니다.

`passwordExpiration`(Python: `password_expiration`)  
암호가 만료되는 시간입니다.

`certificateSHA256Hash`(Python: `certificate_sha256_hash`)  
HTTPS가 활성화된 경우 로컬 디버그 콘솔에서 사용하는 자체 서명된 인증서의 SHA-256 지문입니다. 로컬 디버그 콘솔을 열 때 이 지문을 사용하여 인증서가 합법적이고 연결이 안전한지 확인합니다.

`certificateSHA1Hash`(Python: `certificate_sha1_hash`)  
HTTPS가 활성화된 경우 로컬 디버그 콘솔에서 사용하는 자체 서명된 인증서의 SHA-1 지문입니다. 로컬 디버그 콘솔을 열 때 이 지문을 사용하여 인증서가 합법적이고 연결이 안전한지 확인합니다.

# 클라이언트 디바이스 인증 및 권한 부여
<a name="ipc-client-device-auth"></a>

**참고**  
이 기능은 [Greengrass nucleus 구성 요소](greengrass-nucleus-component.md)의 v2.6.0 이상에서 사용할 수 있습니다.

클라이언트 디바이스 인증 IPC 서비스를 사용하여 클라이언트 디바이스와 같은 로컬 IoT 디바이스가 연결할 수 있는 사용자 지정 로컬 브로커 구성 요소를 개발할 수 있습니다.

이러한 IPC 작업을 사용하려면 사용자 지정 구성 요소에서 [클라이언트 디바이스 인증 구성 요소](client-device-auth-component.md) 버전 2.2.0 이상을 종속성으로 포함합니다. 그런 다음 사용자 지정 구성 요소에서 IPC 작업을 사용하여 다음을 수행할 수 있습니다.
+ 코어 디바이스에 연결하는 클라이언트 디바이스의 ID를 확인합니다.
+ 클라이언트 디바이스가 코어 디바이스에 연결할 세션을 생성합니다.
+ 클라이언트 디바이스에 작업을 수행할 권한이 있는지 확인합니다.
+ 코어 디바이스의 서버 인증서가 교체되면 알림을 받습니다.

**Topics**
+ [최소 SDK 버전](#ipc-client-device-auth-sdk-versions)
+ [권한 부여](#ipc-client-device-auth-authorization)
+ [VerifyClientDeviceIdentity](#ipc-operation-verifyclientdeviceidentity)
+ [GetClientDeviceAuthToken](#ipc-operation-getclientdeviceauthtoken)
+ [AuthorizeClientDeviceAction](#ipc-operation-authorizeclientdeviceaction)
+ [SubscribeToCertificateUpdates](#ipc-operation-subscribetocertificateupdates)

## 최소 SDK 버전
<a name="ipc-client-device-auth-sdk-versions"></a>

다음 표에는 클라이언트 디바이스 인증 IPC 서비스와 상호 작용하는 데 사용해야 AWS IoT Device SDK 하는의 최소 버전이 나열되어 있습니다.


| SDK | 최소 버전 | 
| --- | --- | 
|  [AWS IoT Device SDK Java v2용](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  v1.9.3  | 
|  [AWS IoT Device SDK Python v2용](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.11.3  | 
|  [AWS IoT Device SDK C\$1\$1 v2용](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  v1.18.3  | 
|  [AWS IoT Device SDK JavaScript v2용](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## 권한 부여
<a name="ipc-client-device-auth-authorization"></a>

사용자 지정 구성 요소에서 클라이언트 디바이스 인증 IPC 서비스를 사용하려면 구성 요소가 이러한 작업을 수행하도록 허용하는 권한 부여 정책을 정의해야 합니다. 권한 부여 정책 정의에 대한 자세한 내용은 [구성 요소에 IPC 작업을 수행할 수 있는 권한 부여](interprocess-communication.md#ipc-authorization-policies) 섹션을 참조하세요.

클라이언트 디바이스 인증 및 권한 부여에 대한 권한 부여 정책에는 다음 속성이 있습니다.

**IPC 서비스 식별자:** `aws.greengrass.clientdevices.Auth`


| 연산 | 설명 | 리소스 | 
| --- | --- | --- | 
|  `aws.greengrass#VerifyClientDeviceIdentity`  |  구성 요소가 클라이언트 디바이스의 ID를 확인할 수 있도록 합니다.  |  `*`  | 
|  `aws.greengrass#GetClientDeviceAuthToken`  |  구성 요소가 클라이언트 디바이스의 자격 증명을 검증하고 해당 클라이언트 디바이스에 대한 세션을 생성할 수 있도록 합니다.  |  `*`  | 
|  `aws.greengrass#AuthorizeClientDeviceAction`  |  구성 요소가 클라이언트 디바이스에 작업을 수행할 수 있는 권한이 있는지 확인할 수 있도록 합니다.  |  `*`  | 
|  `aws.greengrass#SubscribeToCertificateUpdates`  |  코어 디바이스의 서버 인증서가 교체될 때 구성 요소가 알림을 받을 수 있도록 합니다.  |  `*`  | 
|  `*`  |  구성 요소가 모든 클라이언트 디바이스 인증 IPC 서비스 작업을 수행할 수 있도록 합니다.  |  `*`  | 

### 권한 부여 정책 예제
<a name="ipc-client-device-auth-authorization-policy-examples"></a>

다음 권한 부여 정책 예제를 참조하면 구성 요소의 권한 부여 정책을 구성하는 데 도움이 됩니다.

**Example 권한 부여 정책 예제**  
다음 예제 권한 부여 정책에서는 구성 요소가 모든 클라이언트 디바이스 인증 IPC 작업을 수행할 수 있도록 합니다.  

```
{
  "accessControl": {
    "aws.greengrass.clientdevices.Auth": {
      "com.example.MyLocalBrokerComponent:clientdevices:1": {
        "policyDescription": "Allows access to authenticate and authorize client devices.",
        "operations": [
          "aws.greengrass#VerifyClientDeviceIdentity",
          "aws.greengrass#GetClientDeviceAuthToken",
          "aws.greengrass#AuthorizeClientDeviceAction",
          "aws.greengrass#SubscribeToCertificateUpdates"
        ],
        "resources": [
          "*"
        ]
      }
    }
  }
}
```

## VerifyClientDeviceIdentity
<a name="ipc-operation-verifyclientdeviceidentity"></a>

클라이언트 디바이스의 ID를 확인합니다. 이 작업은 클라이언트 디바이스가 유효한 AWS IoT 사물인지 확인합니다.

### 요청
<a name="ipc-operation-verifyclientdeviceidentity-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`credential`  
클라이언트 디바이스의 자격 증명입니다. 이 객체 `ClientDeviceCredential`에는 다음 정보가 포함됩니다.    
`clientDeviceCertificate`(Python: `client_device_certificate`)  
클라이언트 디바이스의 X.509 디바이스 인증서입니다.

### 응답
<a name="ipc-operation-verifyclientdeviceidentity-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`isValidClientDevice`(Python: `is_valid_client_device`)  
클라이언트 디바이스의 ID가 유효한지 여부입니다.

## GetClientDeviceAuthToken
<a name="ipc-operation-getclientdeviceauthtoken"></a>

클라이언트 디바이스의 자격 증명을 검증하고 클라이언트 디바이스에 대한 세션을 생성합니다. 이 작업은 이후 [클라이언트 디바이스 작업에 권한을 부여](#ipc-operation-authorizeclientdeviceaction)하는 요청에서 사용할 수 있는 세션 토큰을 반환합니다.

클라이언트 디바이스를 연결하려면 [클라이언트 디바이스 인증 구성 요소](client-device-auth-component.md#client-device-auth-component-configuration)에서 클라이언트 디바이스가 사용하는 클라이언트 ID에 대한 `mqtt:connect` 권한을 부여해야 합니다.

### 요청
<a name="ipc-operation-getclientdeviceauthtoken-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`credential`  
클라이언트 디바이스의 자격 증명입니다. 이 객체 `CredentialDocument`에는 다음 정보가 포함됩니다.    
`mqttCredential`(Python: `mqtt_credential`)  
클라이언트 디바이스의 MQTT 자격 증명입니다. 클라이언트 디바이스가 연결에 사용하는 클라이언트 ID 및 인증서를 지정합니다. 이 객체 `MQTTCredential`에는 다음 정보가 포함됩니다.    
`clientId`(Python: `client_id`)  
연결하는 데 사용할 Client ID입니다.  
`certificatePem`(Python: `certificate_pem`)  
연결하는 데 사용할 X.509 디바이스 인증서입니다.  
`username`  
이 속성은 현재 사용되지 않습니다.  
`password`  
이 속성은 현재 사용되지 않습니다.

### 응답
<a name="ipc-operation-getclientdeviceauthtoken-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`clientDeviceAuthToken`(Python: `client_device_auth_token`)  
클라이언트 디바이스의 세션 토큰입니다. 이후 이 클라이언트 디바이스의 작업에 권한을 부여하는 요청에서 이 세션 토큰을 사용할 수 있습니다.

## AuthorizeClientDeviceAction
<a name="ipc-operation-authorizeclientdeviceaction"></a>

클라이언트 디바이스가 리소스에서 작업을 수행할 권한이 있는지 확인합니다. *클라이언트 디바이스 권한 부여 정책*은 클라이언트 디바이스가 코어 디바이스에 연결되는 동안 수행할 수 있는 권한을 지정합니다. [클라이언트 디바이스 인증 구성 요소](client-device-auth-component.md#client-device-auth-component-configuration)를 구성할 때 클라이언트 디바이스 권한 부여 정책을 정의합니다.

### 요청
<a name="ipc-operation-authorizeclientdeviceaction-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`clientDeviceAuthToken`(Python: `client_device_auth_token`)  
클라이언트 디바이스의 세션 토큰입니다.

`operation`  
권한을 부여할 작업입니다.

`resource`  
클라이언트 디바이스가 작업을 수행하는 리소스입니다.

### 응답
<a name="ipc-operation-authorizeclientdeviceaction-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`isAuthorized`(Python: `is_authorized`)  
클라이언트 디바이스가 리소스에서 작업을 수행할 수 있는 권한이 있는지 여부입니다.

## SubscribeToCertificateUpdates
<a name="ipc-operation-subscribetocertificateupdates"></a>

코어 디바이스가 교체될 때마다 코어 디바이스의 새 서버 인증서를 수신하도록 구독합니다. 서버 인증서가 교체되면 새 서버 인증서를 사용하여 브로커를 다시 로드해야 합니다.

[클라이언트 디바이스 인증 구성 요소](client-device-auth-component.md)는 기본적으로 7일마다 서버 인증서를 교체합니다. 교체 간격을 2\$110일로 구성할 수 있습니다.

<a name="ipc-subscribe-operation-note"></a>이 작업은 이벤트 메시지 스트림을 구독하는 구독 작업입니다. 이 작업을 사용하려면 이벤트 메시지, 오류 및 스트림 종료를 처리하는 함수를 사용하여 스트림 응답 핸들러를 정의합니다. 자세한 내용은 [IPC 이벤트 스트림 구독](interprocess-communication.md#ipc-subscribe-operations) 단원을 참조하십시오.

**이벤트 메시지 유형:** `CertificateUpdateEvent`

### 요청
<a name="ipc-operation-subscribetocertificateupdates-request"></a>

이 작업의 요청에서는 다음 파라미터를 사용합니다.

`certificateOptions`(Python: `certificate_options`)  
구독할 인증서 업데이트의 유형입니다. 이 객체 `CertificateOptions`에는 다음 정보가 포함됩니다.    
`certificateType`(Python: `certificate_type`)  
구독할 인증서 업데이트의 유형입니다. 다음 옵션을 선택합니다.  
+ `SERVER`

### 응답
<a name="ipc-operation-subscribetocertificateupdates-response"></a>

이 작업의 응답에는 다음 정보가 포함됩니다.

`messages`  
메시지 스트림입니다. 이 객체 `CertificateUpdateEvent`에는 다음 정보가 포함됩니다.    
`certificateUpdate`(Python: `certificate_update`)  
새 인증서에 대한 정보입니다. 이 객체 `CertificateUpdate`에는 다음 정보가 포함됩니다.    
`certificate`  
인증서입니다.  
`privateKey`(Python: `private_key`)  
인증서의 프라이빗 키입니다.  
`publicKey`(Python: `public_key`)  
인증서의 퍼블릭 키입니다.  
`caCertificates`(Python: `ca_certificates`)  
인증서의 CA 인증서 체인에 있는 CA(인증 기관) 인증서 목록입니다.