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/

5d9c07f0c2044b1407a84d88362bc84d?s=128

estie | エスティ

April 19, 2022
Tweet

More Decks by estie | エスティ

Other Decks in Programming

Transcript

  1. None
  2.  ࢘ձ঺հ ؠ੒ ୡ࠸ !JX@UBUTV औక໾$50 ৽ଔͰ*OEFFE+BQBOʹೖࣾɻ΢Σϒ্ͷٻਓ ืू৘ใΛूΊͯఏڙ͢ΔσʔλύΠϓϥΠϯ ͷ։ൃʹैࣄɻ ೥݄ʹFTUJF΁71PG1SPEVDUTͱͯ͠

    ࢀը͠ɺ೥݄ʹ$50΁ब೚ɻ ϓϩμΫτ෦໳Λ౷ׅͯ͠ϓϩμΫτ࿈ܞͷઃ ܭ΍ɺ৽نϓϩμΫτ։ൃΛߦ͏ɻ
  3. ొஃऀ঺հ  LFOLPPPP 4PGUXBSF&OHJOFFS લ৬*OEFFE+BQBOͰ͸ɺػցֶ शɾࣗવݴޠॲཧΛ༻͍ͯσʔλ͔ ΒϝλσʔλΛੜ੒͢ΔγεςϜΛ ։ൃɻ FTUJFͰ͸3VTUΛ༻͍ͨ΢ΣϒΞϓ Ϧͷ։ൃʹऔΓ૊Ήɻ

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

    LFOLPPPP NJO  όοΫΤϯυΛ3VTUʹॻ͖׵͑ΔͷͬͯͲͷ͘Β͍͔͔ΔΜͰ͔͢ʁ NBUTV NJO  શମΛ௨ͯ͠ͷ2" NJO  Ϋϩʔδϯά NJO
  5.  ຊ೔ͷྲྀΕ • )BTIUBHʮ3VTUԿ΋Θ͔Βͳ͍ʯΛ࢖ͬͯΠϕϯτΛ੝Γ্͍͛ͯͩ͘͞ʂ • 2"ػೳΛͥͻ͝׆༻͍ͩ͘͞ʂ • ऴྃޙɺຊ೔ͷࢿྉΛμ΢ϯϩʔυͰ͖ΔΑ͏ʹ͍ͨ͠·͢

  6.  FTUJFͱ͸ʁ

  7. 

  8. 7

  9.  ৽ίʔϙϨʔταΠτ ʢ IUUQTXXXFTUJFKQDPSQ ʣ ͷ͝঺հ

  10. ͜Ε·ͰͷϓϩμΫτ܈

  11.  ͦΕΛࢧ͑ΔਐԽ͠ଓ͚ΔσʔλύΠϓϥΠϯ

  12. 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 ௚ۙϲ݄
  13.  1IBTF ۭࣨɾاۀ৘ใͷ σʔλج൫ߏங 1IBTF 1IBTF τϥϯβΫγϣϯ ϓϥοτϑΥʔϜ

  14.  ෳ਺ϓϩμΫτͷ૬৐ޮՌͰاۀՁ஋ΛരൃతʹߴΊΔ 1SPEVDU ۭࣨɾاۀ৘ใͷ σʔλج൫ߏங 1SPEVDU 1SPEVDU τϥϯβΫγϣϯ ϓϥοτϑΥʔϜ "1*ߏ૝

    ଟ༷ͳݴޠ ৽͍͠ϓϩμΫτͷόοΫΤϯυΛ3VTUͰॻ͍ͯ·͢ʂ
  15.  ͬͦ͘͞-5͍͖·͠ΐ͏ʂ )BTIUBH3VTUԿ΋Θ͔Βͳ͍ 2"ػೳΛͥͻ͝׆༻͍ͩ͘͞ʂ

  16. actix-web で快適ウェブアプリ生活 @kenkoooo

  17. 今日話すこと 1. actix-web で爆速ウェブアプリ開発 2. actix-web ミドルウェア

  18. actix-web で爆速ウェブアプリ開発

  19. actix-web と • Rust で作られたウェブフレームワーク • ウェブアプリに必要な機能をカバー • 広く使われている •

    ドキュメント・exampleが充実
  20. ウェブフレームワークと ?

  21. ウェブフレームワークと ? GET /index.html

  22. ウェブフレームワークと ? POST /tweet/new

  23. ウェブフレームワークと ?

  24. actix-web ってどんな感じ? • actix-web を使って簡単にウェブアプリが書ける • "The Rust Programming Language"

    ◦ 公式チュートリアル ◦ https://rust-lang.github.io/async-book/ ◦ 最後 章でウェブサーバーを作る
  25. None
  26. ウェブフレームワークと ? GET /index.html

  27. これだけで動く!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 }
  28. これだけで動く!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 }
  29. これだけで動く!actix-web #[get("/index.html")] async fn index() -> impl Responder { "HELLO

    WORLD" }
  30. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet () -> impl Responder {

    // ツイートする }
  31. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet (new_tweet: Json<Tweet>) -> Json<TweetResult> {

    // ツイートする }
  32. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet (new_tweet: Json<Tweet>) -> Json<TweetResult> {

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

    Json<TweetResult> { // ツイートする }
  34. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, ) -> Json<TweetResult> { // ツイートする }
  35. これだけで動く!actix-web #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

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

    #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client : Data<TwitterClient>, cache: Data<TwitterCache>, ) -> Json<TweetResult> { // ツイートする }
  38. actix-web ミドルウェア

  39. ウェブフレームワークと ?

  40. ウェブフレームワークと ? actix-web フレームワーク #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>,

    client: Data<Client>, ) -> Json<TweetResult> { // 関数の中身 } リクエスト レスポンス 引数 返り値 いい感じにやってくれる
  41. もっと良くしたい!

  42. もっと色々やってほしい! actix-web フレームワーク #[post("/tweet/new")] async fn post_new_tweet( new_tweet: Json<Tweet>, client:

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

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

    UserData, ) -> Json<TweetResult> { // 関数の中身 } 引数 リクエスト データベース ユーザー情報を取得 ミドルウェア3 ミドルウェア2 ミドルウェア1
  45. 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 ()) } }
  46. 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 ()) }
  47. ミドルウェアでデータを渡す #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, ) -> Json<TweetResult> { // ツイートする }
  48. ミドルウェアでデータを渡す #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, user_data: ReqData<UserData>, ) -> Json<TweetResult> { // ツイートする } ミドルウェアでリクエストに渡したデー タを引数として引っ張ってくる
  49. actix-web ミドルウェアまとめ • actix-web メッチャ簡単 • ミドルウェアでカスタマイズしまくり

  50. まとめ

  51. まとめ #[post("/tweet/new")] async fn post_new_tweet ( new_tweet: Json<Tweet>, twitter_client :

    Data<TwitterClient>, user_data: ReqData<UserData>, ) -> Json<TweetResult> { // ツイートする } ミドルウェアから来たデータ サーバーから来た リクエスト 中身 関数を作るだけ! ドンドン関数に渡せる!
  52. Rust導入から5ヶ月… @kenkoooo

  53. Rust導入から5ヶ月… • Rust導入から5ヶ月 • プロダクト 既にリリース済み ◦ 実装したいも が沢山 ◦

    入社して作ってくれ!
  54. Rust導入から5ヶ月… よかったこと • 生産性が高い ◦ パッケージマネージャ ◦ メッチャ強い補完 (rust-analyzer) •

    Rust流 設計を強制される ◦ 参照を持ち回さない
  55. Rust導入から5ヶ月… 大変なこと • サードパーティ 公式SDKがない ◦ Datadog ◦ SendGrid ◦

    Auth0 ◦ etc.
  56. Rust導入から5ヶ月… 他 メンバーへ 教育 • 試行錯誤中 • 動くプロジェクトがあれ 、動かしながら試せる •

    コードレビューをちゃんとする • コンパイラが教えてくれる
  57. まとめ Rustやったことない人 • 頑張って教える で入ってください! Rustやってる人 • 教えてください!!! 副業・アルバイト・インターンも募集中です!

  58. 助けて!

  59. バックエンドをRustに書き換えるって どれくらいかかるんですか? @matsu7874

  60. アジェンダ • 事例紹介 ◦ アプリケーション概要 ◦ ど ように書き換えを意思決定したか ◦ 実際にやってみて

    • TypeScriptと 連携 ◦ ts_rs ◦ paperclip
  61. 自己紹介 松本健太郎 (@matsu7874) • estie SWE ◦ 2021/12から業務委託 ◦ 2022/05から正社員としてフルタイム勤務

    • 『実践Rustプログラミング入門』共著
  62. 事例紹介 プロトタイプアプリ バックエンド再実装

  63. アプリケーション概要 • プロトタイプ開発中 アプリケーション ◦ バックエンド API10本くらい • Node.jsで開発していたバックエンドをRustに書き換えた MySQL

    MySQL Actix Next.js Next.js(API) Next.js
  64. ど ように書き換え 意思決定をしたか • 環境 ◦ Node.jsに詳しい業務委託 エンジニアがチームを抜ける ◦ estieとしてRustに力を入れていきたい

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

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

    sqlx, paperclip, anyhowなど • プロトタイプをRustで書くこと 是非 まだ分からない ◦ 保守しにくいコードを書きにくくする効果 あると思う
  67. フロントエンド Rustと 連携

  68. フロントエンド Rustと 連携 課題 RustでもAPI リクエスト・レスポンス 型を定義したときに、TSでAPI リクエ スト・レスポンス 型を書かなくて済むようにしたい。

    解決策 別プロジェクトで ts_rs を使っていたが、クライアント側 コードを生成する OpenAPI を使うために paperclip を導入した。
  69. ts_rs: TS interface定義を生成するクレート https://docs.rs/ts-rs/latest/ts_rs/

  70. paperclip: OpenAPI 定義ファイルを生成するクレート

  71. paperclip: OpenAPI 定義ファイルを生成するクレート https://paperclip-rs.github.io/paperclip/actix-plugin.html

  72. paperclip: OpenAPI 定義ファイルを生成するクレート https://paperclip-rs.github.io/paperclip/actix-plugin.html

  73. paperclip: OpenAPI 定義ファイルを生成するクレート • OpenAPI 定義ファイルが出力される で超便利 • クレートを分割したときにどう書ける か

    https://paperclip-rs.github.io/paperclip/actix-plugin.html
  74. まとめ

  75. まとめ • 将来にベットする形で実験 コストを支払った ◦ Rustを仕事で書きたいエンジニア 多そう • 既にスタックを共有する効果が現れている ◦

    Actix-web, sqlx, paperclip, anyhow チームメンバーを募集しています • Meety こちら ◦ https://meety.net/matches/wXzgmcmNgWNO
  76.  2"λΠϜ 次回開催に向け、アンケートのご協⼒をお願いします! https://forms.gle/yGE4pKPEc2CY2ZKE9

  77.  .FFUZ΍Γ·͠ΐ͏ʂ kenkoooo matsu7874 ハードル⾼ければTwitter DMくださいー! @iw_tasu

  78.  ࣍ճ3VTUΠϕϯτܾఆʂ 最新情報はConnpass/Twitterにて! 登壇希望の⽅がいれば、お声がけください! ⼀緒に盛り上げていきましょう〜

  79.  ຊ೔͸ɺ͝ࢀՃ͍͖ͨͩ ੣ʹ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ