MQTT Retained Message와 Last Will 차이: 장비 Online·Offline 상태 관리하기

MQTT Retained Message와 Last Will 차이: 장비 Online·Offline 상태 관리하기#

1장 장비가 지금 Online인지 어떻게 알 수 있을까#

주차장 Gate Controller가 MQTT Broker와 연결되어 있다고 생각해보겠습니다.

관제 화면에는 다음과 같은 상태가 필요합니다.

Gate 01
ONLINE

Gate 02
OFFLINE

Gate 03
DEGRADED

문제는 단순히 마지막 Message 하나만 보고 현재 장비가 살아 있다고 판단할 수 없다는 것입니다.

예를 들어 Broker에 다음 Message가 남아 있다고 하겠습니다.

{
  "status": "online"
}

이 Message가 3시간 전에 발행된 것이라면 현재도 장비가 Online이라고 확신할 수 있을까요?

그 사이에:

전원 장애

Network 단절

Gateway 고장

Application Crash

가 발생했을 수도 있습니다.

MQTT에서는 이런 상태 관리에 유용한 기능으로:

Retained Message

Last Will

을 제공합니다.

두 기능은 자주 함께 사용하지만 역할은 전혀 다릅니다.


2장 Retained Message는 마지막 상태를 Broker가 기억하는 기능이다#

일반 MQTT Message는 Subscriber가 연결되어 있을 때 전달됩니다.

그런데 관제 Dashboard가 나중에 실행됐다고 하겠습니다.

이미 Gate가 10분 전에:

{
  "status": "online"
}

을 Publish했습니다.

Dashboard가 뒤늦게 Subscribe했다면 이전 Message를 모를 수 있습니다.

이때 Retained Message를 사용할 수 있습니다.

Publisher가:

retain = true

로 Message를 Publish하면 Broker가 해당 Topic의 Retained Message를 보관합니다.

예:

Topic
parking/site01/gate01/status

Payload:

{
  "status": "online"
}

새로운 Subscriber가:

parking/site01/gate01/status

를 Subscribe하면 Broker는 저장된 Retained Message를 즉시 전달할 수 있습니다.


3장 Retain은 최신 상태판과 비슷하다#

Retain을 가장 쉽게 이해하는 방법은 게시판입니다.

Gate 01 최신 상태

ONLINE

이라는 내용을 게시판에 붙여둔다고 생각하면 됩니다.

새로운 운영자가 나중에 와도 게시판을 보는 순간 마지막 상태를 알 수 있습니다.

그래서 Retained Message는 다음과 같은 State 정보와 잘 맞습니다.

장비 현재 상태

Gate 현재 상태

주차면 현재 점유 상태

현재 운영 Mode

마지막 알려진 Sensor 값

반면 모든 Event를 Retain으로 저장하는 용도로 사용하는 것은 적합하지 않을 수 있습니다.


4장 Retained Message는 Message History가 아니다#

중요한 차이입니다.

다음 Message가 순서대로 Publish되었다고 하겠습니다.

ONLINE

DEGRADED

ONLINE

OFFLINE

모두 같은 Topic에 Retain으로 Publish했다면 Broker가 일반적으로 기억하는 것은 마지막 Retained Message입니다.

즉:

OFFLINE

이 남습니다.

Retain은:

과거 Message 목록

을 저장하는 기능이라기보다:

이 Topic의 마지막 알려진 상태

를 제공하는 기능으로 이해하는 것이 좋습니다.

전체 Event History가 필요하다면 별도의 Database나 Event Store를 사용하는 것이 일반적입니다.


5장 Last Will은 장비가 갑자기 사라졌을 때 Broker가 대신 알리는 기능이다#

이번에는 Gate Controller가 갑자기 전원을 잃었다고 하겠습니다.

정상적인 종료라면 Client가:

나 이제 연결을 종료한다.

는 의미로 정상 Disconnect 과정을 수행할 수 있습니다.

하지만 전원이 갑자기 끊기면 이런 Message를 보낼 기회조차 없습니다.

Gate Controller
      │
      X 전원 장애
      │
Broker

그러면 Subscriber는:

장비가 죽었는지

Network가 끊긴 것인지

그냥 Message를 안 보내는 것인지

알기 어렵습니다.

이때 사용하는 것이 Last Will, 흔히 LWT라고 부르는 기능입니다.


6장 Last Will은 연결할 때 미리 등록한다#

Client가 Broker에 연결할 때 미리 다음과 같은 정보를 등록할 수 있습니다.

내가 비정상적으로 연결을 잃으면

이 Topic에

이 Message를

대신 Publish해줘.

예:

Topic
parking/site01/gate01/status

Payload:

{
  "status": "offline"
}

그러면 흐름은 다음과 같습니다.

Gate Controller
↓
Broker 연결

Will 등록
↓
OFFLINE Message 예약

정상 운영
↓
ONLINE 상태

이후 Gate가 비정상적으로 사라지면:

Gate Controller
       X
       │
       ▼
Broker가 Last Will Publish
       │
       ▼
parking/site01/gate01/status
       │
       ▼
OFFLINE

처럼 처리할 수 있습니다.


7장 Retain과 Last Will을 함께 쓰면 상태 관리가 쉬워진다#

두 기능을 결합하면 매우 실용적인 Device Presence 구조를 만들 수 있습니다.

연결 직후#

장비:

parking/site01/gate01/status

에:

{
  "status": "online"
}

을 Retain으로 Publish합니다.

Broker에는:

gate01 = ONLINE

이 남습니다.


비정상 연결 종료#

연결할 때 등록한 Last Will:

{
  "status": "offline"
}

이 Broker에 의해 Publish됩니다.

Will Message도 Retain하도록 설정했다면 Broker의 마지막 상태는:

gate01 = OFFLINE

으로 바뀝니다.


재접속#

Gate가 다시 연결되면:

{
  "status": "online"
}

을 다시 Retain으로 Publish합니다.

결과:

OFFLINE
↓
재접속
↓
ONLINE

으로 상태가 갱신됩니다.


8장 전체 Online·Offline 흐름을 따라가보자#

일반적인 흐름을 정리하면 다음과 같습니다.

1. Device Broker 연결
   ↓
2. Last Will 등록
   ↓
3. ONLINE Retained Message Publish
   ↓
4. 정상 운영
   ↓
5. Network 또는 전원 장애
   ↓
6. Broker가 연결 종료 감지
   ↓
7. Last Will Publish
   ↓
8. OFFLINE Retained 상태 저장
   ↓
9. Device 재접속
   ↓
10. ONLINE Retained Message Publish

이 구조를 사용하면 새로운 관제 Dashboard도 접속 직후 마지막 알려진 Device 상태를 빠르게 표시할 수 있습니다.


9장 정상 Disconnect에서는 Last Will이 어떻게 될까#

Last Will은 일반적으로 비정상적인 연결 종료를 처리하기 위한 기능입니다.

Client가 정상적으로 MQTT Disconnect를 수행하면 등록해 둔 Will Message가 일반적인 비정상 종료 처리처럼 발행되지 않습니다.

따라서 정상 종료가 필요한 Application에서는 Client가 직접:

{
  "status": "offline",
  "reason": "normal_shutdown"
}

같은 상태를 Publish한 뒤 정상적으로 Disconnect하도록 설계할 수도 있습니다.

예:

정상 Shutdown

OFFLINE Publish
↓
DISCONNECT

반면:

전원 장애
Network 단절
Process Crash

처럼 정상 Message를 보낼 수 없는 경우 Broker의 Last Will이 역할을 합니다.


10장 Offline은 즉시 감지되지 않을 수도 있다#

여기서 매우 중요한 부분이 있습니다.

Network Cable이 뽑혔다고 Broker가 반드시 같은 순간에:

OFFLINE

을 Publish하는 것은 아닙니다.

Broker가 Client 연결이 사라졌다는 사실을 인지해야 합니다.

이 과정에는 다음이 영향을 줄 수 있습니다.

MQTT Keep Alive

TCP 연결 상태

Network Timeout

Broker 동작

따라서:

Cable Disconnect
=
즉시 Last Will

이라고 생각하면 안 됩니다.

실제 Offline 감지 시간은 Keep Alive와 Network 조건을 함께 고려해야 합니다.


11장 Keep Alive와 Last Will은 함께 이해해야 한다#

MQTT Client가 Broker와 연결하면서 Keep Alive 값을 설정할 수 있습니다.

Client와 Broker 사이에 일정 시간 Application Traffic이 없다면:

PINGREQ
↓
PINGRESP

등을 이용해 연결을 유지하고 상태를 확인할 수 있습니다.

장비가 사라져 Keep Alive 조건을 만족하지 못하면 Broker가 연결 문제를 인지하고 Will 처리를 수행할 수 있습니다.

그래서:

Offline을 빨리 감지하고 싶다
↓
Keep Alive를 무조건 아주 짧게

라고 하면 문제가 될 수 있습니다.

Keep Alive가 너무 짧으면:

Network Traffic 증가

Battery 사용 증가 가능성

Broker 처리 증가

가 생길 수 있습니다.

반대로 너무 길면 장애 감지가 늦어질 수 있습니다.


12장 Retained Online 하나만으로 장비 생존을 판단하면 위험하다#

관제 Server가 다음 Retained Message를 받았습니다.

{
  "status": "online",
  "timestamp": "2026-09-24T10:00:00+09:00"
}

현재 시간이:

10:00:02

라면 비교적 최근 정보입니다.

하지만 현재 시간이:

18:00:00

이라면 어떨까요?

오래된 Retained Message일 수 있습니다.

따라서 상태 Message에는 다음과 같은 정보를 함께 넣는 것을 고려할 수 있습니다.

{
  "status": "online",
  "deviceId": "gate01",
  "timestamp": "2026-09-24T10:00:00+09:00"
}

Monitoring System은:

status

마지막 상태 변경 시각

마지막 Heartbeat 시각

실제 MQTT Connection 상태

를 함께 판단할 수 있습니다.


13장 Online과 정상 동작도 같은 의미가 아니다#

또 하나 중요한 차이입니다.

MQTT Broker와 연결되어 있다고 해서 실제 장비가 정상적으로 동작하는 것은 아닙니다.

예:

MQTT
CONNECTED

Camera
ERROR

Loop Sensor
ERROR

Gate Motor
NORMAL

일 수 있습니다.

따라서 상태를:

ONLINE
OFFLINE

두 가지로만 표현하면 실제 운영 상태를 충분히 표현하지 못할 수 있습니다.

다음처럼 확장할 수 있습니다.

ONLINE

OFFLINE

DEGRADED

MAINTENANCE

ERROR

예:

{
  "connection": "online",
  "health": "degraded",
  "camera": "error",
  "gateMotor": "normal"
}

이렇게 하면 Network 연결 상태와 Device Health 상태를 분리할 수 있습니다.


14장 Last Will의 Offline도 원인을 확정해주지는 않는다#

Last Will이 발생했다고 하겠습니다.

{
  "status": "offline"
}

여기서 바로:

Device 전원이 꺼졌다.

고 단정할 수는 없습니다.

가능한 원인은 여러 가지입니다.

전원 장애

Network Cable 문제

Switch 장애

Router 문제

Firewall

Internet 장애

Client Process Crash

Broker 연결 Timeout

Last Will이 알려주는 핵심은:

Broker와 Client의 MQTT 연결이 비정상적으로 유지되지 못했다.

는 사실입니다.

실제 물리적 원인은 추가 진단이 필요합니다.


15장 MQTT 5의 Will Delay를 활용할 수도 있다#

Network가 잠깐 흔들렸다고 하겠습니다.

Disconnect
↓
1초 후 Reconnect

즉시 OFFLINE을 Publish하면 관제 화면이:

ONLINE
↓
OFFLINE
↓
ONLINE

으로 짧게 깜빡일 수 있습니다.

MQTT 5에서는 Will Delay Interval을 이용해 Will Message 발행을 일정 시간 지연하도록 설계할 수 있습니다.

개념적으로:

Connection 끊김
↓
Will Delay
↓
그 안에 Reconnect?
├─ Yes → 상황에 따라 Will 발행 억제
└─ No  → Will 발행

짧은 Network 흔들림을 실제 장애와 구분하는 데 활용할 수 있습니다.

다만 Session 설정과 Broker·Client의 MQTT 5 지원 여부를 함께 확인해야 합니다.


16장 Retained Message도 오래 남을 수 있다#

Device가 다음 값을 Retain으로 남겼다고 하겠습니다.

{
  "status": "offline"
}

장비가 철거된 뒤에도 Retained 상태가 남아 있다면 신규 Dashboard에서 계속:

Gate 01
OFFLINE

으로 표시할 수 있습니다.

실제로는 존재하지 않는 장비일 수도 있습니다.

따라서 Device Lifecycle도 관리해야 합니다.

등록

운영

점검

비활성화

철거

와 MQTT 상태를 연결할 필요가 있습니다.


17장 Retained Message를 제거해야 할 때도 있다#

해당 Topic에 더 이상 Retained 상태를 남길 필요가 없다면 Retained Message를 제거하는 절차가 필요할 수 있습니다.

운영에서는:

장비 폐기

Topic 변경

잘못된 Retained Message

Test Data 제거

같은 상황이 발생합니다.

Retained Message의 삭제 방법은 사용하는 MQTT Version과 Client Tool, Broker 운영 정책을 확인해야 합니다.

중요한 것은 Retain을 한 번 사용하면 Lifecycle 관리도 함께 필요하다는 점입니다.


18장 Topic은 Device 상태 관리가 쉬운 구조로 만든다#

다음과 같은 구조를 사용할 수 있습니다.

parking/site01/gate01/status

parking/site01/gate02/status

parking/site01/gateway01/status

또는 기능을 더 분리할 수 있습니다.

parking/site01/gate01/presence

parking/site01/gate01/health

parking/site01/gate01/alarm

이렇게 하면 의미가 명확해집니다.

예:

presence
→ MQTT 연결·생존 상태

health
→ Device 내부 상태

alarm
→ 장애 Event

개인적으로는 대규모 시스템이라면 단순한 status 하나에 모든 의미를 넣기보다 Presence와 Health를 분리하는 구조가 관리하기 좋습니다.


19장 Retain과 QoS는 별개다#

다음 Message:

{
  "status": "online"
}

에:

QoS 1
Retain true

를 동시에 사용할 수 있습니다.

두 설정의 역할은 다릅니다.

QoS
→ Message 전달 방법

Retain
→ Broker가 마지막 Retained Message를 보관할지

따라서:

Retain = QoS

가 아닙니다.

Last Will 역시 별도의 Topic, Payload, QoS, Retain 설정을 가질 수 있습니다.


20장 상태 Topic에 QoS 1이 항상 정답인 것은 아니다#

상태 Topic에 무조건 QoS 1을 사용해야 하는 것은 아닙니다.

예를 들어 매우 자주 갱신되는 상태이고 최신 값만 중요하다면 QoS 0을 선택할 수도 있습니다.

반대로 장비 Online·Offline 변화가 중요하고 Network 품질이 불안정하다면 QoS 1을 검토할 수 있습니다.

판단 기준은:

상태 중요도

발행 빈도

중복 허용 여부

Network 품질

Broker 부하

장비 성능

입니다.

상태 Message는 무조건 QoS 1 같은 규칙보다는 현장 요구사항을 기준으로 선택해야 합니다.


21장 상태 Message에는 Timestamp와 식별자를 넣는 것이 좋다#

예:

{
  "deviceId": "gate01",
  "status": "online",
  "timestamp": "2026-09-24T15:30:00+09:00"
}

추가로:

{
  "deviceId": "gate01",
  "status": "online",
  "bootId": "boot-a918",
  "timestamp": "2026-09-24T15:30:00+09:00"
}

처럼 Boot ID 또는 Session 수준의 식별자를 둘 수도 있습니다.

이렇게 하면:

이 Message가 현재 Boot에서 나온 것인가?

오래된 상태인가?

재접속 이후 상태인가?

를 판단하는 데 도움이 될 수 있습니다.


22장 상태 위조를 막으려면 Topic ACL이 필요하다#

공격자가 다음 Topic에 Publish할 수 있다고 생각해보겠습니다.

parking/site01/gate01/status

그리고:

{
  "status": "online"
}

을 임의로 보내면 실제 Offline 장비가 정상처럼 보일 수 있습니다.

반대로:

{
  "status": "offline"
}

을 보내 운영자에게 허위 장애를 만들 수도 있습니다.

따라서 Broker에서는:

Gate01 Credential
↓
Gate01 관련 Topic만 Publish

Monitoring Server
↓
Status Topic Subscribe

일반 Client
↓
Publish 금지

같은 ACL을 두는 것이 중요합니다.


23장 Retain과 Last Will 장애를 어떻게 진단할까#

신규 Subscriber가 상태를 받지 못한다#

확인:

Publish할 때 Retain이 설정됐는가?

Topic이 정확한가?

ACL이 허용하는가?

Retained Message가 실제 존재하는가?

Device가 죽었는데 OFFLINE이 안 나온다#

확인:

Will이 연결 시 등록됐는가?

Will Topic이 맞는가?

정상 DISCONNECT였는가?

Keep Alive는 얼마인가?

Broker가 아직 연결을 살아 있다고 판단하는가?

관제 화면이 Offline과 Online을 반복한다#

확인:

Network Flapping

Keep Alive

Reconnect

Will Delay

Wi-Fi·Cellular 품질

을 확인합니다.


오래전에 철거한 장비가 계속 나타난다#

확인:

Retained Message

Device Registry

Topic 삭제 정책

Monitoring DB

를 확인합니다.


24장 주차관제 상태 흐름 예제#

Gate 01이 정상적으로 연결됐다고 하겠습니다.

CONNECT
↓
Will 등록

Topic
parking/site01/gate01/presence

Payload
OFFLINE

연결 성공 후:

PUBLISH

parking/site01/gate01/presence

ONLINE

Retain = true

Broker의 마지막 상태:

ONLINE

Network가 끊깁니다.

Connection Lost
↓
Broker 감지
↓
Last Will
↓
OFFLINE

Will도 Retained Message로 설정했다면 마지막 상태:

OFFLINE

장비가 다시 연결됩니다.

Reconnect
↓
ONLINE Publish
↓
Retained Message 갱신

이 구조가 MQTT Presence 관리의 대표적인 형태입니다.


25장 Retained Message와 Last Will 비교#

항목 Retained Message Last Will
목적 마지막 상태 보관 비정상 Disconnect 알림
누가 Publish하는가 일반적으로 Client Broker가 대신 Publish
동작 시점 일반 Publish 시 비정상 연결 종료 감지 시
신규 Subscriber 마지막 Retained 상태 즉시 수신 가능 Retain 설정 시 결과 상태 수신 가능
대표 활용 현재 상태 Offline 감지
QoS 별도 지정 가능 별도 지정 가능
Retain 기능 자체 Will에도 Retain 설정 가능

핵심은:

Retain
→ 마지막 값을 기억한다.

Last Will
→ Client가 갑자기 사라지면 대신 말한다.

입니다.


26장 흔히 하는 잘못된 판단#

Retained Message가 ONLINE이면 지금도 Online이다#

반드시 그렇지 않습니다.

오래된 Message일 수 있으므로 Timestamp, Connection 상태와 Heartbeat 등을 함께 판단해야 합니다.

Last Will은 장비 전원이 꺼졌다는 뜻이다#

아닙니다.

MQTT 연결이 비정상적으로 종료됐다는 의미이며 실제 원인은 Network나 Application 장애일 수도 있습니다.

정상 DISCONNECT에서도 Last Will이 항상 발행된다#

일반적으로 그렇지 않습니다.

정상 Disconnect와 비정상 연결 종료를 구분해야 합니다.

Retain은 Message History 저장 기능이다#

아닙니다.

일반적으로 Topic의 마지막 Retained 상태를 제공하는 기능입니다.

Retain을 쓰면 Session도 자동 유지된다#

아닙니다.

Retained Message와 MQTT Session은 별개의 기능입니다.

Online·Offline 두 상태만 있으면 충분하다#

실제 산업 시스템에서는 Network Presence와 Device Health를 분리해야 할 수 있습니다.


27장 MQTT 장비 상태 설계 체크리스트#

□ Presence Topic을 정의했는가?

□ Health Topic을 분리할 필요가 있는가?

□ ONLINE Message를 언제 Publish하는가?

□ ONLINE에 Retain을 사용할 것인가?

□ Last Will Topic을 정의했는가?

□ Last Will Payload를 표준화했는가?

□ Will에도 Retain을 적용할 것인가?

□ Keep Alive 값은 적절한가?

□ Offline 감지 허용 시간은 얼마인가?

□ MQTT 5 Will Delay가 필요한가?

□ Timestamp를 포함하는가?

□ 오래된 Retained 상태를 구분할 수 있는가?

□ Device ID가 명확한가?

□ 장비 철거 시 Retained 상태 제거 정책이 있는가?

□ QoS를 요구사항에 따라 선택했는가?

□ Topic ACL을 적용했는가?

□ TLS를 사용하는가?

□ Broker 재시작 후 Retained 상태를 검증했는가?

□ Reconnect 후 ONLINE 상태를 다시 갱신하는가?

□ MQTT 연결 상태와 실제 Device Health를 구분하는가?

28장 자기 점검#

Retained Message란 무엇인가#

Broker가 특정 Topic의 마지막 Retained Message를 보관하고 새로운 Subscriber에게 전달할 수 있도록 하는 기능입니다.

Last Will은 언제 사용되는가#

Client가 Broker와 비정상적으로 연결을 잃었을 때 Broker가 미리 등록된 Message를 대신 Publish하는 데 사용합니다.

정상 Disconnect에서도 Last Will이 발행되는가#

일반적인 정상 Disconnect에서는 Will이 비정상 종료 알림처럼 발행되지 않습니다.

Retained ONLINE Message만으로 현재 장비가 Online이라고 판단해도 되는가#

안 됩니다. Message가 오래된 것일 수 있으므로 Timestamp, MQTT Connection, Heartbeat 등 다른 상태도 함께 확인하는 것이 좋습니다.

Retain과 QoS는 같은 기능인가#

아닙니다. QoS는 전달 수준이고 Retain은 마지막 Message 보관 기능입니다.

29장 이 글을 마치며#

MQTT Device 상태 관리는 다음 두 기능을 구분하면 이해하기 쉽습니다.

Retained Message
→ 마지막 상태 기억

Last Will
→ 비정상 연결 종료 알림

두 기능을 함께 사용하면:

Device 연결
↓
ONLINE Retain

정상 운영
↓
Network 장애

Broker 감지
↓
Last Will

OFFLINE Retain
↓
Device 재접속

ONLINE Retain

과 같은 상태 관리 구조를 만들 수 있습니다.

하지만 실제 관제 시스템에서는 여기에서 한 단계 더 생각해야 합니다.

MQTT 연결 상태
≠
Application 정상 상태
≠
Sensor 정상 상태
≠
실제 장비 물리 상태

각각 다른 상태입니다.

특히 다음 다섯 가지를 기억하면 됩니다.

Retained Message는 새로운 Subscriber에게 마지막 알려진 상태를 제공하는 기능이지 전체 Message History를 저장하는 기능이 아닙니다.

Last Will은 Client가 비정상적으로 연결을 잃었을 때 Broker가 대신 Message를 Publish하도록 미리 등록하는 기능입니다.

Retained ONLINE이 존재한다고 지금 장비가 살아 있다는 뜻은 아니므로 Timestamp와 Heartbeat, 실제 연결 상태를 함께 확인해야 합니다.

장비가 Offline이라는 사실과 장비 Hardware가 고장났다는 사실도 같지 않으므로 Network·Application·Device Health를 분리해서 판단해야 합니다.

실무에서는 Presence·Health·Alarm을 분리하고 Topic ACL과 TLS를 적용하면 상태 관리와 보안 정책을 훨씬 명확하게 만들 수 있습니다.

결국 Retain과 Last Will을 제대로 활용한다는 것은 단순히 online, offline 문자열을 보내는 것이 아닙니다.

장비가 연결되고, 사라지고, 다시 연결되는 전체 Lifecycle을 Broker가 일관되게 표현하도록 설계하고, 관제 시스템이 오래된 상태와 실제 현재 상태를 구분할 수 있도록 만드는 것이 핵심입니다.

이 페이지의 목차