🚀

async/await — Rust의 비동기 프로그래밍

Future trait 기반, 런타임 선택이 자유로운 비동기 모델

JavaScript의 async/await와 문법은 비슷하지만 내부 동작이 다르다. Rust의 async fn은 Future trait을 구현하는 상태 머신으로 컴파일된다. 힙 할당도 최소화된다.

async fn fetch_data(url: &str) -> Result<String, Error> {
    let response = reqwest::get(url).await?;
    let body = response.text().await?;
    Ok(body)
}

Rust 표준 라이브러리에는 비동기 런타임이 포함되어 있지 않다. tokio(가장 인기)나 async-std를 직접 가져다 쓴다. 이 설계 덕분에 임베디드 환경에서는 가벼운 런타임을, 서버에서는 고성능 런타임을 선택할 수 있다.

Pin과 Self-Referential Future

async 블록이 .await를 넘어서 로컬 변수의 참조를 유지하면 자기 참조(self-referential) 구조가 된다. 이걸 안전하게 다루기 위해 Pin이 존재한다. 이 부분이 Rust async의 가장 어려운 곳이다.

핵심 포인트

1

async fn은 Future trait을 구현하는 상태 머신으로 컴파일

2

.await에서 제어를 런타임에 양보(yield) — 다른 태스크 실행

3

tokio::spawn으로 비동기 태스크를 스케줄러에 등록

4

#[tokio::main]으로 런타임 초기화 + main을 async로

장점

  • 제로 코스트 — Future가 상태 머신으로 컴파일, 힙 할당 최소
  • 런타임 교체 가능 — tokio, async-std, smol 등

단점

  • async trait이 최근까지 불안정했다 (RPITIT로 안정화 진행 중)
  • Pin/Unpin 개념이 어렵다
  • 라이브러리가 tokio vs async-std로 갈리는 생태계 분열

사용 사례

웹 서버(axum, actix-web) — 수천 동시 연결을 적은 스레드로 처리 HTTP 클라이언트(reqwest) — 동시 다중 요청

참고 자료