Learn Rust Coding · 강의

Tokio로 비동기 애플리케이션 만들기

Tokio 런타임을 사용해 비동기 작업을 효율적으로 실행하고 입출력 및 기타 동시 작업을 처리합니다.

레슨 2/311개 단계

Tokio로 비동기 애플리케이션 만들기은(는) CoddyKit의 무료 Learn Rust Coding 강의입니다. 이것은 3개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Learn Rust Coding 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Learn Rust Coding 강의에는 총 3개의 강의가 포함되어 있습니다.

Tokio 런타임 알아보기

다시 오신 것을 환영합니다! 이전 레슨에서는 async와 await를 배웠습니다. 그렇다면 async 함수는 실제로 어떻게 실행될까요?

이때 Tokio와 같은 비동기 런타임이 필요합니다. Tokio는 비동기 Rust 코드를 실행할 환경을 제공하는 강력한 라이브러리입니다.

  • Future를 예약하고 실행합니다.
  • 차단 없이 입출력 작업을 처리합니다.
  • 동시 작업을 효율적으로 관리합니다.

비동기 코드 실행하기

Tokio를 시작할 때는 일반적으로 #[tokio::main] 속성 매크로를 사용합니다. 이 매크로는 async fn main()을 Tokio 런타임을 초기화하고 비동기 코드를 실행하는 표준 fn main()으로 변환합니다.

비동기 애플리케이션의 진입점이라고 생각하시면 됩니다.

use tokio;

#[tokio::main]
async fn main() {
  println!("Hello from Tokio!");
}

새로운 비동기 작업 생성하기

Tokio의 핵심 기능 중 하나는 여러 비동기 작업을 동시에 실행하는 기능입니다. tokio::spawn을 사용하면 이를 구현할 수 있습니다.

tokio::spawn은 Future를 받아 Tokio 런타임에서 실행하도록 예약합니다. 따라서 생성된 작업이 백그라운드에서 실행되는 동안 주 작업을 계속 실행할 수 있습니다.

  • 실행을 차단하지 않습니다.
  • 완료를 기다릴 수 있는 JoinHandle을 반환합니다.
  • 작업은 서로 독립적으로 실행됩니다.

<code>tokio::spawn</code> 사용하기

tokio::spawn을 사용하면 코드를 동시에 실행할 수 있는 방법을 살펴보겠습니다. 두 메시지가 모두 출력되지만, sleep 때문에 'task complete' 메시지보다 'done' 메시지가 먼저 출력될 수도 있다는 점에 주목하세요.

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  // Spawn a new task
  let handle = tokio::spawn(async {
    sleep(Duration::from_secs(1)).await;
    println!("Async task complete!");
  });

  println!("Main task continuing...");

  // Wait for the spawned task to finish
  handle.await.unwrap();
  println!("All tasks done.");
}

여러 작업 기다리기

여러 작업이 있을 때는 모든 작업이 완료될 때까지 기다려야 하는 경우가 많습니다. Tokio는 이를 위해 tokio::join! 매크로를 제공합니다.

tokio::join!을 사용하면 여러 퓨처를 동시에 기다리고 결과를 결합할 수 있습니다. 여러 JoinHandle을 `await`하는 것과 비슷하지만, 개수가 정해진 퓨처를 처리할 때 더 간결한 경우가 많습니다.

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  let task1 = async {
    sleep(Duration::from_secs(1)).await;
    println!("Task 1 finished");
    1
  };

  let task2 = async {
    sleep(Duration::from_millis(500)).await;
    println!("Task 2 finished");
    2
  };

  let (result1, result2) = tokio::join!(task1, task2);
  println!("Results: {}, {}", result1, result2);
}

Tokio로 비동기 파일 입출력하기

기존 파일 작업은 스레드를 차단할 수 있으므로 비동기 애플리케이션에 좋지 않습니다. Tokio의 tokio::fs 모듈은 파일 시스템 작업의 비동기 버전을 제공합니다.

따라서 큰 파일을 읽거나 많은 파일 작업을 수행할 때도 입출력이 차단 없이 처리되어 애플리케이션이 계속 응답할 수 있습니다.

  • tokio::fs::read_to_string
  • tokio::fs::write
  • 더 세밀하게 제어할 때 사용하는 tokio::fs::File

비동기 방식으로 파일 읽기

tokio::fs::read_to_string을 사용해 파일을 비동기 방식으로 읽는 방법은 다음과 같습니다. 이 코드가 실행되려면 Rust 프로젝트와 같은 디렉터리(예: src/ 내부 또는 프로젝트 루트)에 내용이 들어 있는 hello.txt 파일이 있어야 합니다.

use tokio::fs;

#[tokio::main]
async fn main() {
  let path = "hello.txt";
  // Create a dummy file for the example if it doesn't exist
  // In a real app, you'd handle file creation/existence more robustly
  if let Err(_) = fs::metadata(path).await {
    fs::write(path, "Hello, Tokio file!").await.unwrap();
  }

  match fs::read_to_string(path).await {
    Ok(content) => println!("File content: '{}'", content),
    Err(e) => eprintln!("Error reading file: {}", e),
  }
}

비동기 네트워크 작업

Tokio는 네트워크 프로그래밍에서 진가를 발휘합니다. Tokio의 tokio::net 모듈은 TCP 및 UDP 통신을 위한 비차단 기본 기능을 제공합니다.

이는 각 연결마다 별도의 스레드를 만들지 않고도 많은 연결을 동시에 처리하는 고성능 서버나 클라이언트를 구축하는 데 매우 중요합니다.

  • 서버에는 tokio::net::TcpListener를 사용합니다.
  • 클라이언트 연결에는 tokio::net::TcpStream을 사용합니다.

기본 비동기 TCP 서버 구조

완전한 서버는 복잡하지만, 이 코드는 Tokio를 사용한 비동기 TCP 서버의 핵심 반복문을 보여 줍니다. 이 서버는 들어오는 연결을 수신하고 각 연결마다 메시지를 출력합니다. 실행한 다음 브라우저에서 http://127.0.0.1:8080을 열어 연결을 확인해 보세요.

use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
  let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
  println!("Listening on: {}", listener.local_addr().unwrap());

  loop {
    let (socket, addr) = listener.accept().await.unwrap();
    println!("Accepted connection from: {}", addr);
    // In a real server, you'd spawn a task to handle the socket
    // tokio::spawn(async move { handle_connection(socket).await; });
  }
}

// fn handle_connection(socket: TcpStream) { /* ... */ } // Placeholder

Tokio 작업 도전 과제

Tokio를 사용하는 다음 Rust 코드를 살펴보세요. 이 프로그램을 실행하면 콘솔에 처음으로 출력되는 메시지는 무엇일까요?

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  tokio::spawn(async {
    sleep(Duration::from_millis(200)).await;
    println!("Task 1: Done");
  });

  tokio::spawn(async {
    sleep(Duration::from_millis(100)).await;
    println!("Task 2: Done");
  });

  println!("Main: Starting tasks...");

  sleep(Duration::from_millis(300)).await;
  println!("Main: Finishing.");
}

복습: Tokio로 구축하기

Rust와 Tokio를 사용해 비동기 애플리케이션을 구축하는 데 큰 발걸음을 내디디셨습니다!

  • Tokio는 비동기 런타임으로 동작하며 async 코드를 실행합니다.
  • #[tokio::main]은 프로그램의 비동기 진입점입니다.
  • tokio::spawn을 사용하면 여러 작업을 동시에 실행할 수 있습니다.
  • tokio::join!은 여러 퓨처를 기다리는 데 도움이 됩니다.
  • Tokio는 파일(tokio::fs)과 네트워크(tokio::net)에 비차단 입출력을 제공합니다.

이 도구들은 동시성과 응답성이 높은 Rust 애플리케이션을 만드는 데 기본이 됩니다. 계속 연습해 보세요!

무료로 시작

AI 튜터와 함께 Rust을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
39
레슨
144

자주 묻는 질문

“Tokio로 비동기 애플리케이션 만들기” 강의는 무료인가요?

네 — “Tokio로 비동기 애플리케이션 만들기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Learn Rust Coding 강의 전체를 잠금 해제할 수 있습니다. Learn Rust Coding 강의에는 총 3개의 강의가 포함되어 있습니다.

“Tokio로 비동기 애플리케이션 만들기”에서 뭘 배우나요?

Tokio 런타임을 사용해 비동기 작업을 효율적으로 실행하고 입출력 및 기타 동시 작업을 처리합니다. 브라우저에서 직접 실행하는 실습 코드로 Learn Rust Coding을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Learn Rust Coding을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Learn Rust Coding은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 3개 중 2번째 강의입니다.

“Tokio로 비동기 애플리케이션 만들기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Learn Rust Coding 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Learn Rust Coding 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Async/Await 입문
  2. Tokio로 비동기 애플리케이션 만들기
  3. 퓨처와 작업 다루기
← Learn Rust Coding(으)로 돌아가기