C.W.K.
Stream
Lesson 05 of 06 · published

Channel<T>로 스트리밍

~13 min · tauri, channel, streaming, ipc

Level 0웹 관광객
0 XP0/56 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"이벤트는 공용 방송 시스템이야. 채널은 한 통화를 위해 연 사설 전화선이고."

command 하나가 할 말이 많을 때

command는 한 번 반환해. 근데 어떤 일은 갱신의 스트림을 만들어: 바이트를 보고하는 파일 다운로드, 진행률을 내는 긴 작업, 토큰을 내는 생성기. 이벤트로 방송할 수도 있지만, 그러면 사방의 모든 리스너가 듣고 어느 갱신이 어느 호출 거였는지 맞춰야 해. Tauri의 Channel<T>가 이걸 깔끔히 풀어 — 단일 invoke에 스코프된 타입 있는 순서 있는 스트림이야.

어떻게 엮이나

프론트엔드가 Channel을 만들고, onmessage 핸들러를 정하고, command 인자로 넘겨. Rust command는 Channel<T> 파라미터를 받아서 원하는 만큼 .send(payload)를 불러. 각 send가 프론트엔드 핸들러를 순서대로 발화시켜. command가 반환하면 그 호출의 스트림은 끝. 이벤트 이름 충돌도, correlation ID도 없어 — 채널이 correlation이야.

Channel vs 이벤트 vs 외부 스트림

스코프로 골라. 이벤트: 전역, 누구나 listen, 앱 전체 소식에 좋아. Channel: 요청 스코프, 호출자 하나, 작업의 진행에 좋아. 그리고 스트림이 완전히 다른 프로세스에서 올 때 — 네 Tauri 코어가 아니라 — 둘 다 안 맞아. 진짜 네트워크 전송을 꺼내. Cinder는 생성된 이미지를 별개 brain 프로세스에서 WebSocket으로 스트리밍해, 생산자가 Tauri 코어 안이 아니라서. 같은 '스트리밍'이란 단어, 데이터가 태어나는 곳에 따라 정답 셋.

Code

Channel로 진행률을 스트리밍하는 command·rust
use tauri::ipc::Channel;
use serde::Serialize;

#[derive(Clone, Serialize)]
struct Tick { step: u32, total: u32 }

// command가 Channel을 받아서 거기로 스트리밍해.
#[tauri::command]
async fn run_job(on_event: Channel<Tick>) -> Result<(), String> {
    for step in 1..=10 {
        tokio::time::sleep(std::time::Duration::from_millis(200)).await;
        on_event.send(Tick { step, total: 10 }).map_err(|e| e.to_string())?;
    }
    Ok(()) // 반환하면 이 호출의 스트림 종료
}
프론트엔드에서 스트림 받기·tsx
import { invoke, Channel } from "@tauri-apps/api/core";

type Tick = { step: number; total: number };

const channel = new Channel<Tick>();
channel.onmessage = (msg) => {
  console.log(`step ${msg.step}/${msg.total}`);
};

// 채널을 인자로 넘김; 갱신이 onmessage로 순서대로 도착.
await invoke("run_job", { onEvent: channel });

External links

Exercise

Channel로 진행 갱신 5개를 사이에 짧은 지연을 두고 스트리밍하는 command를 쓰고, channel.onmessage로 프론트엔드에 라이브 진행바를 렌더링해. 그다음 언제 대신 이벤트를 쓰고 언제 WebSocket이 필요한지 각각 한 문장으로 말해봐 — 셋을 스코프 스펙트럼에 놓을 수 있다는 걸 증명해.
Hint
Rust: 루프에서 tokio sleep 두고 on_event.send(...). 프론트엔드: new Channel(), onmessage 정하고, { onEvent }로 넘겨. 이벤트 = 전역/앱 전체; WebSocket = 다른 프로세스나 원격 서버의 데이터.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.