"command는 질문과 답이야. 이벤트는 아무도 안 물어본 공지야."
pull이 아니라 push
가끔 코어한텐 프론트엔드가 요청 안 한 소식이 있어: 다운로드 끝남, 감시하던 파일 바뀜, 타이머 틱, 트레이 메뉴 클릭됨. 그걸 command로 폴링하는 건 낭비야. 대신 코어가 이벤트를 emit하고 프론트엔드가 listen해. app.emit("name", payload)가 모든 웹뷰에 방송하고, 프론트엔드의 listen("name", handler)(@tauri-apps/api/event에서)가 각각을 payload랑 받아. payload는 직렬화 가능한 값 뭐든, command 데이터처럼 serde로 인코딩돼.
방송 vs 타깃
emit은 모두한테 보내. 창이 여럿이고 하나만 들어야 하면 emit_to("window-label", "name", payload)가 특정 웹뷰를 노려. 이벤트는 반대 방향으로도 흘러 — 프론트엔드가 emit하고 Rust가 listen할 수 있어 — 근데 프론트엔드→코어 요청엔 보통 command를 원해(반환값이랑 에러 처리를 얻으니까). 이벤트는 던지고 잊는 공지에 남겨둬.
리스너는 항상 정리해
listen은 리스너를 제거하는 함수를 반환해. 컴포넌트에선 effect에서 등록하고 cleanup에서 그 unlisten 함수를 불러 — 안 그러면 컴포넌트 마운트할 때마다 중복 핸들러가 쌓여, 고전적인 메모리 누수 + 이중 발화 버그야. 딱 한 번만 처리하고 싶은 이벤트엔 once를 써.