Notice
Recent Posts
Recent Comments
Link
투케이2K
173. (TWOK/LOGIC) [Web] 자바스크립트 paho-mqtt 라이브러리 사용해 AWS Iot Core Fleet Provisioning 프로비저닝 동작 로직 정리 본문
투케이2K 로직정리
173. (TWOK/LOGIC) [Web] 자바스크립트 paho-mqtt 라이브러리 사용해 AWS Iot Core Fleet Provisioning 프로비저닝 동작 로직 정리
투케이2K 2026. 2. 10. 20:06728x90
반응형
[로직 정리]
정리 로직 : AWS / WebRTC / MQTT
상태 : [Web] 자바스크립트 paho-mqtt 라이브러리 사용해 AWS Iot Core Fleet Provisioning 프로비저닝 동작 로직 정리

[설 명]
// --------------------------------------------------------------------------------------
[사전) 설정 및 정보 확인 사항]
// --------------------------------------------------------------------------------------
1. 제 목 : [Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 AWS Iot Core Fleet Provisioning 프로비저닝 동작 로직 정리
2. 테스트 환경 : Aws / Iot / Mqtt / WebSocket / JavaScript / Paho.MQTT
3 사전) Aws Iot Core 간단 설명 :
>> AWS IoT 는 IoT 디바이스를 다른 디바이스 및 AWS 클라우드 서비스에 연결하는 클라우드 서비스를 제공합니다.
>> 디바이스가에 연결할 수 있는 경우 AWS IoT는 AWS 가 제공하는 클라우드 서비스에 디바이스를 AWS IoT 연결할 수 있습니다.
>> AWS IoT Core 메시지 브로커는 MQTT 및 MQTT over WSS 프로토콜을 사용하여 메시지를 게시하고 구독하는 디바이스 및 클라이언트를 지원합니다.
- HTTPS 프로토콜을 사용하여 메시지를 게시하는 디바이스와 클라이언트도 지원합니다.
4. 사전) MQTT (Message Queuing Telemetry Transport) 설명 :
>> MQTT 는 경량 메시지 프로토콜로, 주로 IoT(사물인터넷) 환경에서 사용됩니다
>> MQTT 목적 : 제한된 네트워크 환경(저속, 불안정)에서 효율적으로 메시지를 주고받기 위해 설계
>> MQTT 기반 : TCP/IP 위에서 동작
>> MQTT 패턴 : Publish/Subscribe 모델을 사용
- Publisher : 메시지를 발행하는 클라이언트
- Subscriber : 특정 주제(topic)를 구독하는 클라이언트
- Broker: 메시지를 중개하는 서버 (예: Mosquitto)
>> MQTT 주요 특징 :
- 경량성 : 헤더가 매우 작음(2바이트부터 시작)
- QoS (Quality of Service) :
$ QoS 0: 최대 한 번 전달(보장 없음)
$ QoS 1: 최소 한 번 전달(중복 가능)
$ QoS 2: 정확히 한 번 전달(가장 안전)
- 지속 연결 : KeepAlive로 연결 상태 유지
- Last Will and Testament (LWT) : 클라이언트 비정상 종료 시 브로커가 메시지 발행
- 토픽 기반 라우팅 : 계층적 구조(/home/temperature 등)
5. 사전) 자바스크립트에서 MQTT 연결을 위한 Paho 라이브러리 및 aws4fetch 의존성 설정 코드 :
<!-- [CDN 주소 설정] : https://www.jsdelivr.com/package/npm/paho-mqtt -->
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1416.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/paho-mqtt@1.1.0/paho-mqtt.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.10.7/dayjs.min.js"></script>
<!-- [자바스크립트 코드 작성 부분에 module 로드 지정] -->
<script type="module">
// [모듈 import]
import aws4 from "https://esm.sh/aws4fetch@1.0.17";
const { AwsClient } = aws4;
</script>
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[로직 설명]
// --------------------------------------------------------------------------------------
1. 사전) IAM 계정에 권한 부여 필요 : AWSIoTFullAccess
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:*",
"iotjobsdata:*"
],
"Resource": "*"
}
]
}
2. 자바스크립트에서 AWS Iot Core IAM 계정 정보를 사용해 SigV4 인증 및 URL 생성 수행
// --------------------------------------
// AWS : SigV4 인증 URL 생성
// --------------------------------------
const aws = new AwsClient({
accessKeyId: accessKeyElValue,
secretAccessKey: secretKeyElValue,
service: "iotdevicegateway", // ✅ 중요!
region: regionElValue,
});
const url = `wss://${endpointElValue}/mqtt`; // [AWS iot:Data-ATS 도메인]
// [SigV4 서명된 URL 생성]
const signed = await aws.sign(url, {
method: "GET",
signQuery: true // ✅ signQuery: true 옵션 추가
});
// ✅ wss://a1y..pd9-ats.iot.ap-northeast-1.amazonaws.com/mqtt?X-Amz-Date=20251123T234432Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AK..H7Q%2F20251123%2Fap-northeast-1%2Fiotdevicegateway%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=fcc..d7a
const signUrl = signed.url;
3. new Paho.Client 객체 생성 및 mqttClient.connect 연결 수행
// --------------------------------------
// Set : Client Id : AWS 연결 세션 아이디
// --------------------------------------
const clientId = "clientId-" + Math.random();
// --------------------------------------
// Set : Paho.Client
// --------------------------------------
mqttClient = new Paho.Client(url, clientId); // ✅ AWS WebSocket : wss:// 443 자동 할당
// --------------------------------------
// Set : callback handlers
// --------------------------------------
mqttClient.onConnectionLost = onConnectionLost;
mqttClient.onMessageArrived = onMessageArrived; // ✅ 실시간 메시지 수신 감지 콜백 함수 지정
mqttClient.connect({ // Custom Option
useSSL: true, // ✅ SSL/TLS 사용 여부 : 반드시 true 설정
mqttVersion: 4, // MQTT 프로토콜 버전 (MQTT v3.1.1)
timeout: CONNECT_TIME_OUT, // 연결 시도 타임아웃 (초) → 기본값은 30초
keepAliveInterval: 30, // ✅ Ping 주기 (초) → 기본값은 60초
cleanSession: true, // ✅ 이전 세션 구독 정보 삭제
onSuccess: () => { // 연결에 따른 콜백
console.warn("[AWS] Connection Success : ", url);
onConnect(); // Call Connect Success
},
onFailure: (err) => { // 연결에 따른 에러 메시지
console.error("[AWS] Connection failed : ", err);
onConnectionFail(err); // Call Connect Fail
}
});
4. mqttClient.onConnect 연결이 완료 된 경우 임시 사물 인증서 발급 관련 토픽 구독 수행 및 임시 사물 인증서 생성 요청 수행
// ---------------------------------
// ✅ AWS : Subscribe : 임시 사물 인증서 생성 응답 확인 관련 토픽
// ---------------------------------
const subscribe_topic_Certificate_Accepted_Path = `$aws/certificates/create/json/accepted`;
const subscribe_topic_Certificate_Rejected_Path = `$aws/certificates/create/json/rejected`;
mqttClient.subscribe(topic, { // Custom Set Topic Subscribe
qos: QOS, // 네트워크 서비스 품질
timeout: SUBSCRIBE_TIME_OUT, // SUBACK 대기 시간 (초)
invocationContext: { topic }, // ✅ 토픽을 컨텍스트에 담아둠
onSuccess: (resp) => {
// 브로커가 승인한 QoS와 함께, 내가 담아둔 topic 을 확인 가능
console.log("=========================================");
console.log("[Mqtt] : onSubscribe : onSuccess");
console.log("---------------------------------------");
console.log("[topic] : ", resp.invocationContext.topic);
console.log("---------------------------------------");
console.log("[QOS] : ", resp.grantedQos);
console.log("=========================================");
try {
if (subscribeTopicList.indexOf(resp.invocationContext.topic) < 0){ // 배열에 특정 값을 포함하지 않는 경우
subscribeTopicList.push(resp.invocationContext.topic); // ✅ 배열에 구독한 토픽 추가
}
// ✅ 임시 사물 인증서 생성 요청에 대한 토픽이 모두 구독 된 경우
if (subscribeTopicList.indexOf(subscribe_topic_Certificate_Accepted_Path) >= 0 && subscribeTopicList.indexOf(subscribe_topic_Certificate_Rejected_Path) >= 0){
console.warn("[Mqtt] : onSubscribe : Certificate Path Validation Check : Success");
// ---------------------------------
// ✅ AWS : Publish : 임시 인증서 생성 요청
// ---------------------------------
onPublish(publish_topic_Certificate_Create_Path, "");
// ---------------------------------
}
}
catch (exception) {
console.error("[onSubscribe] : [Topic List Add] : 예외 상황 발생 : ", exception.message);
}
},
onFailure: (err) => {
console.error("[onSubscribe] : [구독 수행] : onFailure : ", err);
}
});
5. 실시간 mqtt 메시지 수신 감지 onMessageArrived 부분에서 임시 사물 인증서 생성 요청 accepted 토픽으로 응답이 내려온 경우 필요 데이터 파싱 수행 및 템플릿 등록 요청 관련 토픽 구독 수행 실시
if (message.destinationName == subscribe_topic_Certificate_Accepted_Path){ // ✅ 임시 사물 인증서 생성 요청 성공 응답
/*
{
"certificateId": "688..e2c",
"certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCC..Z+yxpf\n-----END CERTIFICATE-----\n",
"privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpA..zpvlMuQi0g==\n-----END RSA PRIVATE KEY-----\n",
"certificateOwnershipToken": "ey..pUIn0="
}
// */
try {
const temp_json = JSON.parse(message.payloadString);
if (temp_json.hasOwnProperty("certificateId") == true && temp_json.hasOwnProperty("certificatePem") == true
&& temp_json.hasOwnProperty("privateKey") == true && temp_json.hasOwnProperty("certificateOwnershipToken") == true){
temp_certificateId = temp_json.certificateId;
temp_certificatePem = temp_json.certificatePem;
temp_privateKey = temp_json.privateKey;
temp_certificateOwnershipToken = temp_json.certificateOwnershipToken;
console.warn("[Mqtt] : onMessageArrived : Parsing : Certificate : Success");
onMessageTopicList.push(message.destinationName); // Add Array
// ---------------------------------
// ✅ AWS : Subscribe : 템플릿 등록 요청 응답 확인 관련 토픽
// ---------------------------------
/*
var subscribe_topic_Template_Accepted_Path = function(){
return `$aws/provisioning-templates/${templateName}/provision/json/accepted`;
}
var subscribe_topic_Template_Rejected_Path = function(){
return `$aws/provisioning-templates/${templateName}/provision/json/rejected`;
}
// */
// ---------------------------------
onSubscribe(subscribe_topic_Template_Rejected_Path()); // 템플릿 등록 관련 응답 확인 토픽
onSubscribe(subscribe_topic_Template_Accepted_Path()); // 템플릿 등록 관련 응답 확인 토픽
// ---------------------------------
}
else {
console.error("[Mqtt] : onMessageArrived : Parsing : Certificate : Error : certificateId , certificatePem , privateKey , certificateOwnershipToken Key Not Found");
}
}
catch (error){
console.error("[Mqtt] : onMessageArrived : Parsing : Certificate : Exception : ", error);
}
}
6. mqttClient.subscribe 구독 이벤트 확인 부분에서 템플릿 등록 관련 토픽이 모두 구독 된 경우 템플릿 생성 요청 publish 수행 실시
mqttClient.subscribe(topic, { // Custom Set Topic Subscribe
qos: QOS, // 네트워크 서비스 품질
timeout: SUBSCRIBE_TIME_OUT, // SUBACK 대기 시간 (초)
invocationContext: { topic }, // ✅ 토픽을 컨텍스트에 담아둠
onSuccess: (resp) => {
// 브로커가 승인한 QoS와 함께, 내가 담아둔 topic 을 확인 가능
console.log("=========================================");
console.log("[Mqtt] : onSubscribe : onSuccess");
console.log("---------------------------------------");
console.log("[topic] : ", resp.invocationContext.topic);
console.log("---------------------------------------");
console.log("[QOS] : ", resp.grantedQos);
console.log("=========================================");
try {
if (subscribeTopicList.indexOf(resp.invocationContext.topic) < 0){ // 배열에 특정 값을 포함하지 않는 경우
subscribeTopicList.push(resp.invocationContext.topic); // ✅ 배열에 구독한 토픽 추가
}
// ✅ 템플릿 생성 요청에 대한 토픽이 모두 구독 된 경우
if (subscribeTopicList.indexOf(subscribe_topic_Template_Accepted_Path()) >= 0 && subscribeTopicList.indexOf(subscribe_topic_Template_Rejected_Path()) >= 0){
console.warn("[Mqtt] : onSubscribe : Template Path Validation Check : Success");
// ---------------------------------
// ✅ AWS : Publish : 정의 된 규격에 맞게 Template 템플릿 등록 요청 수행
// ---------------------------------
const templateCreateJson = templatePayloadInput.value; // TextArea 값을 JSONObject 로 변경
const parseJson = JSON.parse(templateCreateJson);
parseJson.certificateOwnershipToken = temp_certificateOwnershipToken;
parseJson.Parameters.CertificateId = temp_certificateId;
onPublish(publish_topic_Template_Create_Path(), JSON.stringify(parseJson));
// ---------------------------------
}
}
catch (exception) {
console.error("[onSubscribe] : [Topic List Add] : 예외 상황 발생 : ", exception.message);
}
},
onFailure: (err) => {
console.error("[onSubscribe] : [구독 수행] : onFailure : ", err);
}
});
7. 실시간 mqtt 메시지 수신 감지 onMessageArrived 부분에서 템플릿 등록 요청 관련 accepted 응답이 내려온 경우 데이터 파싱 및 프로비저닝 수행 완료 처리 진행
// --------------------------------------
// Check : Template Create Accepted
// --------------------------------------
if (message.destinationName == subscribe_topic_Template_Accepted_Path()){ // ✅ 템플릿 등록 요청 관련 응답 체크
/*
{"deviceConfiguration":{},"thingName":"TWOK_9999999999"}
// */
try {
const temp_json = JSON.parse(message.payloadString);
if (temp_json.hasOwnProperty("thingName") == true){
responseThingName = temp_json.thingName;
onMessageTopicList.push(message.destinationName); // Add Array
console.warn("[Mqtt] : onMessageArrived : Parsing : Template : Success");
// ✅ statusEl.value = 'AWS 템플릿 등록 요청 완료 >> Response Thing 확인 : ' + responseThingName;
}
else {
console.error("[Mqtt] : onMessageArrived : Parsing : Template : Error : thingName Json Key Not Found");
}
}
catch (error){
console.error("[Mqtt] : onMessageArrived : Parsing : Template : Exception : ", error);
}
}
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------
[Web/JavaScript] paho-mqtt 라이브러리 사용해 AWS IOT Core 플릿 프로비저닝 Thing 사물 등록 수행
https://kkh0977.tistory.com/8491
https://blog.naver.com/kkh0977/224109136460
[Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 구독 된 토픽 전체 구독 해제 수행 - All UnSubscribe
https://kkh0977.tistory.com/8590
https://blog.naver.com/kkh0977/224158927319
[간단 소스] 자바스크립트 paho-mqtt 라이브러리 및 aws4fetch 사용해 AWS IOT MQTT 연결을 위한 WebSocket 주소 확인
https://kkh0977.tistory.com/8417
https://blog.naver.com/kkh0977/224084144227
[간단 소스] 자바스크립트 paho-mqtt 라이브러리 사용해 커스텀 구독 Subscribe , Publish 메시지 발생 객체 정의
https://blog.naver.com/kkh0977/224086668570
// --------------------------------------------------------------------------------------
728x90
반응형
'투케이2K 로직정리' 카테고리의 다른 글
Comments
