C# WPF 에서 MQTTnet 5 로 MQTT 서버와 클라이언트 구성하기
C# WPF 에서 MQTTnet 5 로 MQTT 서버와 클라이언트 구성하기
## MQTT란 무엇인가? MQTT(Message Queuing Telemetry Transport) 는 사물인터넷(Iot) 환경에서 널리 사용되는 경량 메시지 프로토콜 입니다.
처음에는 위성 통신용으로 개발되었으며, 지금은 스마트홈, 센서 네트워크, 원격제어 등 다양한 분야에서 활용됩니다.
## 특징
| 특징 | 설명 |
|---|---|
| 경량성 | 매우 가볍고 적은 네트워크 트래픽 사용 |
| Pub/Sub 모델 | 발행(Publish) / 구독(Subscribe) 구조 |
| 지속 연결 | 클라이언트와 브로커 간 TCP 기반 연결 유지 |
| Qos 지원 | 메시지 전송 품질 보장 (0, 1, 2 단계) |
| 보안 | TLS, 인증 기반 통신 가능 |
## MQTT 통신 구조
1
2
3
4
5
6
7
8
9
10
11
+------------------------+
| MQTT Broker | ◀── 중개자 역할 (서버)
+------------------------+
▲ ▲
│ │
+-----------+ +-----------+
| Publisher | |Subscriber|
+-----------+ +-----------+
- Publisher: 특정 토픽(topic)에 메시지를 발행
- Subscriber: 원하는 토픽을 구독하고 메시지를 수신
우리가 만들 예제
WPF 앱에서 MQTT 브로커를 직접 실행하고, 앱 내부에서 Publish / Subscribe도 함께 동작시켜 다음을 확입하니다:
- 메시지를 전송(Publish)
- 구독자가 메시지를 수신(Subscribe)
- WPF UI와 연동하여 동작 확인
## 개발 환경
- WPF (.Net 6 이상)
- MQTTnet 5.0.1.1416
1
2
NuGet 설치 명령어:
PM> Install-Package MQTTnet -Version 5.0.1.1416
## 예제 코드 - UI (MainWindow.xaml)
1
2
3
4
5
6
7
8
<Window x:Class="MqttTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="MQTT Demo" Height="200" Width="400">
<StackPanel Margin="20">
<TextBox x:Name="MessageTextBox" Height="30" Margin="0,0,0,10" />
<Button Content="메시지 보내기" Click="Send_Click" Height="30"/>
</StackPanel>
</Window>
## 예제 코드 - 로직 (MainWindow.xaml.cs)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using MQTTnet;
using MQTTnet.Protocol;
using MQTTnet.Server;
using System.Text;
using System.Windows;
namespace MqttTest
{
public partial class MainWindow : Window
{
private MqttServer mqttServer;
private IMqttClient subscriberClient;
private IMqttClient publisherClient;
public MainWindow()
{
InitializeComponent();
StartMqttServerAndClients();
}
private async void StartMqttServerAndClients()
{
await StartMqttServerAsync();
await StartSubscriberAsync();
await StartPublisherAsync();
await Task.Delay(1000); // subscriber 연결 대기
await PublishTestMessageAsync("test/topic", "Hello from Publisher");
}
private async Task StartMqttServerAsync()
{
var options = new MqttServerOptionsBuilder()
.WithDefaultEndpoint()
.Build();
var serverFactory = new MqttServerFactory();
mqttServer = serverFactory.CreateMqttServer(options);
await mqttServer.StartAsync();
}
private async Task StartSubscriberAsync()
{
var clientFactory = new MqttClientFactory();
subscriberClient = clientFactory.CreateMqttClient();
subscriberClient.ApplicationMessageReceivedAsync += e =>
{
string topic = e.ApplicationMessage.Topic;
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
Dispatcher.Invoke(() =>
{
MessageBox.Show($"[SUBSCRIBER] 수신된 메시지: {payload} (Topic: {topic})");
});
return Task.CompletedTask;
};
var options = new MqttClientOptionsBuilder()
.WithTcpServer("127.0.0.1", 1883)
.WithClientId("subscriber-client")
.Build();
await subscriberClient.ConnectAsync(options);
await subscriberClient.SubscribeAsync("test/topic");
}
private async Task StartPublisherAsync()
{
var clientFactory = new MqttClientFactory();
publisherClient = clientFactory.CreateMqttClient();
var options = new MqttClientOptionsBuilder()
.WithTcpServer("127.0.0.1", 1883)
.WithClientId("publisher-client")
.Build();
await publisherClient.ConnectAsync(options);
}
private async Task PublishTestMessageAsync(string topic, string message)
{
var appMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(Encoding.UTF8.GetBytes(message))
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
.Build();
await publisherClient.PublishAsync(appMessage);
}
private async void Send_Click(object sender, RoutedEventArgs e)
{
string topic = "test/topic";
string payload = MessageTextBox.Text;
if (string.IsNullOrWhiteSpace(payload))
{
MessageBox.Show("메시지를 입력하세요.");
return;
}
var appMessage = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(Encoding.UTF8.GetBytes(payload))
.WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
.Build();
await publisherClient.PublishAsync(appMessage);
}
}
}
## 실행 결과
- 앱 실행 시 MQTT 브로커가 백그라운드에서 실행됨
- Publish 와 Subscribe 가 자동 연결됨
- 메시지를 보내면
MessageBox로 수신 확인 가능
## 마무리 (외부 MQTT 브로커와 연동하기) 지금까지는 MQTTnet 라이브러리를 이용해 WPF 앱 내부에서 브로커를 직접 실행했지만,
실제 현업 환경에서는 전용 MQTT 브로커를 따로 운영하는 경우가 대부분입니다.
대분적인 MQTT 브로커는 다음과 같습니다:
| 브로커 | 특징 |
|---|---|
| Mosquitto | 가볍고 빠르며 설치 쉬움 (IoT에서 가장 많이 사용됨 |
| RabbitMQ + MQTT 플러그인 | 고성능 메시지 브로커, MQTT뿐 아니라 AMQP 등 지원 |
| EMQX | 고급 분산 MQTT 브로커, 대규모 서비스에 적합 |
| HiveMQ | 상업용 중심, 웹 UI 및 클라우드 지원 강력 |
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.