장군께서는
나의 죽음을 적에게 알리지마라
라고 하셨지만, client는 자신의 죽음을 server 에게 알려야 한다.
이것을 LWT(Last will and testament) 라고 하며 고급지게 유언 이라 한다.
우리는 죽을 때 말(言)을 남기는데, 서양은 윌(Will)을 남기나 보다.
장군의 죽음을 왜군이 알아선 안되지만,
server는 client 상태를 알아야 한다.
왜?
server가 talk을 보낼 때(전파할 때) 이 톡을 받는 주체는 client의 mqtt_connect이다.
client의 mqtt_connect이 살아 있는지, 아니면 죽었는지에 따라 pub할지 push할지 결정하기 때문이다.
client의 mqtt_connect가 죽었는지, 살았는지 알려면 어떡해해야할까?
will이 그 답이다.
client의 mqtt_connect 가 죽으면 boker가 client의 will을 보낼 것이다.
server는 이 will을 수신하고 있다가, 어느 client가 죽었는지? 살았는지 판단하면 된다.
상태 | 설명 |
---|---|
active | 😁 앱에서 mqtt_connect 가 살아 있을 때 |
inactive | 😅 mqtt_connect 가 죽었을 때 |
uninstall | 😰 슬프게도 앱을 삭제했을 때 |
mqtt_connect 생사 여부와 별개로 앱에서 앱 Noti 띄우는 건 또 다른 로직이다.
client 앱에서는 mqtt_connect 가 살아 있고, foreground 상태이며, 현재 message와 동일 room 에 있다면 앱 Noti에 등록하지 않고 톡방에만 쏘면 된다.
그 이외에는 Noti에 띄워야 한다.
앱 개발자라면 이 말을 이해할 것이다.
상태 | 설명 |
---|---|
App.state == Foreground && room == message.room | room 화면에 talk 내용을 쓰면 된다. |
App.state == Foreground && room != message.room | Noti에 등록 |
App.state == Background || App을 실행하지 않은 경우 | Noti에 등록 |
lwt의 기본 개념은 이렇다.
죽기 전 lwt(유언)을 써 놓고, 내가 죽으면 내 죽음에 관심있는 자(여기선 server겠지)에게 뿌리라고 borker에게 부탁하는거다.
즉 client가 mqtt 연결할 때 lwt를 함께 등록하는 거다.
nodejs mqtt에서는 다음과 같다.
client에 추가하는 코드는 단순한다. 접속할 때 나의 will을 등록하면 된다.
요렇게 해 놓으면 connection이 끊어지면 broker(브로커라기보단 변호사네😏) 가 나의 죽음에 관심있는(sub하고 있는) 이들한테 이를 뿌려준다.
const user_id = process.argv[2]; //'client1';
const client = mqtt.connect({
host: 'localhost',
will: {
topic: 'server/die',
payload: JSON.stringify({ data: { id: user_id } })
}
});
내 죽음에 관심 있는 자들이 여럿 있겠지만 😂, server가 가장 관심이 있을 것이다.
왜냐하면 이를 DB에 저장하고 pub할지 push할지 결정해야 하기 때문이다.
따라서 서버 토픽인 server/die로 이름 짓자.
이제 서버가 server/die topic도 sub하도록 추가하면 된다.
server.on("connect", () => {
server.subscribe(["server/login", "server/talk", "server/die"]);
});
그 다음 server/die가 들어왔을 때 처리하는 함수만 짜 넣으면 끝.
server.on("message", (topic, message) => {
console.log('received: ', topic, JSON.parse(message));
if (topic.endsWith('/login')) process_login(message);
else if (topic.endsWith('/talk')) process_talk(message);
else if (topic.endsWith('/die')) process_die(message);
});
...
function process_die(message) {
let json = JSON.parse(message);
mysql_conn.sql(UPDATE_USER_STATE, [json.data.id,'inactive'], function(err, results, fields) {
...
}
}
서버가 있어 너무 행복😁하지 아니한가?
active는 따로 로직을 뺄 필요도 없다.
active는 로그인 시 active로 DB에 Update하도록 추가하면 된다.
uninstall은 앱 삭제 이벤트 받아 Update하면 된다.
녜. 저도 서버가 있어 행복하고 싶네요.
조금 더 봐야할듯요.