4편까지 최신 값을 알려면 물어야 했다. 1초마다 묻거나, 사람이 새로고침하거나.
구독한다
client.onResourceUpdated((uri) {
// The notification says only that it changed. Read to learn what to.
seen.add(uri);
stdout.writeln('notified: $uri');
});
await client.subscribeResource('desk://waiting');
그리고 값이 바뀌게 만들어 본다.
await client.callTool('desk.admit', {'count': 1});
subscribed to desk://waiting
notified: desk://waiting
after the notification, reading gives {waiting: 2}
notifications received: 1
알림은 uri 만 나른다
핸들러가 받는 건 uri 하나다. 몇 명이 됐는지는 안 온다. 서버 6편에서 값을 안 싣는 이유를 다뤘고, 받는 쪽에서는 그게 읽어야 한다는 뜻이 된다.
final now = await client.readResource('desk://waiting');
한 번 더 왕복하는 게 손해 같지만, 이게 항상 옳다. 알림이 몇 개 오든 순서가 어떻든, 읽은 시점의 값이 최신이기 때문이다.
폴링의 진짜 문제
폴링을 안 쓰는 이유로 대개 자원을 든다. 1초마다 서버를 두드리면 낭비다.
그건 부차적이다. 진짜 문제는 두 번 묻는 사이를 못 본다는 것이다.
09:00:00 폴링 → waiting 3
09:00:00.4 두 명 입장 → waiting 1
09:00:00.7 한 명 도착 → waiting 2
09:00:01 폴링 → waiting 2
화면은 3에서 2로 갔다. 1이었던 순간을 못 봤다. 최종값만 필요하면 상관없지만, "0이 되면 알림" 같은 규칙이 있으면 그 규칙은 안 발동한다.
간격을 줄여도 사라지지 않는다. 좁아질 뿐이다. 그리고 좁힐수록 낭비가 는다.
끝나면 푼다
await client.unsubscribeResource('desk://waiting');
화면이 닫히면 구독을 푼다. 안 풀면 서버가 없는 상대에게 계속 보낸다.
실보드 편의 ESP32 가 이걸 화면 정의 안에 넣어 뒀다 — onReady 에 구독, onDestroy 에 해제. 생명주기가 화면에 적혀 있으면 클라이언트가 잊을 수 없다.