본문 바로가기
컴퓨터 활용(한글, 오피스 등)/기타

[Rust 입문] Actix 프레임워크로 웹 서버 만들어보기Actix 프레임워크로 웹 서버 만들어보기

by 3604 2024. 3. 30.
728x90

출처: https://blog.naver.com/shino1025/223076390730

막상 러스트 튜토리얼을 떼긴 했는데 뭔가 할게 없을까 고민하다가, Rust의 웹 프레임워크를 사용해보기로 결심했다. 러스트는 워낙 성능이 좋다고 알려져있다 보니 웹 프레임워크 벤치마크 사이트에서도 최상위권 랭킹을 거의 독식하고 있다.

보라색이 러스트(2,3,5,8,9 위)

뭐를 써볼까 좀 찾아봤는데 비교적 문서가 잘되어있고 커뮤니티도 활발해보이는 Actix라는 걸 써보기로 했다. 무엇보다 메인 페이지의 첫 이미지가 확 와닿았는데,

엄청 쉬워보였다. Python의 Flask, Js의 Express를 보는 듯한 기분이랄까? 라는 생각으로 시작했는데 단 2시간만에 뒤집어지긴 했지만 ㅎㅎ.. 아무튼 간단하게 알아보자.

Actix-Web

 

액틱스 웹은 액틱스라는 라이브러리를 기반으로 만들어진 웹 프레임워크이다. extremely fast web framework라고 언급되어 있지만, 사실 rust 기반 웹 프레임워크는 다들 퍼포먼스가 좋기 때문에 오히려 actix는 유틸/편의성을 많이 신경쓴 편에 속한다는 생각이 들었다.

Type Safe

러스트 기반이기 때문에 사실 당연하다. 사용자단에서 넘어오는 모든 리퀘스트에 대한 Validation도 나름 Rust의 철학대로 잘 풀어냈다.

Feature Rich

현대적인 웹 프레임워크가 지원하는 기능을 다소 지원하고 있다. 멀티스레딩, Fully Async, HTTP/2, Logging, Request/Response Compression, 컴파일 언어임에도 불구하고 Auto-Reloading까지 등등..

하지만 어디까지나 다소일 뿐, 현재 trend setter 자리에 있는 웹 프레임워크에 비하면 살짝 부족하다는 느낌을 받았다.

Extensible

확장 가능하다는 건데, 아마 주로 Middleware를 언급하는 것이 아닐까 싶다. 이미 만들어진 몇개의 Middleware도 있고 원한다면 자신이 직접 해당 인터페이스(Trait)에 기반하여 커스텀 미들웨어를 작성할 수 있다. 이를 통해 Actix의 생태계가 점점 확장되어가는 형태가 아닐까 싶다.

Get Started

root URL에서 "Hello world!"를 출력하는 가장 간단한 actix-web 예제 코드를 살펴보자.

use actix_web::{get, App, HttpResponse, HttpServer, Responder}; #[get("/")] async fn hello() -> impl Responder { HttpResponse::Ok().body("Hello world!") } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(hello) }) .bind(("127.0.0.1", 8080))? .run() .await }

async fn main()

actix_web에서 지원하는 "main"이라는 attribute를 사용하여 해당 함수는 Actix Web 프레임워크의 메인 함수로 사용된다. actix를 설치할 때 함께 tokio도 설치되는데 이를 통해 모든 함수에서 async programming이 가능해지는 것 같다.

여기서 HttpServer 및 App 인스턴스를 생성하여 웹 서버를 실행하는 것을 알 수 있다. bind() 메소드를 통해 127.0.0.1에 한정하여 8080 포트에 서버를 열고 웹 서버를 실행한다.

HttpServer::new의 구문 안에서는 익명 함수를 통해 어플리케이션이 초기화될 때, 다른 여러 전처리 작업을 실행시켜 줄 수 있다. 단 마지막에는 언제나 App 객체를 return 해주어야 한다!

async fn hello()

actix_web::get attribute를 통해 해당 함수를 Root URL("/")의 Route Function으로 지정해주었다.

약간 편리한 점은 직접 구체적인 Response Type을 명시하는 것이 아닌, 위처럼 "impl Responder"로 명시해주어도 된다. 즉, Responder라는 impl이 구현된 무언가를 대충 얼버무려준다는 의미이다.

하지만 여기서 주의할 점은 이 부분의 Reponse Type이 컴파일 타임에서 결정된다는 점이다.

만약 impl Responder를 충족하기는 하지만 상황에 따라 서로 다른 Type을 반환하도록 함수를 작성한 경우, 컴파일러가 이를 허용하지 않는다.

Extractor

액틱스에서는 Router단에서 사용자의 리퀘스트나 Application의 Global State에 접근하는 것을 Extractor(익스트랙터)라고 부른다.

 

위 문서에 들어가면 각각의 리퀘스트나 State에 대하여 어떻게 접근하고 추출할 수 있는지에 대해 간단한 예자가 작성되어 있다.

근데 한가지 걸리는 건 File Upload가 안 보인다는 건데...(선넘네) 필자는 현재 하고자 하는 것에서 파일 업로드/다운로드까지는 필요하지 않아서 넘어갔는데 나중에 알게 된다면 다른 포스팅에서 공유하도록 하겠다.

Application Test

Cargo에서 지원하는 테스트 프레임워크를 그대로 사용할 수 있도록 actix에서 지원해준다. 아래는 테스트 코드 예제이다.

#[cfg(test)] mod tests { use actix_web::{test, App, web::Data}; use crate::app::router; use crate::config::AppConfig; #[actix_web::test] async fn test_true() { assert!(true); } #[actix_web::test] async fn test_index() { let app_config = AppConfig::from_env(".env"); let app = test::init_service( App::new().service(router::template::index) ).await; let req = test::TestRequest::get().uri("/").to_request(); let resp = test::call_service(&app, req).await; assert!(resp.status().is_success()); } }

actix_web::test attribute를 사용해서 테스트를 사용할 수 있다. 테스트 시에는 init_service라는 메소드를 통해 가상의 App 인스턴스를 만들어 준 후, 해당 App에 대하여 request를 보내는 형태로 intergation test를 진행할 수 있다.

Actix Application 구조화하기

Actix는 대체로 구조화가 자유로운 편이다. actix 개발자 분들도 그걸 당연히 알고 계시는지, 도큐먼트 끝단에 Example Repo라고 해서 다른 개발자들이 Actix를 어떻게 구조화해놓았는 지에 대해 모아 놓은 Repo를 링크로 달아놓으셨다.

필자도 여기있는 Repo를 몇개 참고하여 나만의 Actix Structure를 라이트하게 작성해보았다. 앞으로 Rust 기반으로 간단한 API 서버를 구현한다면 해당 Template을 기반으로 구현해보려 한다!

References

728x90
반응형

'컴퓨터 활용(한글, 오피스 등) > 기타' 카테고리의 다른 글

Read Excel File in C#  (0) 2024.04.01
Getting Started with Actix Web - The Battle-tested Rust Framework  (0) 2024.03.30
[비공개] finereport  (0) 2024.03.30
report 종류  (0) 2024.03.30
개발 코드  (1) 2024.03.23