AWS IoT
개발자 안내서

프로토콜

메시지 브로커는 MQTT 프로토콜을 사용한 게시 및 구독과 HTTPS 프로토콜을 사용한 게시를 지원합니다. 두 프로토콜은 모두 IP 버전 4 및 IP 버전 6을 통해 지원됩니다. 또한 메시지 브로커는 MQTT over WebSocket 프로토콜도 지원합니다.

프로토콜/포트 매핑

다음 표에는 AWS IoT에서 지원하는 각 프로토콜과 각 프로토콜에서 사용되는 인증 방법 및 포트가 나와 있습니다.

프로토콜, 인증 및 포트 매핑

프로토콜 인증 포트

MQTT

클라이언트 인증서

8883, 443

HTTP

클라이언트 인증서

8443

HTTP

SigV4

443

MQTT + WebSocket

SigV4

443

포트 443에서 MQTT(X.509 클라이언트 인증서 인증)를 사용하여 연결하려는 클라이언트는 ALPN(Application Layer Protocol Negotiation) TLS 확장을 구현하고 x-amzn-mqtt-ca을(를) ProtocolNameList의 ProtocolName으로 전달해야 합니다. 포트 8883을 통해 MQTT(X.509 클라이언트 인증서 인증)를 사용하여 연결하는 데는 ALPN이 필요하지 않습니다.

MQTT

MQTT는 제약된 디바이스용으로 설계된 경량 메시징 프로토콜로서 광범위하게 사용되고 있습니다. 자세한 내용은 MQTT를 참조하십시오.

AWS IoT 메시지 브로커 구현이 MQTT 버전 3.1.1을 기반으로 하지만 다음과 같이 사양이 다릅니다.

  • AWS IoT에서 주제 구독 서비스 품질(QoS) 0은 메시지가 0번 이상 전달된다는 의미입니다. 메시지가 한 번 이상 전달될 수 있습니다. 여러 번 전달되는 메시지는 다른 패킷 ID를 사용하여 전송될 수 있습니다. 이러한 경우 DUP 플래그가 설정되지 않습니다.

  • AWS IoT은(는) QoS 2 게시 및 구독을 지원하지 않습니다. AWS IoT 메시지 브로커는 QoS 2가 요청될 경우 PUBACK 또는 SUBACK을 전송하지 않습니다.

  • 한 주제에 대한 게시 및 구독의 QoS 수준은 서로 관련이 없습니다. 한 클라이언트가 QoS 1을 사용하여 주제를 구독하고 다른 클라이언트가 QoS 0을 사용하여 동일한 주제에 게시하는 것이 가능합니다.

  • 연결 요청에 응답할 때 메시지 브로커는 CONNACK 메시지를 전송합니다. 이 메시지에는 연결이 이전 세션을 재개하는 것인지 여부를 나타내는 플래그가 포함됩니다. 2개의 MQTT 클라이언트가 동일한 클라이언트 ID로 동시에 연결하는 경우 이 플래그의 값이 잘못된 것일 수 있습니다.

  • 클라이언트가 주제를 구독할 때 메시지 브로커가 SUBACK을 전송하는 시간과 클라이언트가 일치하는 메시지를 수신하기 시작하는 시점 사이에 지연이 있을 수 있습니다.

  • MQTT 사양은 게시자가 메시지 브로커에게 특정 주제로 전송된 마지막 메시지를 보관했다가 향후의 모든 주제 구독자에게 전송하도록 요청하는 기능을 제공합니다. AWS IoT은(는) 메시지 보관을 지원하지 않습니다. 메시지 보관을 요청할 경우 연결이 해제됩니다.

  • 메시지 브로커는 클라이언트 ID를 사용하여 각 클라이언트를 식별합니다. 클라이언트 ID는 MQTT 페이로드의 일부로 클라이언트가 메시지 브로커로 전달합니다. 클라이언트 ID가 동일한 2개의 클라이언트가 동시에 메시지 브로커에 연결하도록 허용되지 없습니다. 한 클라이언트가 다른 클라이언트에서 사용 중인 클라이언트 ID를 사용하여 메시지 브로커에 연결할 경우 두 클라이언트 모두에게 CONNACK 메시지가 전송되고 현재 연결된 클라이언트가 연결 해제됩니다.

  • 메시지 브로커는 영구 세션(cleanSession 플래그가 false로 설정된 연결)을 지원하지 않습니다. AWS IoT 메시지 브로커는 모든 세션이 클린 세션으로 가정되고 세션 간에 메시지가 저장되지 않는다고 가정합니다. MQTT 클라이언트가 이(가) (으)로 설정된 메시지 브로커로 연결을 시도할 경우 해당 클라이언트는 연결 해제됩니다.

  • 드물지만 메시지 브로커가 다른 패킷 ID로 동일한 논리적 PUBLISH 메시지를 재전송할 수 있습니다.

  • 메시지 브로커는 메시지 및 ACK가 수신되는 순서를 보장하지 않습니다.

HTTP

메시지 브로커는 REST API를 사용하여 HTTP 프로토콜을 통해 연결하는 클라이언트를 지원합니다. 클라이언트는 <AWS IoT Endpoint>/<url_encoded_topic_name>?qos=1"에 POST 메시지를 전송하여 게시할 수 있습니다.

예를 들어 curl을 사용하여 버튼 누름을 에뮬레이션할 수 있습니다. MQTT 클라이언트에서와 같이 AWS IoT MQTT 클라이언트를 사용하는 대신 시작하기 자습서를 따른 경우 다음과 같은 명령을 사용합니다.

curl --tlsv1.2 --cacert root-CA.crt --cert 4b7828d2e5-certificate.pem.crt --key 4b7828d2e5-private.pem.key -X POST -d "{ \"serialNumber\": \"G030JF053216F1BS\", \"clickType\": \"SINGLE\", \"batteryVoltage\": \"2000mV\" }" "https://a1pn10j0v8htvw.iot.us-east-1.amazonaws.com:8443/topics/iotbutton/virtualButton?qos=1"
--tlsv1.2

TLSv1.2(SSL)를 사용합니다. curl이 OpenSSL과 함께 설치되어 있어야 하고 TLS 버전 1.2를 사용해야 합니다.

--cacert <filename>

피어를 확인하기 위한 CA 인증서의 파일 이름입니다.

--cert <filename>

클라이언트 인증서 파일 이름입니다.

--key <filename>

프라이빗 키 파일 이름입니다.

-X POST

요청의 유형입니다(이 경우 POST).

-d <data>

게시할 HTTP POST 데이터입니다. 이 경우, 버튼 한 번 누름으로 전송된 데이터를 에뮬레이션합니다.

"https://..."

URL입니다. 이 경우 사물의 REST API 엔드포인트입니다. (사물의 엔드포인트를 확인하려면 AWS IoT 콘솔에서 레지스트리를 선택하여 선택 항목을 확장합니다. [Things]를 선택하고 사물을 선택한 후 [Interact]를 선택합니다.) 엔드포인트 다음에 포트(:8443), 주제를 차례로 추가하고 마지막으로 쿼리 문자열에 서비스 품질을 지정합니다(?qos=1).

MQTT Over WebSocket 프로토콜

AWS IoT은(는) MQTT over WebSocket 프로토콜을 지원하여 브라우저 기반 및 원격 애플리케이션이 AWS 자격 증명을 사용하여 AWS IoT 연결 디바이스와 데이터를 송수신할 수 있습니다. AWS 자격 증명은 AWS 서명 버전 4를 사용하여 지정됩니다. WebSocket 지원은 TCP 포트 443에서 가능하며, 대부분의 방화벽 및 웹 프록시를 통해 메시지를 전달할 수 있습니다.

WebSocket 연결은 클라이언트에서 HTTP GET 요청을 전송하여 시작됩니다. URL의 형식은 다음과 같습니다.

wss://<endpoint>.iot.<region>.amazonaws.com/mqtt
wss

WebSocket 프로토콜을 지정합니다.

endpoint

AWS 계정별 AWS IoT 엔드포인트입니다. AWS IoT CLI describe-endpoint 명령을 사용하여 이 엔드포인트를 찾을 수 있습니다.

리전

AWS 계정의 AWS 리전입니다.

mqtt

MQTT 메시지를 WebSocket 프로토콜을 통해 전송함을 지정합니다.

서버가 응답하면 클라이언트가 서버에게 WebSocket 프로토콜을 사용하여 통신할 것임을 표시하는 업그레이드 요청을 전송합니다. 서버가 업그레이드 요청을 확인하면 모든 통신이 WebSocket 프로토콜을 사용하여 이루어집니다. 사용하는 WebSocket 구현은 전송 프로토콜의 역할을 담당합니다. WebSocket 프로토콜을 통해 전송하는 데이터는 MQTT 메시지입니다.

웹 애플리케이션에서 WebSocket 프로토콜 사용

대부분의 웹 브라우저가 제공하는 WebSocket 구현은 HTTP 헤더 수정을 허용하지 않으므로 쿼리 문자열에 서명 버전 4 정보를 추가해야 합니다. 자세한 내용은 쿼리 문자열에 서명 정보 추가 섹션을 참조하십시오.

다음 JavaScript는 서명 버전 4 요청에 사용되는 몇몇 유틸리티 함수를 정의합니다.

/** * utilities to do sigv4 * @class SigV4Utils */ function SigV4Utils() {} SigV4Utils.getSignatureKey = function (key, date, region, service) { var kDate = AWS.util.crypto.hmac('AWS4' + key, date, 'buffer'); var kRegion = AWS.util.crypto.hmac(kDate, region, 'buffer'); var kService = AWS.util.crypto.hmac(kRegion, service, 'buffer'); var kCredentials = AWS.util.crypto.hmac(kService, 'aws4_request', 'buffer'); return kCredentials; }; SigV4Utils.getSignedUrl = function(host, region, credentials) { var datetime = AWS.util.date.iso8601(new Date()).replace(/[:\-]|\.\d{3}/g, ''); var date = datetime.substr(0, 8); var method = 'GET'; var protocol = 'wss'; var uri = '/mqtt'; var service = 'iotdevicegateway'; var algorithm = 'AWS4-HMAC-SHA256'; var credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'; var canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm; canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(credentials.accessKeyId + '/' + credentialScope); canonicalQuerystring += '&X-Amz-Date=' + datetime; canonicalQuerystring += '&X-Amz-SignedHeaders=host'; var canonicalHeaders = 'host:' + host + '\n'; var payloadHash = AWS.util.crypto.sha256('', 'hex') var canonicalRequest = method + '\n' + uri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash; var stringToSign = algorithm + '\n' + datetime + '\n' + credentialScope + '\n' + AWS.util.crypto.sha256(canonicalRequest, 'hex'); var signingKey = SigV4Utils.getSignatureKey(credentials.secretAccessKey, date, region, service); var signature = AWS.util.crypto.hmac(signingKey, stringToSign, 'hex'); canonicalQuerystring += '&X-Amz-Signature=' + signature; if (credentials.sessionToken) { canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken); } var requestUrl = protocol + '://' + host + uri + '?' + canonicalQuerystring; return requestUrl; };

서명 버전 4 요청을 생성하려면

  1. 서명 버전 4에 대한 정식 요청을 생성합니다.

    다음 JavaScript 코드는 정식 요청을 생성합니다.

    var datetime = AWS.util.date.iso8601(new Date()).replace(/[:\-]|\.\d{3}/g, ''); var date = datetime.substr(0, 8); var method = 'GET'; var protocol = 'wss'; var uri = '/mqtt'; var service = 'iotdevicegateway'; var algorithm = 'AWS4-HMAC-SHA256'; var credentialScope = date + '/' + region + '/' + service + '/' + 'aws4_request'; var canonicalQuerystring = 'X-Amz-Algorithm=' + algorithm; canonicalQuerystring += '&X-Amz-Credential=' + encodeURIComponent(credentials.accessKeyId + '/' + credentialScope); canonicalQuerystring += '&X-Amz-Date=' + datetime; canonicalQuerystring += '&X-Amz-SignedHeaders=host'; var canonicalHeaders = 'host:' + host + '\n'; var payloadHash = AWS.util.crypto.sha256('', 'hex') var canonicalRequest = method + '\n' + uri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\nhost\n' + payloadHash;
  2. 문자열을 생성하여 서명, 서명 키 생성, 문자열 서명을 수행합니다.

    이전 단계에서 생성한 정식 URL을 서명할 문자열에 어셈블합니다. 이렇게 하려면 해시 알고리즘, 날짜, 자격 증명 범위 및 정식 요청의 SHA로 구성된 문자열을 생성합니다. 그런 다음 아래 JavaScript 코드에 나온 것처럼 서명 키를 생성해 문자열에 서명합니다.

    var stringToSign = algorithm + '\n' + datetime + '\n' + credentialScope + '\n' + AWS.util.crypto.sha256(canonicalRequest, 'hex'); var signingKey = SigV4Utils.getSignatureKey(credentials.secretAccessKey, date, region, service); var signature = AWS.util.crypto.hmac(signingKey, stringToSign, 'hex');
  3. 요청에 서명 정보를 추가합니다.

    다음 JavaScript 코드는 쿼리 문자열에 서명 정보를 추가하는 방법을 보여 줍니다.

    canonicalQuerystring += '&X-Amz-Signature=' + signature;
  4. 세션 자격 증명(STS 서버, AsuumeRole 또는 Amazon Cognito의 자격 증명)이 있는 경우, 서명 후 URL 문자열 끝에 세션 토큰을 추가합니다.

    canonicalQuerystring += '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
  5. canonicalQuerystring 앞에 프로토콜, 호스트, URI를 추가합니다.

    var requestUrl = protocol + '://' + host + uri + '?' + canonicalQuerystring;
  6. WebSocket을 엽니다.

    다음 JavaScript 코드는 Paho MQTT를 생성하고 AWS IoT(으)로 CONNECT를 호출하는 방법을 보여 줍니다. endpoint 인수는 사용자의 AWS 계정에 고유한 엔드포인트입니다. clientId는 AWS 계정에서 동시에 연결된 모든 클라이언트를 통틀어 고유한 텍스트 식별자입니다.

    var client = new Paho.MQTT.Client(requestUrl, clientId); var connectOptions = { onSuccess: function(){ // connect succeeded }, useSSL: true, timeout: 3, mqttVersion: 4, onFailure: function() { // connect failed } }; client.connect(connectOptions);

모바일 애플리케이션에서 WebSocket 프로토콜 사용

WebSocket 연결을 하는 경우 AWS IoT 디바이스 SDK 중 하나를 사용하여 디바이스를 AWS IoT에 연결하는 것이 좋습니다. 다음의 AWS IoT 디바이스 SDK는 AWS IoT와(과)의 WebSocket 기반 MQTT 연결을 지원합니다.

MQTT over WebSocket 프로토콜을 사용하여 웹 애플리케이션을 AWS IoT에 연결하기 위한 참조 구현은 AWS Labs WebSocket sample(AWS 실습 WebSocket 샘플) 단원을 참조하십시오.

현재 지원되지 않는 프로그래밍 또는 스크립팅 언어를 사용 중인 경우 최초 WebSocket 업그레이드 요청(HTTP POST)이 AWS 서명 버전 4를 사용하여 서명되었다면 기존의 모든 WebSocket 라이브러리를 사용할 수 있습니다. Eclipse Paho for JavaScript와 같은 일부 MQTT 클라이언트는 기본으로 WebSocket 프로토콜을 지원합니다.