非同期処理を支えるRust活用術 エンジニアの「書いていて楽しい」を実現

投稿日時:
吉川 哲史のアイコン

Fairy Devices株式会社 / プロダクト開発部 部長

吉川 哲史

Xアカウントリンク

はじめまして。Fairy Devices(フェアリーデバイセズ)で、プロダクト開発部の部長を務める吉川(@emergent)といいます。ここでは、当社におけるRustの活用を紹介します。

Fairy Devicesとは?独自開発のデバイス×AI技術

Fairy Devicesは、自社開発のウェアラブルデバイスとAI技術を組み合わせた事業を展開しており、主なサービスとして、音声関連の技術をクラウドAPIとして提供する「mimi」、顧客の遠隔業務を支援する「LINKLET」があります。

mimiでは、音声関連の技術をクラウドAPIとして提供し、音声認識、入力された音声から必要な情報を抽出するAPI、音声認識前に音声をクリアに処理するライブラリなどをセットで提供しています。LINKLETでは、首にかける形状のウェアラブルデバイス「THINKLET」をZoomなどのWeb会議ツールと連携させ、作業者がハンズフリーで前方の映像をリアルタイムに共有することなどを可能にします。

下記では、Fairy DevicesでRustの採用を進めることになった背景をご説明します。

C++時代に抱えていた課題

私がFairy Devicesに入社した2018年は、mimiの事業のみを展開しており、サーバーサイドからクライアントライブラリまで、ほぼC++で実装されていました。例えば、音声認識機能では、サーバーがクライアントから音声ストリーム(音声データ)を受け取るとともに、認識エンジンからも非同期で認識結果を受け取る必要がありました。こうした非同期処理をC++で記述すると、コードをメンテナンスする際にバグを埋め込んでしまうことがよくあり、「生産性を高めながら安全に開発できないか」というニーズを抱えていました。

なぜRustを採用したのか

Rustであればコンパイル時にメモリの安全性を担保できるほか、非同期処理などで発生しがちなクラッシュやデータ競合を減らすことができ、開発者の負荷軽減につながります。C++時代に苦労していた部分を丁寧に拾ってくれる言語仕様であることから、「うちのプロダクトにフィットするぞ」と思い、採用に至りました。Rustは現在、mimiだけでなく、さまざまなサービスで活躍しています。

mimiとLINKLETを支える仕組み

mimiクラウドAIのAPI構成では、音声ストリームがクライアントプログラムから音声入力エンドポイントと中間サーバーを経て、音声処理エンジンへ流れる仕組みを採っています。音声入力エンドポイントでは現状C++で記述していますが、中間サーバーは順次Rustに置き換えています。

mimiクラウドAIの構成概要.jpg

LINKLETの場合は、ウェアラブルデバイスであるTHINKLETの制御がポイントになります。Webのフロントエンドからカメラやマイクのオン/オフなどのメッセージを送る時は、バックエンドを経由して「THINKLET制御基盤」にデバイス制御リクエストを送り、そこから実際のデバイスにメッセージを伝える仕組みです。一方、デバイス側からはリクエストへの応答やデバイス内のデータ(バッテリー残量や位置情報など)が制御基盤経由でバックエンドに返ってきます。これにより、LINKLETのWebフロントエンド上でもデバイスの状態をリアルタイムに把握できます。

LINKLETの構成概要.jpg

LINKLETの事業では、遠隔業務支援とデバイス管理を行う同サービスに加え、お客さまごとに異なる機能を制御したりデバイスの貸し出し状況を管理したりする自社のバックオフィス向けの「LINKLET管理Web」を運用しています。さらに、まだ開発中のプロダクトですが、THINKLETで録画した映像を解析して見やすく表示する「映像解析システム」もあります。

「一人二役以上」のチーム構成と新たな挑戦

下記の表は、ここまでご紹介したシステムの採用言語をまとめたものです。バックエンドは、Rustがメインです。mimiの音声処理エンドポイントではC++を、mimiの一部サービスやサーバーレス構成のTHINKLET制御基盤ではPythonも使っていますが、そのほかのLINKLET・LINKLET管理Web・映像解析システムはRustで構築しています。フロントエンドはほぼTypeScriptで作っている一方、コマンドラインインターフェース(CLI)ベースの運用ツールはほぼ全てRustで作られており、Rustの割合は高まっています。

サービスごとの技術スタック.jpg

当社のエンジニアは、フロントエンド(TypeScript)、バックエンド(Rust)、クラウドインフラストラクチャー(Amazon Web Services / Google Cloud Platform)などの役割のうち、一人当たり二役以上を兼任する形でチームを組んでいます。APIビジネスから始まった当社はフロントエンドの経験者がおらず、当初は開発を外部委託していましたが、コミュニケーションコストの高さが課題となったため、機能追加の節目にフロント/バックエンドを一貫して担当する体制に切り替えました。現在は、社内エンジニアのスキルアップを促しながら、必要に応じて外部パートナーにサポートしてもらう形を採っています。

当社でC++からRustへの移行を進めてから、5年ほどが経ちました。Rustのメモリ安全性によって安心して開発できるというメリットはもちろん、書いていて楽しいという声もあり、採用でも「Rustを使いたい」というエンジニアが入社してくれるケースが増えました。

一方、Rustや各種クレート(ライブラリ)は非常に進化が速いため、プロダクトごとに使っているフレームワークやバージョンにばらつきが出てきます。バージョンアップが大変な面もありますが、レイヤードアーキテクチャの採用や継続的インテグレーション/継続的デリバリー(CI/CD)の整備など、"一般的なWeb開発で大事とされること"をRust開発でも実践することで、この課題に対応しています。

Rustならではの課題として「ビルドに時間がかかる」というものがありますが、ビルド高速化のノウハウについては@tatsuya6502さんこと当社の河野がZennでまとめているので、興味のある方は併せてご覧ください。

Rustプロジェクトのビルド高速化に関するベストプラクティス(ローカル環境編)

今後は、AI関連の新しいツールにおけるRustの有効性の検証や、バックエンド中心だったRustの適用領域の拡大など、Rustを使った開発においてさまざまな挑戦を検討しています。組織は今まさに拡大期で、新しいフェーズに向けて一緒に働いていただける方を募集しています。Rustの経験はもちろん、他言語での豊富な知見をお持ちの方も歓迎していますので、気になった方はカジュアル面談からでもご応募いただけたら幸いです。[1]

Loading...Loading...Loading...
脚注
  1. 本記事は、2025年4月17日に開催されたイベントの内容を元に編集した記事です

プロフィール