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

Async command & 런타임

~14 min · tauri, async, rust, performance

Level 0웹 관광객
0 XP0/56 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"느린 동기 command는 앱을 얼려. async는 작업이 도는 동안 창이 계속 숨 쉬게 해."

그냥 async를 붙여

command를 비동기로 만들려면 async fn으로 써. Tauri가 그걸 async 런타임(Tokio)에서 돌리고, 프론트엔드의 invoke Promise는 future가 완료될 때 resolve돼. 이게 중요한 건 긴 동기 command가 블록해서 UI가 얼어붙은 느낌을 줄 수 있어서야. 네트워크 호출, 자식 프로세스 대기, I/O 바운드 뭐든 — async로 만들면 앱이 반응성을 유지해.

I/O 바운드 vs CPU 바운드

진짜 구분이 있어. I/O 바운드 작업(HTTP, 디스크, 대기)은 async에 완벽히 맞아 — 런타임이 기다리는 동안 태스크를 주차하고 다른 일을 돌려. CPU 바운드 작업(거대한 이미지 리사이즈, 해싱, 무거운 파싱)은 async만으론 이득이 없어. async 태스크 안에서 CPU를 갈면 여전히 런타임을 멈출 수 있어. 무거운 연산은 tokio::task::spawn_blocking(또는 그냥 std::thread)으로 블로킹 스레드에 떠넘겨서 async 런타임을 자유롭게 둬.

Send 함정

컴파일러가 강제할 규칙 하나: async command에서 await가로질러 들고 있는 데이터는 스레드 사이로 옮겨도 안전(Send)해야 해. 흔한 함정이 std::sync::Mutex 가드를 await 지점을 가로질러 들고 있는 거야 — 컴파일 안 돼. 고침은 await 전에 락을 떨구거나, async 인식 락을 쓰는 거야. state 트랙에서 제대로 만나 — 지금은 'cannot be sent between threads safely'가 보통 'await를 가로질러 락을 들고 있었다'는 뜻인 걸 알아둬.

Code

async command (I/O 바운드)·rust
// I/O 바운드: 네트워크 호출이 도는 동안 async가 UI 반응성을 유지.
#[tauri::command]
async fn fetch_title(url: String) -> Result<String, String> {
    let body = reqwest::get(&url)
        .await
        .map_err(|e| e.to_string())?
        .text()
        .await
        .map_err(|e| e.to_string())?;
    Ok(body.chars().take(80).collect())
}
spawn_blocking으로 CPU 작업 떠넘기기·rust
// CPU 바운드: async 태스크 안에서 갈지 마 — 떠넘겨.
#[tauri::command]
async fn heavy_hash(data: Vec<u8>) -> Result<String, String> {
    let digest = tokio::task::spawn_blocking(move || {
        expensive_pure_cpu_hash(&data) // 블로킹 스레드 풀에서 실행
    })
    .await
    .map_err(|e| e.to_string())?;
    Ok(digest)
}

External links

Exercise

command 하나를 async로 바꿔. 제일 쉬운 데모: 2초 tokio sleep을 await하고 문자열을 반환하는 async command를 써. 프론트엔드에서 부르고, 도는 동안 UI 나머지(스피너, 카운터)가 계속 움직이는지 확인해. 그다음 같은 지연을 std::thread::sleep으로 동기로 쓰고 차이를 느껴봐 — 동기 버전은 창을 얼려.
Hint
Async: tokio::time::sleep(Duration::from_secs(2)).await 써. Sync(얼음 느끼려면): 비-async command 안에서 std::thread::sleep(...) 직접. 얼어붙은 창이 레슨이야.

Progress

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

댓글 0

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

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