본문 바로가기

프로그래밍/IoT

[AWS IoT] MQTT Republish Rule Action 사용시 주의점

반응형

요구사항은 다음과 같았다.

IoT Device에서 발생한 특정한 이벤트에 대하여 실시간으로 정보를 받고 싶다는 외부의 요청이 있었다.

협업을 하는 외부 조직이다보니 빠르게 대응을 해줘야했지만, 우리가 갖춰야 하는 중요한 Business Logic과는 관련이 없는 부분이었기 때문에 로직을 관리하는 코드를 더럽히고(?) 싶지 않았다.

단순한 API 연동이었기 때문에 특정 Topic으로 발생한 이벤트를 catch하여, 전달받은 API로 POST요청을 하면 되는 상황이었다.

 

이 때 발생한 고민 포인트가 또 한가지 있었다.

HTTPS API 연동을 Lambda와 같은 서비스를 사용해서 처리할 지, 다행스럽게도 AWS IoT에서 제공하는 HTTPS Downstream Rule을 사용하여 처리할 지..

 

위의 고민 포인트에 앞서서 결정해야 되는 부분은 모든 Topic들 중에서 특정 Topic만을 filtering하는 것을 어떻게 해야할까? 라는 것이 있었다.

비용 효율화를 위해 Basic Ingest Rule을 사용하고 있다 보니, 해당 Topic에 대해서는 온전히 새로운 Rule을 생성하여 처리할 수 없는 한계가 있었기 때문에 특적 Topic을 Filtering 하는 방법으로 MQTT Republish Rule Action을 선택하였다.

 

Topic Depth를 사용한 Republish Rule

$aws/rules/iotService/v1/{thingName}

위와 같은 Topic Interface가 있다고 가정해보자.

당연히 위 Topic을 처리하는 Rule Name은 iotService일 것이다.

 

기존에 위 Topic이 전달될 경우 처리하던 Rule Action이 있었지만, 외부 조직의 요청사항을 위해 필요한 데이터는 맨 마지막 Topic Depth를 사용하기로 하였다.

$aws/rules/iotService/v1/{thingName}/{reqType}

맨 마지막의 reqType 필드는 존재할 수도, 존재하지 않을 수도 있다.

해당 필드가 존재하지 않아도 Rule 자체는 FROM절이 없는 Basic Ingest Rule이기 때문에 정상적인 Topic 처리가 가능하다.

 

만약 위의 예시에서 reqType이 "specific"일 경우 외부 연동 API를 호출하는 작업이 필요할 경우,

reqType을 포함하여 Republish Topic을 생성한뒤, 재게시 되는 Topic을 Catch하는 Rule을 생성하면 된다고 판단하였다.

send/external/${topic(3)}

위와 같이 Republish Topic을 만들었고, 

send/external/specific이라는 토픽만을 Catch하는 Rule을 만들고자 하였다.

 

결과는 정상적으로 동작하였지만, 뒤늦게 발생한 문제점이 있었다.

Broker Log에서 functionEval 에러가 발생하였고, topic이라는 functionName에서 에러가 발생하는 것이었다.

 

functionEval 에러가 발생하는 이유

$aws/rules/iotService/v1/{thingName}/specific의 토픽을 publish하면 에러 메시지가 나타나지 않지만,

$aws/rules/iotService/v1/{thingName}의 토픽을 publish하면 에러 메시지가 나타난다.

 

즉, 아래의 Topic은 topic(3)라고 하는 함수를 실행하는 과저에서 에러가 나는 것으로

Broker Log의 Error Message에 나오는 바와 같이 결과 값이 Undefined라서 발생하는 Error이다.

 

한가지 특이한 부분은 topic(3)를 실행한 결과가 undefined라서 에러는 발생하고 있지만, 실제 republish Action은 오류 없이 실행된다.

단, send/external/ 이렇게만 republish가 된다.

 

Empty String에 대한 Republish 처리 - Proxy Rule Action 사용

일반적인 Coding Level에서 사용하는 or 구문을 Republish Rule Action에서 사용하는 것은 불가능했다.

그렇다고 Basic Ingest Rule에 바로 Lambda를 연결하여 Lambda 함수 내에서 특정 Topic을 Filtering하는 것은 비용적으로나 운영 및 관리의 측면에서나 Managed Service를 사용하는 이점을 하나도 누릴 수 없었다.

 

조금은 번거롭지만, 그래도 가장 효과적으로 처리할 수 있는 방법으로서 AWS Docs에도 제시된 Substitution Templates을 사용하기로 하였다. (링크)

 

Topic의 특정 depth를 선택하여 republish를 하는 것이 아니라 전체 topic에 대하여 republish를 하는 것이다.

${topic()}/republish

// v1/{thingName}/republish
// v1/{thingName}/specific/republish

위의 예시와 같이 전체 Topic을 선택하여 republish를 한다면, 발송하는 topic의 depth에 따라서 각주처리한 2개의 republish topic이 생성된다.

실제 외부 연동 API를 호출하는 Rule 이전에 Proxy 역할을 할 수 있는 Rule Action을 만들어서,

v1/+/+/republish 토픽을 Catch하도록 한 뒤,

send/external/topic(3) 토픽으로 다시 Republish를 한다면, topic(3) 부분은 언제나 존재하는 값이 되기 때문에 topic function을 실행하는 과정에서 발생하는 에러는 없어지게 된다. 

 

 

반응형