투케이2K

169. (TWOK/LOGIC) [Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 구독 된 토픽 전체 구독 해제 수행 - All UnSubscribe 본문

투케이2K 로직정리

169. (TWOK/LOGIC) [Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 구독 된 토픽 전체 구독 해제 수행 - All UnSubscribe

투케이2K 2026. 1. 25. 12:08
728x90

[로직 정리]

정리 로직 : Aws / Iot Core / MQTT / Shadow

상태 : [Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 구독 된 토픽 전체 구독 해제 수행 - All UnSubscribe

 

[설 명]

 

// --------------------------------------------------------------------------------------
[사전) 설정 및 정보 확인 사항]
// --------------------------------------------------------------------------------------

1. 제 목 : [Aws] 자바스크립트 paho-mqtt 라이브러리 사용해 구독 된 토픽 전체 구독 해제 수행 - All UnSubscribe


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. 사전) 해당 로직 개발 요건 :

  >> 관리자페이지에서 특정 사물 별 구독 해제하는 로직을 전체 구독을 해제할 수 있게 해달라는 로직 개발 요청


2. 자바스크립트에서 전체 구독 토픽을 관리할 수 있게 전역 변수 배열 선언 후 구독 및 구독 해제 시 마다 배열에서 


3. 자바스크립트 구독 시 마다 토픽 리스트 추가 코드 : 

  mqttClient.subscribe(topic, { // Custom Set Topic Subscribe

      qos: QOS, // 네트워크 서비스 품질
      timeout: SUBSCRIBE_TIME_OUT, // SUBACK 대기 시간 (초)
      invocationContext: { topic }, // ✅ 토픽을 컨텍스트에 담아둠

      onSuccess: (resp) => {

          // 브로커가 승인한 QoS와 함께, 내가 담아둔 topic 을 확인 가능
          console.log("");
          console.log("=========================================");
          console.log("[Mqtt] : onSubscribe : onSuccess");
          console.log("---------------------------------------");
          console.log("[topic] : ", resp.invocationContext.topic);
          console.log("---------------------------------------");
          console.log("[QOS] : ", resp.grantedQos);
          console.log("=========================================");
          console.log("");

          try {
            if (subscribeTopicList.indexOf(resp.invocationContext.topic) < 0){ // ✅ 토픽 리스트에 특정 값을 포함하지 않는 경우
              subscribeTopicList.push(resp.invocationContext.topic);

              console.warn("[Add Topic List Total Count] : ", subscribeTopicList.length);
            }
          }
          catch (exception) {
            console.error("[onSubscribe] : [Topic List Add] : 예외 상황 발생 : ", exception.message);
          }
          
      },
      onFailure: (err) => {
          console.error("[onSubscribe] : [구독 수행] : onFailure : ", err);
      }
  });


4. 자바스크립트 구독 된 토픽 전체 구독 해제 수행 코드 : 

if (subscribeTopicList != null && subscribeTopicList != undefined && subscribeTopicList.length > 0){
  
  // ---------------------------------------------------

  console.warn("subListAllUnSub : 구독 해제 토픽 리스트 확인 : ", subscribeTopicList);

  // ---------------------------------------------------

  // ✅ [동기 순차 처리 - 구독 해제 (Promise 내부 함수 생성)]
  const unsubscribeAsync = (topic, msTimeout = 5000) => {
    return new Promise((resolve, reject) => {

      let finished = false;
      const timer = setTimeout(() => {
        if (!finished) {
          finished = true;
          reject(new Error(`Unsubscribe timeout: ${topic}`));
        }
      }, msTimeout);
      
      try {

        mqttClient.unsubscribe(topic, {
          timeout: 5, // 초
          onSuccess: (ctx) => {
            console.warn("unsubscribed : success : ", ctx?.invocationContext);                                

            // 토픽 제거 후 재할당
            subscribeTopicList = subscribeTopicList.filter(v => v !== topic);

            console.warn("doUnSubscribe : 토픽 제거 및 현재 구독 된 리스트 확인 : ", JSON.stringify(subscribeTopicList));

            if (!finished) {
              finished = true;
              clearTimeout(timer);
              resolve(ctx);
            }

          },
          onFailure: (e) => {
            console.error("unsubscribe failed : ", e.errorMessage);

            if (!finished) {
              finished = true;
              clearTimeout(timer);
              reject(new Error(`Unsubscribe failed : ${topic}`));
            }

          },
          invocationContext: { reason: "manual-unsub" }
        });

      }
      catch(error){
        console.error("unsubscribeAsync : Exception : ", error);

        if (!finished) {
          finished = true;
          clearTimeout(timer);
          reject(new Error(`Unsubscribe exception : ${topic}`));
        }
        
      }                              

    });
  };

  // ---------------------------------------------------

  const topics = [...subscribeTopicList]; // ✅ 배열 복사

  for (var i=0; i<topics.length; i++){
    try {
      const topic = topics[i];

      console.log("subListAllUnSub : await topic unSubscribe : ", topic);

      await unsubscribeAsync(topic, 5000); // ✅ ★ 진짜로 대기(순차)

    }
    catch (error){
      console.error("subListAllUnSub : for exception : ", error);
    }                            

  }

  // ---------------------------------------------------

}

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------

[Web/JavaScript] paho-mqtt 라이브러리 사용해 AWS IOT Core 플릿 프로비저닝 Thing 사물 등록 수행

https://kkh0977.tistory.com/8491

https://blog.naver.com/kkh0977/224109136460


[간단 소스] 자바스크립트 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
반응형
Comments