← 전체 글
MQTT/약 11분 읽기/ 조회

SCADA에서 MQTT QoS와 Retained Message를 정할 때 보는 것

SCADA와 산업용 텔레메트리에서 MQTT QoS, retained message, 세션, 중복 메시지, 명령 토픽을 어떻게 나눠 볼지 정리한 현장 노트.

MQTTSCADA네트워킹문제 해결태그

QoS만 올린다고 안전해지지 않는다

MQTT를 SCADA에 붙이면 처음에는 금방 동작한다. 게이트웨이가 온도 값을 publish하고, 브로커가 받고, HMI나 히스토리언이 subscribe한다. 여기까지는 단순하다.

문제는 운영 중에 나온다.

  • 철거한 장치 값이 새 화면에 다시 나타난다.
  • 재접속 뒤 같은 명령이 한 번 더 처리된다.
  • 히스토리언이 오래된 시작 값을 새 데이터처럼 저장한다.
  • 느린 subscriber 때문에 브로커 큐가 쌓인다.
  • 현장 장비는 죽었는데 화면에는 정상 값처럼 보인다.

이런 문제는 “QoS 1로 바꾸자”로 끝나지 않는다. QoS, retained message, 세션 유지 방식, 타임스탬프, 품질값을 같이 정해야 한다.

QoS는 통신 보장이지 값의 품질이 아니다

MQTT QoS는 브로커와 클라이언트 사이에서 메시지를 어떻게 주고받을지 정한다. 그 값이 최신인지, PLC가 실제로 받아들였는지, 계측기가 정상인지까지 보장하지 않는다.

QoS의미SCADA에서 쓰는 경우
0최대 한 번 전달다음 값이 곧 오는 빠른 텔레메트리. 한두 개 빠져도 되는 값.
1최소 한 번 전달중요한 상태 변화나 계측값. 중복 처리가 가능해야 한다.
2MQTT 구간에서 정확히 한 번 전달현장 텔레메트리에서는 드물다. 오버헤드가 있고 명령 안전을 대신하지 못한다.

대부분의 설비 데이터는 QoS 0 또는 QoS 1로 충분하다. QoS 2라는 이름이 좋아 보여도 모터 기동 명령을 안전하게 만들지는 않는다. 기동 명령에는 명령 ID, 인터록 확인, 피드백, 타임아웃, 운전 이력이 따로 필요하다.

QoS 1 중복은 정상 상황으로 본다

QoS 1에서는 같은 메시지가 두 번 도착할 수 있다. 브로커 오류가 아니라 방식 자체가 그렇다.

그래서 받는 쪽을 중복에 강하게 만들어야 한다.

  • 페이로드(payload)에 소스 타임스탬프를 넣는다.
  • 순서가 중요하면 sequence 번호를 넣는다.
  • 히스토리언이나 이벤트 저장 로직은 같은 메시지를 다시 받아도 결과가 틀어지지 않게 만든다.
  • 명령에는 command ID와 응답 토픽을 둔다.
  • 같은 MQTT 메시지가 다시 왔다고 생산 수량이나 정지 횟수를 또 올리지 않는다.

현장에서 자주 보는 실수는 이벤트 테이블이다. 네트워크가 잠깐 끊긴 뒤 subscriber가 재접속한다. QoS 1 메시지가 다시 들어온다. 이벤트 처리기가 이를 새 이벤트로 저장하면 보고서가 틀어진다. MQTT는 정상 동작했는데 업무 데이터가 깨진 것이다.

Retained message는 새 subscriber에게 보여줄 값에만 쓴다

Retained message는 브로커가 해당 토픽의 마지막 메시지를 저장했다가 새 subscriber에게 바로 보내는 기능이다. 상태값에는 편하지만, 오래된 값과 실시간 값을 구분하지 못하면 위험하다.

retained로 두기 괜찮은 예는 다음과 같다.

  • 엣지 장치의 birth 정보.
  • 모델명, 펌웨어 버전 같은 정적 정보.
  • 현재 모드나 레시피명. 단, 타임스탬프와 장치 상태가 같이 있어야 한다.
  • 화면에서 “마지막으로 알려진 상태”라고 분명히 표시하는 값.

retained로 두면 곤란한 예도 명확하다.

  • 순간 명령.
  • 알람 확인 요청.
  • 빠르게 변하는 아날로그 샘플.
  • 한 번만 처리해야 하는 배치 이벤트.
  • 장비가 오프라인인데도 정상값처럼 보이는 계측값.

펌프 속도 값이 retained로 남아 있으면 새 HMI 화면은 값을 즉시 받는다. 하지만 그 값이 어제 값이면 운전자는 속을 수 있다. retained telemetry를 쓰려면 화면에 신선도와 품질을 같이 보여줘야 한다.

텔레메트리, 상태, 명령 토픽을 나눈다

모든 토픽을 같은 규칙으로 처리하면 나중에 반드시 꼬인다. 토픽 종류별로 QoS와 retained 정책을 다르게 잡는 편이 낫다.

토픽 종류보통의 설정
텔레메트리site/line1/press/pt101/pvQoS 0 또는 1. 보통 retained 없음. 소스 타임스탬프 필요.
상태site/line1/filler/stateQoS 1. 마지막 상태 표시가 필요할 때만 retained.
Birth/deathsite/line1/gw01/statusQoS 1. birth retained와 Last Will 조합.
이벤트site/line1/filler/eventsQoS 1. retained 없음. event ID 필요.
명령site/line1/filler/cmd/startQoS 1. retained 금지. command ID와 응답 토픽 필요.

이렇게 나눠 두면 장애 분석도 쉽다. 브로커에 retained 명령이 남아 있다면 토픽 정책이 잘못된 것이다.

세션 유지와 큐 적체를 확인한다

Subscriber가 꺼져 있을 때 브로커가 메시지를 어떻게 처리하는지도 중요하다. persistent session은 오프라인 동안 메시지를 쌓아 두었다가 나중에 보낼 수 있다. 좋아 보이지만, 오래된 운전값이 한꺼번에 몰려오면 HMI에는 쓸모가 없다.

HMI 화면은 보통 최신값과 품질이 중요하다. 반대로 이벤트 수집기는 끊긴 동안의 이벤트를 받아야 할 수 있다. 이때도 원래 소스 타임스탬프로 저장해야 한다.

시운전 때는 다음을 확인한다.

  • 클라이언트 라이브러리가 clean session, clean start, session expiry를 어떻게 쓰는가.
  • 느리거나 끊긴 subscriber의 큐 제한이 있는가.
  • backlog를 받아도 되는 subscriber와 안 되는 subscriber를 구분했는가.
  • 브로커의 queued message, dropped message 카운터를 모니터링하는가.
  • 실제 publish 중 subscriber를 내렸다 올려서 순서와 시간 처리를 확인했는가.

모든 클라이언트가 항상 살아 있을 때만 맞는 설계는 현장 설계가 아니다. 데모에 가깝다.

페이로드에 꼭 들어가야 할 정보

페이로드가 복잡할 필요는 없다. 다만 재접속, 중복, 지연 상황에서도 판단할 수 있는 정보는 있어야 한다.

현장에서 유용한 필드는 다음과 같다.

  • value: 계측값, 상태값, 이벤트 내용.
  • sourceTimestamp: 장치나 게이트웨이가 값을 만든 시각.
  • quality: good, uncertain, bad, simulated, forced 같은 품질.
  • sequence: 가능하면 소스별 증가 번호.
  • source: 게이트웨이, PLC, 장비 ID.

명령 응답에는 command ID, accepted 또는 rejected 결과, 거절 사유, 평가 후 장비 상태를 넣는다. 이 정보가 없으면 나중에 브로커 로그만 뒤지게 된다.

시운전에서 반드시 해볼 테스트

MQTT 경로를 운영에 넣기 전에 브로커와 실제 클라이언트 설정으로 테스트해야 한다.

  1. Publisher가 이미 동작 중일 때 subscriber를 새로 띄우고 어떤 retained 값이 들어오는지 본다.
  2. Publisher를 끊고 Last Will 또는 offline 상태가 표시되는지 확인한다.
  3. Publisher를 다시 붙였을 때 offline 상태가 정상 birth 상태로 바뀌는지 본다.
  4. Subscriber를 오래 내려 backlog를 만든 뒤 다시 올려 순서와 타임스탬프를 본다.
  5. publish acknowledgement 시점에 네트워크를 끊어 QoS 1 중복 상황을 만든다.
  6. 명령 토픽이 retained가 아니며 클라이언트 재시작 뒤 재실행되지 않는지 확인한다.
  7. HMI가 live, stale, bad, last-known 값을 다르게 보여주는지 본다.

정답은 모든 토픽에 같은 MQTT 설정을 넣는 것이 아니다. 토픽 종류별로 장애와 복구 때 어떻게 보일지 미리 정해 두는 것이다.

현장에서 쓰는 기준

빠르게 계속 들어오는 값은 QoS 0을 검토한다. 중요한 상태와 이벤트는 QoS 1을 쓰되 중복 처리를 전제로 한다. Retained message는 새 subscriber가 마지막 상태를 알아야 할 때만 쓴다. 그리고 타임스탬프, 품질, sequence, 명령 응답을 붙여 SCADA가 올바르게 판단하게 만든다.

MQTT는 메시지를 옮긴다. 그 메시지가 신선한지, 믿을 수 있는지, 제어에 써도 되는지는 SCADA 설계에서 결정해야 한다.