HTTP는 정보 및 데이터 전송을 위해 클라이언트-서버 아키텍처를 활용합니다. Rust와 같은 서버 측 프로그래밍 언어의 특징 중 하나는 HTTP 기반 서비스와 상호 작용하기 위한 서버 및 클라이언트 앱을 개발하는 것입니다.

Rust는 안전, 성능 및 안정성 기능으로 인해 HTTP 서버를 구축하는 데 적합합니다. Actix 및 Rocket과 같은 Rust의 서드파티 크레이트는 높은 트래픽을 처리할 수 있는 정교한 웹 서버를 구축하는 데 널리 사용됩니다.

HTTP 웹 서버 개발에 Rust를 사용해야 하는 이유는 무엇인가요?

Rust는 언어의 일부 기능이 대부분의 웹 서버 구축에 필요한 요구 사항과 정확히 일치하기 때문에 웹 서버 개발에서 인기를 얻고 있습니다.

Rust를 사용하면 애플리케이션을 효율적으로 확장할 수 있으므로 고성능 앱을 구축하는 데 이상적인 언어입니다. 웹 서버 및 기타 서버 측 애플리케이션에 Rust 사용을 고려해야 하는 구체적인 이유는 다음과 같습니다.

Rust의 고성능

고성능은 Rust가 HTTP 웹 서버를 구축하는 데 탁월한 선택이 되는 이유 중 하나입니다. Rust는 메모리와 CPU를 포함한 시스템 리소스에 대한 로우레벨 액세스를 제공하므로 다른 서버 측 언어보다 적은 리소스로 더 빠르게 실행되는 코드를 작성할 수 있습니다.

또한 Rust의 소유권 시스템은 일부 서버 측 언어가 느린 이유 중 하나인 컴파일 시 가비지 컬렉션이 필요하지 않습니다.

안전 및 보안

Rust의 메모리 관리 소유권 시스템은 웹 서버 개발을 위한 안전한 언어입니다. 메모리 누수 및 기타 보안 취약점으로 이어질 수 있는 널 또는 매달린 포인터 참조가 발생하지 않습니다.

Rust의 소유권 시스템은 이러한 일반적인 오류를 방지하여 서버와 앱을 안전하게 유지합니다. 또한 Rust는 버퍼 오버플로 및 기타 메모리 관련 오류를 방지하는 데 중점을 둡니다.

동시성

동시성은 출력에 영향을 주지 않고 프로그램의 여러 단위를 순서대로 실행할 수 있는 기능입니다. 동시 프로그램의 출력은 비동기 프로그램의 출력과 동일해야 합니다.

이 글도 확인해 보세요:  Python을 사용하여 할 일 목록 프로그램 만들기

서버가 여러 요청을 동시에 처리해야 하므로 동시성은 애플리케이션의 성능에 큰 영향을 미칠 수 있습니다. Rust는 경량 스레딩 모델과의 공존을 지원합니다.

Rust에서 동시 프로그래밍의 장점은 소유권 시스템을 통해 잠금 및 기타 동기화 프리미티브 없이도 스레드에 안전한 코드를 작성할 수 있다는 것입니다.

최신 툴링 제공

Rust 표준 라이브러리와 Rust 에코시스템의 타사 패키지는 효과적인 웹 서버 개발을 위한 최신 툴링을 제공합니다.

Rust의 패키지 관리자 Cargo는 종속성 관리와 빌드 프로세스를 간소화합니다. 또한 Rust는 원활한 코드 완성, 오류 강조 표시 및 기타 기능을 제공하는 Rust Analyzer와 같은 도구를 통해 뛰어난 IDE 지원을 제공합니다.

Actix 및 Rocket 라이브러리 개요

Rust의 표준 라이브러리에는 웹 서버를 빌드하는 데 필요한 대부분의 유틸리티가 포함되어 있습니다. Rocket 및 Actix와 같은 타사 라이브러리는 Rust로 서버 측 애플리케이션을 간편하게 구축할 수 있게 해줍니다.

Actix Rocket 는 널리 사용되는 Rust 웹 프레임워크이지만 라이브러리마다 디자인과 기능이 다릅니다.

Rocket은 생산성과 사용 편의성을 우선시하는 고급 웹 프레임워크입니다. Rocket은 Rust로 웹 앱을 구축하기 위한 많은 추상화와 구문 설탕을 제공합니다. 또한 강력한 타이핑과 직관적인 API 디자인으로 유명합니다.

Cargo.toml 파일에 프로젝트 종속성으로 Rocket을 추가하여 Rust에서 웹 앱 빌드를 시작할 수 있습니다:

 [dependencies]
rocket = "0.4.11"

반면에 Actix-web은 성능과 확장성에 우선순위를 둔 로우레벨 프레임워크입니다. 액틱스는 액터 기반 동시성 모델을 활용하고 비차단 I/O를 제공하여 고성능 웹 애플리케이션을 구축하는 데 이상적인 패키지입니다.

Cargo.toml 파일의 종속성 섹션에 Actix를 프로젝트 종속성으로 추가합니다:

 [dependencies]
actix-web = "4.3.1"

프로젝트에 사용할 라이브러리를 선택하는 것은 프로젝트의 사양, 라이브러리의 기능, Rust 및 HTTP에 대한 경험에 따라 달라집니다.

Rust로 간단한 웹 서버 빌드하기

Rust 프로젝트를 생성하고 프로젝트의 종속성에 Rocket 또는 Actix 프레임워크를 Cargo.toml 파일에 추가하면 Rust로 웹 서버를 빌드할 준비가 된 것입니다.

이 글도 확인해 보세요:  내부에서 REST API 호출을 수행하는 방법 VS 코드

Actix로 간단한 웹 서버 빌드하기

Rust에서 웹 서비스를 빌드할 때 요청에 직렬화기를 사용할 수 있습니다.

Serde는 Rust 유형과 JSON, YAML, TOML과 같은 데이터 형식 간에 데이터를 직렬화 및 역직렬화하는 데 널리 사용되는 Rust 라이브러리입니다. Serde는 Rust 데이터 구조와 다른 데이터 형식의 해당 표현 간의 데이터 변환을 정의하기 위한 프레임워크를 제공합니다.

프로젝트에 Serde를 서드파티 패키지로 추가하기 위한 지시어는 다음과 같습니다.

 [dependencies]
serde = { version = "1.0.159" , features = ["derive"] }

Serde와 Actix를 프로젝트 종속 요소로 추가한 후에는 Rust로 기본 웹 서버를 생성할 수 있습니다. 간단한 Hello World를 설정하는 방법은 다음과 같습니다! Actix를 사용하여 클라이언트에 문자열을 작성하는 웹 서버입니다:

먼저 actix_web 및 serde 상자에서 필요한 모듈과 유형을 가져옵니다:

 use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};

serde를 사용하여 구조체로 메시지를 클라이언트에 직렬화합니다. Serde는 클라이언트를 위해 구조체를 JSON으로 변환합니다. 다음은 메시지에 대한 구조체입니다:

 #[derive(Debug, Serialize, Deserialize)]
struct Message {
    message: String,
}

이제 엔드포인트에 대한 핸들러 함수를 정의할 수 있습니다. 핸들러 함수의 맨 위에 사용자 지정 동작을 위한 데코레이터를 추가할 수 있습니다:

 #[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().json(Message {
        message: "Hello, World!".to_owned(),
    })
}

hello 핸들러 함수는 GET 요청을 처리합니다. 이 함수는 Actix 패키지의 응답자 특성을 구현하는 유형을 반환합니다.

HttpResponse::Ok() 유형의 json 메서드는 Serde가 내부에서 처리하는 구조체 인스턴스를 가져와 클라이언트에 응답을 반환합니다.

엔드포인트를 정의한 후 서버 인스턴스를 시작하고 경로에 엔드포인트를 마운트할 수 있습니다.

 #[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(hello))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

HttpServer::new 함수는 새 서버 인스턴스입니다. 메인 함수가 시작되고 서버는 헬로 핸들러 함수를 새 앱 인스턴스와 함께 마운트합니다. 바인드 메서드는 서버를 지정된 URL에 바인딩하고 실행 함수는 서버를 실행합니다.

로켓으로 간단한 웹 서버 구축하기

로켓은 미니멀리즘을 지향하기 때문에 로켓 크레이트 외에 다른 의존성 없이 간단한 웹 서버를 구축할 수 있습니다.

이 글도 확인해 보세요:  HTTP와 HTTPS: 차이점은 무엇인가요?

Rocket을 사용하여 Hello World! 엔드포인트가 있는 간단한 서버를 설정하는 방법은 다음과 같습니다:

먼저 서버에 필요한 종속성을 가져옵니다.

 #![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate rocket;

// imports from the Rocket crate
use rocket::response::content;
use rocket::State;

#![feature(proc_macro_hygiene, decl_macro)] 속성은 로켓 프레임워크에 대한 Rust 실험적 기능을 활성화합니다. macro_use] 속성은 로켓 모듈에서 매크로를 가져옵니다.

다음은 요청 시 HTML을 제공하는 핸들러 함수입니다:

 #[get("/")]
fn hello_world() -> content::Html<&'static str> {
    content::Html("<h1>Hello, world!</h1>")
}

hello_world 함수는 content::Html 함수와 함께 HTML 정적 문자열을 반환합니다.

다음은 서버에 대한 구성 구조체 선언입니다(로켓 프레임워크 규칙):

 struct Config {
    port: u16,
}

#[get("/port")]
fn port(config: State<Config>) -> String {
    format!("Server running on port {}", config.port)
}

서버를 실행할 때 /port 엔드포인트로 포트 상태를 요청할 수 있습니다.

마지막으로, 이그나이트 함수를 사용하여 서버 인스턴스를 생성합니다. 구성을 추가하고, 경로를 마운트하고, 서버를 시작합니다:

 fn main() {
    let config = Config { port: 8000 };

    rocket::ignite()
        .manage(config)
        .mount("/", routes![hello_world, port])
        .launch();
}

config 변수는 Config 구조체의 인스턴스입니다. ignite 함수는 서버 인스턴스를 시작하고, manage 메서드는 서버에 구성을 추가하며, mount 메서드는 기본 경로에 핸들러 함수를 마운트합니다. 마지막으로 launch 메서드는 지정된 포트에서 수신 대기하도록 서버를 시작합니다.

WASM으로 Rust에서 강력한 웹 애플리케이션을 빌드할 수 있습니다

웹어셈블리(WASM)는 브라우저 및 기타 장치에서 실행되도록 설계된 바이너리 명령어 형식입니다. WASM은 Rust와 같은 상위 수준 프로그래밍 언어가 컴파일 대상으로 사용할 수 있는 저수준 바이트코드 형식을 제공합니다.

WASM을 사용하면 가장 널리 사용되는 브라우저에서 실행할 수 있는 바이너리 형식으로 Rust 코드를 컴파일할 수 있습니다. WASM은 풀스택 웹 앱을 포함하여 Rust에서 강력한 웹 애플리케이션을 구축할 수 있는 무한한 가능성을 열어줍니다.

By 박준영

업계에서 7년간 경력을 쌓은 숙련된 iOS 개발자인 박준영님은 원활하고 매끄러운 사용자 경험을 만드는 데 전념하고 있습니다. 애플(Apple) 생태계에 능숙한 준영님은 획기적인 솔루션을 통해 지속적으로 기술 혁신의 한계를 뛰어넘고 있습니다. 소프트웨어 엔지니어링에 대한 탄탄한 지식과 세심한 접근 방식은 독자에게 실용적이면서도 세련된 콘텐츠를 제공하는 데 기여합니다.