: 정보기술과 전기통신 및 관련 분야에서 채널에 대한 정상적인 통신이 시작되기 전에 두 개의 실체 간에 확립된 통신 채널의 변수를 동적으로 설정하는 자동화된 협상 과정, 채널의 물리적인 확립이 잇따르며, 정상적인 정보 전송 이전에 이루어진다.
SYN: Synchronize sequence number, 연결 시작 요청ACK: Acknowledgement, 응답 확인FIN: Finish, 연결 종료 요청
클라이언트/서버 간의 연결을 수립할 때 사용되는 TCP 3 way Handshaking의 순서는 아래와 같다.
1. 클라이언트는 서버에게 접속을 요청한다. SYN
2. 클라이언트로부터 SYN 요청을 받은 서버는 클라이언트에게 요청을 수락한다 보낸다. SYN/ACK
3. 클라이언트가 서버에게 다시 ACK를 보내게 되면 연결이 이루어진 것이며, 실질적인 데이터가 오간다.
이때, 서버와 클라이언트는 신호를 주고받는 과정 속에서 '상태(State)'가 변하게 된다.
SYN을 보낸 후, 서버로부터 다시 SYN/ACK를 받기 전까지 SYN-SENT 상태가 된다.SYN을 받았을 때 SYN-RECEIVED 상태가 된다. 그리고 다시 클라이언트에게 SYN/ACK를 보낸다.SYN/ACK를 받은 클라이언트는 ESTABLISHED 상태가 된다. => '연결이 수립되었다'ACK를 보낸다. 그러면 ACK를 받은 서버도 ESTABLISHED 상태가 된다.
클라이언트/서버 간의 연결을 해제할 때 사용되는 TCP 4 way Handshaking의 순서는 아래와 같다.
1. 클라이언트가 서버에게 종료 요청을 보낸다. FIN
2. 서버가 클라이언트의 종료 요청을 받아들인다. 그리고 그에 대한 응답을 보낸다. ACK ("일단 알겠다")
3. 서버는 연결을 종료할 준비가 끝나면 연결을 해제할 준비가 끝났다는 뜻으로 FIN을 클라이언트에게 보낸다.
4. 클라이언트는 서버로부터 FIN을 받을 것이며, 연결 해제의 준비가 끝났음을 확인했다는 뜻으로 다시 ACK를 보낸다.
FIN을 보낸 클라이언트는 FIN_WAIT 상태가 된다.FIN을 받은 서버가 ACK을 보내고 나서 자신의 통신을 끝낼 때까지 CLOSE_WAIT 상태가 된다.FIN을 보내고, 이때 서버는 LAST_ACK 상태가 된다.FIN을 받은 클라이언트는 ACk를 보내는데 이때 TIME_WAIT 상태로 바뀌고, 이 ACK을 받은 서버는 CLOSED 상태가 된다.서버에서 전송한 패킷이 문제가 발생하여 FIN보다 늦게 도착하는 상황이 발생할 수도 있다.
-> 이 때 FIN을 받은 클라이언트가 ACK를 보낸 직후 통신을 끊어버리면 그 데이터가 유실될 수 있다. 따라서 클라이언트는 서버로부터 FIN을 받은 후 일정 시간(Default : 240초) 동안 세션을 열어 두고, 잉여 패킷이 도착할 수 있도록 한다.
=> 즉 클라이언트는 TIME_WAIT 상태로 일정 시간 기다렸다가 CLOSED 상태로 바뀌게 되는 것이다.
"Quality of Service"의 약자로, 전달되는 Application Message의 신뢰성을 보장하는 레벨이다.
PUBLISH 제어 패킷에 포함되어 전송되며, MQTT는 이 규격을 사용하여 반드시 전달되어야 하는 메시지의 전달을 보장한다.Client와 Server(Broker)는 각각 자신이 처리할 수 있는 최대 QoS 레벨을 가지고 있다.

최대 1번 전달을 보장하는 구조
Packet ID 없음: QoS 0에서는 메시지가 신뢰성 있는 전송을 보장하지 않기 때문에, 패킷 식별자(Packet ID)가 필요하지 않다!
- Packet ID는 QoS 1과 QoS 2에서 메시지의 전달 상태를 추적하고 관리하는 데 사용

최소 1번 이상의 메시지 전송을 보장하는 방식
PUBACK 메시지를 발신자에게 전송하면서 메시지 전달이 완료됨PUBACK 메시지로 수신 측이 메시지를 받았는지 확인 가능다만,
PUBACK단계에서 네트워크 이슈 등으로 지연이 발생되었을 때 -> 발신자(Publisher)는 응답이 없기에 메시지를 재전송할 수 있다.
- 이때 수신자가 메시지를 구독자에게 이미 발송하고 삭제한 상태라면, 수신자는 메시지 중복여부를 판별할 수 없기에 구독자에게 동일한 메시지를 다시 보낼 수 있다.
- 이렇기에 QoS 1은 메시지가 미전송되는 상황은 막을 수 있으나, 메시지가 중복으로 전달될 가능성이 존재한다.

가장 높은 QoS 레벨
: QoS 1에서는 발신자(Publisher)는 메시지 전송 후 응답을 받아 메시지 전송 성공여부를 판단
: QoS 2에서는 4-way HandShaking을 사용해 정확히 한번의 메시지 전송 보장
PUBREC 단계에서 지연이 발생해 발신자가 메시지를 재전송한다 하더라도, 수신자는 이전에 받은 메시지를 가지고 있기에 메시지를 구독자에게 재전송 XPUBCOMP 단계에서 지연이 발생했다 하더라도 이미 이전에 PUBREC를 받음으로써 메시지를 구독자에게 보냈음을 확인했기에 구독자에게 메시지 재전송되는 상황 XQoS 2는 처리에 소모되는 리소스가 크지만, 이러한 방식으로 정확히 1번 구독자가 메시지를 받게 되는 것을 보장한다.
-> 메시지 중복 전달 시 문제가 발생되는 데이터의 경우에 사용 가능
패킷 ID의 생성 및 관리:
- 동적 생성: 패킷 ID는 MQTT 클라이언트(발행자 또는 구독자)에 의해 동적으로 생성된다.
- 일반적으로 패킷 ID는 순차적으로 증가하는 숫자를 사용하여 관리된다.
- 유니크한 ID: 각 패킷 ID는 활성 연결 내에서 유니크해야 한다.
- 이는 메시지가 올바르게 추적되고 관리될 수 있도록 보장한다.
- 재사용: 일반적으로 패킷 ID는 메시지가 완전히 처리되고, 관련된 모든 확인 응답이 수신된 후에 재사용될 수 있다.
MQTT 메시지의 발행과 구독은 Topic을 기준으로 이루어진다.
Topic은 Level Seperator(/)를 이용하여 아래와 같은 형태로 계층적으로 구성 가능하다.

Level Seperator로 구분된 각각의 계층은 Topic Level이라고 한다.
구독자는 Topic Filter를 사용하여 Topic을 구독한다.
Topic Filter에는 wildcard 문자가 포함될 수 있으며, 구독자는 이 wildcard 문자를 이용하여 다수의 Topic을 한 번에 Subscribe할 수 있디.
사용가능한 wildcard 문자와 의미를 알아보자.
1) # Multi Level wildcard
: 여러 단계의 Topic Level을 대체할 수 있다. 단독으로 쓰이거나 Topic Filter의 마지막 Level에 위치 가능하다.

2) + Single Level wildcard
: 한 단계의 토픽 레벨을 대체할 수 있다. 단독으로 쓰이거나 Topic Filter 내의 특정 Topic Filter에 위치 가능하다.

Topic 중에는 $로 시작하는 특수 목적의 Topic이 있다.
이 Topic은 읽기 전용 Topic이며, 시스템에 의해 예약된 특수한 목적의 Topic이기에 클라이언트에서는 사용할 수 없다!
$SYS/ Topic이 있다.$SYS/ Topic은 서버의 고유 정보를 모니터링하기 위해 사용된다.$SYS/ 의 내용은 규격상 정해져 있지 않으며, 기본적인 지침은 있으며 아래와 같다.
Topic Name과 Topic Filter는 작성 시 지켜여 할 기본적인 규칙들이 있으며, 내용은 아래와 같다.
1. Topic Name과 Topic Filter는 최소한 1글자보다 길어야 한다.
2. Topic Name과 Topic Filter는 대소문자를 구분한다.
3. 공백 문자의 사용은 가능하다.
4. Null (Unicode U+0000) 문자는 포함할 수 없다.
5. Maximum Topic 길이는 65535 bytes이다.
6. 앞, 뒤에 /가 붙으면 전혀 다른 Topic Name 혹은 Topic Filter가 된다.
CONNECT 타입의 MQTT 제어 패킷의 경우, 'Connect Flags'라는 8bit(1Byte)의 정보가 Variable Header에 포함되어 있다.
8bit로 구성된 Flags 정보 내에는 아래와 같이 MQTT 연결과 관련된 각종 설정 값들이 기록되어 있다.

서버와 클라이언트는 안정적이 메시지 송/수신을 위해 Session 상태를 저장하고 있다.
Clean Session은 재연결 시, 이전 세션(Persistence session)을 사용할지를 설정하는 것이다.
0으로 설정하여 연결 요청을 하면 저장되어 있는 세션을 찾아 재활용하고, 1로 설정하여 요청하면 신규 세션을 생성하여 사용한다.또한 Clean Session 설정은 메시지 재전송 (Message delivery retry)과도 연관되어 있다.
0으로 서버와 재연결되면, 클라이언트와 서버는 각각 응답을 받지 못한 패킷을 동일한 Packet ID로 재전송해야 한다.MQTT에서 클라이언트는 자신이 접속 종료되었을 때 특정 Topic을 발송하라고 서버에 등록할 수 있다. 이것을 Will Message라고 한다.
1로 설정하여 서버에 연결해야 한다.Will Message 전송 시에도 QoS 레벨과 Retain 설정을 할 수 있으며, 이 값은 Connect Flags 내의 Will QoS, Will Retain에 설정된다.
1로 설정될 경우, Payload에 User Name, Password 필드를 사용한다.
0이면 Password Flag도 0이다.CONNECT 타입의 MQTT 제어 패킷에 포함되어 전달되는 정보이며, 16bit를 사용한다.
기본적으로 클라이언트는 Keep Alive Interval이 지나기 전의 메시지 전송을 보장해야 한다.
PINGREQ, PINGRESP (클라이언트와 서버 간의 연결 상태를 유지하고 확인하기 위해 사용되는 제어 패킷)PINGREQ (Ping Request)는 클라이언트가 서버에 보내는 패킷
- 이 패킷은 클라이언트가 아직 활성 상태임을 서버에 알리며, 서버가 반응하도록 요구
- 클라이언트는 설정된 keep-alive 시간 동안 어떠한 다른 MQTT 메시지도 서버에 보내지 않았을 때
PINGREQ를 보내서 연결이 여전히 유효한지를 확인
PINGRESP (Ping Response)는 서버가 PINGREQ를 받고 난 후 클라이언트에게 보내는 응답 패킷
- 서버가 아직 활성 상태이며, 클라이언트의 PINGREQ를 성공적으로 수신했음을 알린다
- 클라이언트는 이
PINGRESP를 받음으로써 서버와의 연결이 여전히 활성화되어 있고, 메시지 교환을 계속할 수 있음을 확인
서버는 Keep Alive 시간의 1.5배 내에 아무런 패킷이 들어오지 않으면 클라이언트와의 연결이 끊겼다고 판단하고, Will 메시지 전송 등의 절차를 수행할 수 있다.
출처: 블로그 + ChatGPT
MQTT란?
MQTT란 무엇인가?
HiveMQ
OSI 7계층
MQTT 프로토콜이란
MQTT 프로토콜 분석 (1)
MQTT 프로토콜 분석 (2)