"command는 묻고 답하는 거야. 이벤트는 아무도 안 물어봤는데 하는 공지고."
당겨오는 게 아니라 밀어주는 것
가끔 코어한텐 프론트엔드가 물어보지도 않은 소식이 생겨. 다운로드가 끝났다든지, 지켜보던 파일이 바뀌었다든지, 타이머가 한 번 돌았다든지, 트레이 메뉴가 눌렸다든지. 그걸 command로 계속 물어보는 건 낭비야. 대신 코어가 이벤트를 emit하고 프론트엔드가 listen해. app.emit("name", payload)가 모든 웹뷰에 방송하고, 프론트엔드의 listen("name", handler)(@tauri-apps/api/event에 있어)가 payload랑 함께 하나씩 받아. payload는 직렬화되는 값이면 뭐든 되고, command 데이터처럼 serde가 실어 보내.
다 뿌릴까, 하나만 찍을까
emit은 모두한테 보내. 창이 여럿인데 하나만 들어야 하면 emit_to("window-label", "name", payload)로 특정 웹뷰만 찍어. 이벤트는 반대 방향으로도 흘러 — 프론트엔드가 emit하고 Rust가 듣는 것도 돼 — 근데 프론트엔드에서 코어로 뭘 요청할 땐 보통 command를 쓰는 게 나아(반환값이랑 에러 처리를 공짜로 받으니까). 이벤트는 던져놓고 잊는 공지에 남겨둬.
리스너는 반드시 치워
listen은 리스너를 떼는 함수를 돌려줘. 컴포넌트에선 effect에서 등록하고 cleanup에서 그 함수를 불러 — 안 그러면 컴포넌트가 마운트될 때마다 핸들러가 겹겹이 쌓여. 메모리 누수에 같은 이벤트가 두 번 세 번 처리되는 고전 버그가 그거야. 딱 한 번만 처리하고 싶은 이벤트엔 once를 써.