Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust、何もわからない... ~Rust ウェブ開発事例紹介~

Rust、何もわからない... ~Rust ウェブ開発事例紹介~

「Rust、何もわからない... 」

4/18(月) 19:00~20:00に開催したイベントの資料を公開します。
https://estie.connpass.com/event/243724/
イベントハッシュタグ:#Rust何もわからない

https://www.estie.jp/corp/

estie | エスティ

April 19, 2022
Tweet

More Decks by estie | エスティ

Other Decks in Programming

Transcript

  1. ొஃऀ঺հ  LFOLPPPP 4PGUXBSF&OHJOFFS લ৬*OEFFE+BQBOͰ͸ɺػցֶ शɾࣗવݴޠॲཧΛ༻͍ͯσʔλ͔ ΒϝλσʔλΛੜ੒͢ΔγεςϜΛ ։ൃɻ FTUJFͰ͸3VTUΛ༻͍ͨ΢ΣϒΞϓ Ϧͷ։ൃʹऔΓ૊Ήɻ

    ʰ࣮ફ3VTUϓϩάϥϛϯάೖ໳ʱ ʰΞϧΰϦζϜ࣮ٕݕఆ ެࣜςΩε τʦΤϯτϦʔʙதڃฤʧʱڞஶɻ NBUTV 4PGUXBSF&OHJOFFS ૣҴాେֶ੓࣏ܦࡁֶ෦ଔɻ ೥ΑΓϑΥϧγΞגࣜձࣾ ʹͯ8FCΤϯδχΞͱͯ͠ۈ຿ɻ ೥ΑΓFTUJFʹࢀըɻ ʰ࣮ફ3VTUϓϩάϥϛϯάೖ໳ʱ ڞஶɻ
  2.  ຊ೔ͷྲྀΕ  Φʔϓχϯά r FTUJFͱ͸ʁ NJO  "DUJYXFC Ͱշద΢ΣϒΞϓϦੜ׆

    LFOLPPPP NJO  όοΫΤϯυΛ3VTUʹॻ͖׵͑ΔͷͬͯͲͷ͘Β͍͔͔ΔΜͰ͔͢ʁ NBUTV NJO  શମΛ௨ͯ͠ͷ2" NJO  Ϋϩʔδϯά NJO
  3. 

  4. 7

  5. 20/4 20/5 20/6 20/7 20/8 20/9 20/10 20/11 20/12 21/1

    21/2 21/3 21/4 21/5 21/6 21/7 21/8 21/9 21/10 21/11  ϏδωεΠϯύΫτ ओͳಋೖاۀ ԻॱɺҰ෦ൈਮ BOENPSF .33 Y ௚ۙϲ݄
  6. actix-web ってどんな感じ? • actix-web を使って簡単にウェブアプリが書ける • "The Rust Programming Language"

    ◦ 公式チュートリアル ◦ https://rust-lang.github.io/async-book/ ◦ 最後 章でウェブサーバーを作る
  7. これだけで動く!actix-web use actix_web::{get, App, HttpServer, Responder}; #[get("/index.html")] async fn index()

    -> impl Responder { "HELLO WORLD" } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().service(index)) .bind(("127.0.0.1", 8080))? .run() .await }
  8. これだけで動く!actix-web use actix_web::{get, App, HttpServer, Responder}; #[get("/index.html")] async fn index()

    -> impl Responder { "HELLO WORLD" } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().service(index)) .bind(("127.0.0.1", 8080))? .run() .await }
  9. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet (new_tweet: Json<Tweet>) -> Json<TweetResult> {

    // ツイートする } 関数 引数に渡すと、 actix-web が body として受け取る
  10. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, ) -> Json<TweetResult> { // ツイートする } Data<T> を引数に渡すと、 フレームワーク側から 引っ張ってくる
  11. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, cache: Data<TwitterCache>, ) -> Json<TweetResult> { // ツイートする } Data<T> を引数に渡すと、 フレームワーク側から 引っ張ってくる
  12. まとめ • actix-web で超簡単ウェブアプリ • 関数を書くだけ • 関数に色々渡せる • 良い感じにやってくれる

    #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client : Data<TwitterClient>, cache: Data<TwitterCache>, ) -> Json<TweetResult> { // ツイートする }
  13. ウェブフレームワークと ? actix-web フレームワーク #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>,

    client: Data<Client>, ) -> Json<TweetResult> { // 関数の中身 } リクエスト レスポンス 引数 返り値 いい感じにやってくれる
  14. もっと色々やってほしい! actix-web フレームワーク #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>, client:

    Data<Client>, user_data: UserData, ) -> Json<TweetResult> { // 関数の中身 } 引数 リクエスト データベース ユーザー情報を取得
  15. もっと色々やってほしい! #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>, client: Data<Client>, user_data:

    UserData, ) -> Json<TweetResult> { // 関数の中身 } 引数 リクエスト データベース ユーザー情報を取得 actix-web ミドルウェア
  16. もっと色々やってほしい! #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>, client: Data<Client>, user_data:

    UserData, ) -> Json<TweetResult> { // 関数の中身 } 引数 リクエスト データベース ユーザー情報を取得 ミドルウェア3 ミドルウェア2 ミドルウェア1
  17. actix-web ミドルウェア impl Service for Middleware { fn call(&self, req:

    ServiceRequest ) -> Self::Future { // req に対して色々処理 // 次の処理に req を渡す self.service.call(req).await.map(|res| res.map_into_left_body ()) } }
  18. actix-webミドルウェア 例 fn call(&self, req: ServiceRequest ) -> Self::Future {

    let token = parse_token(&req); // リクエストからトークンを取り出す // トークンを使って、ユーザー情報を取得 let user_info = self.client.get_user_info(&token); // ユーザー情報をリクエストに詰める req.extensions_mut ().insert(user_info); // リクエストを次の処理に渡す service.call(req).await.map(|res| res.map_into_left_body ()) }
  19. ミドルウェアでデータを渡す #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, user_data: ReqData<UserData>, ) -> Json<TweetResult> { // ツイートする } ミドルウェアでリクエストに渡したデー タを引数として引っ張ってくる
  20. まとめ #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, user_data: ReqData<UserData>, ) -> Json<TweetResult> { // ツイートする } ミドルウェアから来たデータ サーバーから来た リクエスト 中身 関数を作るだけ! ドンドン関数に渡せる!
  21. ど ように書き換え 意思決定をしたか • 環境 ◦ Node.jsに詳しい業務委託 エンジニアがチームを抜ける ◦ estieとしてRustに力を入れていきたい

    • チームメンバーを中心にメリット・デメリットを整理 ◦ CTOや他チーム エンジニアからも意見をもらいながら • 長期的な視点をもって意思決定した ◦ アプリケーション 開発効率・安全性 ◦ エンジニア採用
  22. 懸念・議論 • 型定義 二重管理問題 ◦ Rust実装 APIをTSから呼ぶと両方 言語で型定義が必要になる ◦ Rustから自動生成するツールを利用することで解決

    • Rust用 コンテナが必要問題 ◦ 他 チームで既に運用しており、行けると判断 • Rustが書けるエンジニアがアサインできるか問題 ◦ 興味を持てる人をアサインできれ 、キャッチアップしてもらえる
  23. 実際にやってみて • 実稼働3日で再実装できた ◦ 5~7日くらいと想定していたが、kenkooooさん チーム ノウハウを 活かすことができた ▪ Actix-web,

    sqlx, paperclip, anyhowなど • プロトタイプをRustで書くこと 是非 まだ分からない ◦ 保守しにくいコードを書きにくくする効果 あると思う
  24. フロントエンド Rustと 連携 課題 RustでもAPI リクエスト・レスポンス 型を定義したときに、TSでAPI リクエ スト・レスポンス 型を書かなくて済むようにしたい。

    解決策 別プロジェクトで ts_rs を使っていたが、クライアント側 コードを生成する OpenAPI を使うために paperclip を導入した。
  25. まとめ • 将来にベットする形で実験 コストを支払った ◦ Rustを仕事で書きたいエンジニア 多そう • 既にスタックを共有する効果が現れている ◦

    Actix-web, sqlx, paperclip, anyhow チームメンバーを募集しています • Meety こちら ◦ https://meety.net/matches/wXzgmcmNgWNO