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

런타임: tokio

~11 min · async, tokio, runtime

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Rust 표준 라이브러리는 Future trait 이랑 async/await 문법을 정의해 — 근데 의도적으로 async 런타임을 실어. Future 를 실제로 돌리려면 런타임 크레이트를 가져와. 지배적인 게 tokio 야.

왜 내장 런타임이 없냐?

다른 워크로드는 다른 스케줄러를 원해 — 웹 서버, 임베디드 기기, GUI 앱은 필요가 달라. 그래서 Rust 는 언어 기능 (Future, await) 을 표준화하지만 실행기 는 생태계에 맡겨. 언어 나머지랑 같은 철학이야: 최소 코어, 정책 결정은 네가 고르는 라이브러리에.

tokio: 사실상의 런타임

tokio 가 Future 를 poll 하는 실행기, 더하기 async 버전 I/O — TCP, 파일, 타이머, 채널 — 를 제공해. #[tokio::main] attribute 가 네 async fn main 을 런타임을 세팅하고 최상위 Future 에 블록하는 평범한 main 으로 바꿔. 거기서부터 안쪽 모든 .await 가 tokio 스케줄러에서 돌아.

std 는 async 를 정의; 런타임 크레이트가 실행. 언어가 Futureawait 를 주고; tokio (또는 async-std, smol) 가 그걸 구동하는 실행기랑 await 할 async I/O 를 줘. 이 분리가 async 가 실제로 돌기 전에 Cargo.tomltokio 를 더하고 main#[tokio::main] 을 다는 이유야.

생태계가 tokio 를 가정해

대부분 async 라이브러리 — axum 같은 웹 프레임워크, sqlx 같은 DB 드라이버, reqwest 같은 HTTP 클라이언트 — 가 tokio 위에 지어졌어. 대안이 있지만 tokio 가 안전한 기본값이고 제일 많이 만날 거야. 대부분 프로덕션 Rust 서비스가 그 위에서 돌아.

Code

#[tokio::main] 이 async main 을 준다·rust
// Cargo.toml:  tokio = { version = "1", features = ["full"] }

// #[tokio::main] 이 런타임을 세팅하고 최상위 Future 를 돌림
#[tokio::main]
async fn main() {
    let result = compute().await; // 이제 .await 가 실제로 돎
    println!("result: {result}");
}

async fn compute() -> i32 {
    // 진짜 프로그램은 여기서 I/O 를 .await (네트워크, 파일, 타이머)
    40 + 2
}

External links

Exercise

Cargo.toml 에 tokio 를 넣고 async main 에 #[tokio::main] 을 달아 바이너리를 세팅해. 계산된 값을 반환하는 async 함수를 쓰고, main 에서 await 하고, 결과를 출력해. 그다음 tokio::time::sleep(...).await 로 I/O 대기를 시뮬레이션해 — 프로그램이 스레드를 블록하는 대신 반응성을 유지하는 걸 봐.
Hint
tokio = { version = "1", features = ["full"] } 를 더하고, main 에 #[tokio::main] 을 달면, 이제 최상위에서 .await 가 통해. tokio::time::sleep 이 async 친화적 대기 방법이야 — 스레드 블록 대신 양보해.

Progress

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

댓글 0

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

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