Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
サーバサイドDartを試してみた
Search
ANDPAD inc
February 25, 2021
Programming
4.9k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
サーバサイドDartを試してみた
2021/02/24 ANDPAD TechLive #2 Flutterって実際どうなの?設計からテストまで
ANDPAD inc
February 25, 2021
More Decks by ANDPAD inc
See All by ANDPAD inc
実行場所を意識させない i18n API を作った話
andpad
1
57
Go 1.27 における memory allocation の高速化
andpad
0
390
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
190
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
150
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
570
ANDPAD Ruby sponsor session in RubyKaigi 2026
andpad
0
260
AWS WAFの運用を地道に改善し、自社で運用可能にするプラクティス
andpad
2
1.3k
アプリから 360 度カメラ「RICOH THETA」に接続して写真を撮影する
andpad
0
93
アンドパッドが提供する Drinks and Local Meals と Drinkup を大公開
andpad
0
160
Other Decks in Programming
See All in Programming
Intent as Code
shoppingjaws
4
710
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
190
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
140
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
120
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
150
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
140
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
910
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
130
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
140
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
220
デプロイ直後のレイテンシスパイクを調べたら、 Railsの仕様にたどり着いた
nhsykym
0
110
Featured
See All Featured
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
230
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Thoughts on Productivity
jonyablonski
76
5.4k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
440
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
190
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
240
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
270
The browser strikes back
jonoalderson
0
1.7k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
202
76k
Transcript
サーバサイドDartを試してみた バベルの塔以前の世界へ ANDPAD Tech Live #2
1. 動機 2. なぜDartでサーバを実装するのか 3. サンプルの構成 4. サンプルのポイント解説 5. 感想
6. 実戦投入のはじめの一歩 目次 ※ FlutterやgRPCの基礎知識があることを前提にしている。本資料では、これらの詳細には触れない。
• サーバ、Webフロント、モバイルアプリで言語がばら ばらのせいか、相乗効果がない ◦ バベルの塔の建設現場っぽい • サーバのコードを読まないと、Web APIの仕様が分か らないことがある ◦
モバイルアプリエンジニアからすると、サーバの言語とツー ルに馴染みがないのでつらい 1. 動機(問題意識) 主は、人の子らが作ろうとしていた街と塔とを見ようとしてお下りになり、そして仰せられた、「なるほど、彼らは一つの民で、同じ言葉を話して いる。この業は彼らの行いの始まりだが、おそらくこのこともやり遂げられないこともあるまい。それなら、我々は下って、彼らの言葉を乱して やろう。彼らが互いに相手の言葉を理解できなくなるように」。 — 「創世記」11章1-9節
• サーバ、Webフロント、モバイルアプリで言語を統一 する ◦ ノウハウの共有ができる ◦ 担当外のコードも読みやすい ◦ フルスタック開発もできる 1.
動機(解決案)
• フルスタック開発ができる言語は2つ ◦ Javascript(Typescript込み) ◦ Dart • モバイルアプリ開発では、Javascript(ReactNative)よ りも、Dart(Flutter)の方が勢いがある 2.
なぜDartでサーバを実装するのか ※厳密にいえばGoなどでも全部開発できるが、この 2つの言語以外はロマンだと思う。
• サーバをDartで実装してみました ◦ サンプルコード ▪ https://github.com/KamikazeZirou/dart-ser ver-sample ◦ おなじみのTodoアプリ ▪
バックエンドのAPIのみ 3.サンプルの構成(概要)
3.サンプルの構成(アーキテクチャ) Repository MySQL Domain Model Service gRPC Handler API Client
Handler:APIのエントリポイント。データ形式の変換をして、 gRPCを隠蔽する。 Service:ビジネスロジックを担当。ロジックが単純すぎるので Repositoryのメソッド呼ぶだけ。 DomainModel:データとビジネスロジックを持つ。サンプルは単純すぎるので単なる構造体。 Repository:データのCRUD機能などを提供。データの保存方法を隠蔽する。 円の外から内の依存関係は良いが、逆は NG。 Dart Server
ライブラリ バージョン 備考 Flutter 1.26.0.17.6.pre beta channel, Dart 2.12。 grpc
3.0.0 このバージョンではDart 2.12以上が必要。 protoファイルからのコード生成は割愛。 公式の説明をお勧めします。 https://grpc.io/docs/languages/dart/ mysql1 0.17.1 MySQLドライバ。 riverpod 0.13.0-nullsafety.3 DIに使う。 3.サンプルの構成(利用ライブラリ) mysql1以外は、モバイルアプリ開発でも珍しくはない
3.サンプルの構成(開発環境) ツール 説明 Docker MySQLサーバとDartサーバを動かす用。 Dockerを使わなくてもサーバは起動できるが、実務ではコンテナとしてデプロイ することが多いので Dockerを使う。 protoc gRPCのAPIを定義するprotoファイルから各言語のコードを生成するツール。
protoc_plugin protoファイルからDartのクライントコードとサーバコードを生成するツール。 Dart のプラグイン。 Android Studio コードエディタ。サーバ独自の設定は不要。 もちろん、InteliJやVSCodeでもOK。
3.サンプルの構成(開発環境) service TodoService { rpc CreateTodo (CreateTodoRequest) returns (CreateTodoResponse) {}
} message Todo { int32 id = 1; string title = 2; string description = 3; } message CreateTodoRequest { // 作成するTodo Todo todo = 1; } message CreateTodoResponse { // 作成したTodo Todo todo = 1; } 補足:gRPCのコード生成 protoファイル Dart コード Go コード JS コード protocで 生成
4.サンプルのポイント解説(main) void main(List<String> arguments) async { final container = ProviderContainer();
var listener = container.listen(todoServiceHandlerProvider); // 1. serviceHandler の作成 final serviceHandler = await listener.read(); // 2. serviceHandler をgRPCのServerに登録 final server = Server( [serviceHandler], const <Interceptor>[], CodecRegistry(codecs: const [GzipCodec(), IdentityCodec()]), ); // 3. サーバ起動 await server.serve(port: 5001); ... }
4.サンプルのポイント解説(Handler) // 1. Handlerにはprotocが生成したAPIサーバ用の基底クラスを継承させる class TodoServiceHandler extends TodoServiceBase { //
2. APIに対応するメソッドがあるのでoverrideする @override Future<grpc.CreateTodoResponse> createTodo(ServiceCall call, grpc.CreateTodoRequest request) async { // 3. データをgRPC -> domain形式に変換 // 4. Serviceのメソッドを呼ぶ final newTodo = await _todoService.create(domain.Todo( title: request.todo.title, description: request.todo.description, )); // 5. Serviceの処理結果をgRPC形式に変換して返す return CreateTodoResponse( todo: grpc.Todo( id: newTodo.id, title: newTodo.title, description: newTodo.description, )); } } 形式変換をするのは、 Service がgRPCに依存しないようにす るため。
• Service ◦ サンプルではRepositoryのAPI呼ぶだけ • Repository ◦ モバイルアプリの時と同じように実装すればOK 4.サンプルのポイント解説(Service/Repository)
riverpodを使用。 Handler、Service、 Repositoryのオブジェクト のProviderを実装。 // MySQLConnection のプロバイダ final dbConnectionProvider =
Provider.autoDispose((ref) async { ... final connection = await MySqlConnection.connect(settings); ... return connection; }); // Repository のプロバイダ。 // ref.watch で依存オブジェクトを取得する。 // ここでは、MySQLConnection を取得している。 final todoRepositoryProvider = Provider.autoDispose((ref) => ref.watch(dbConnectionProvider).then((conn) => MySQLTodoRepository(conn))); final todoServiceProvider = Provider.autoDispose((ref) => ref .watch(todoRepositoryProvider) .then((repository) => TodoServiceImpl(repository))); final todoServiceHandlerProvider = Provider.autoDispose((ref) => ref .watch(todoServiceProvider) .then((service) => TodoServiceHandler(service))); 4.サンプルのポイント解説(DI)
マルチステージビルドを使う。 ビルド用と実行用でイメージを分け ることで、実行イメージのサイズを 抑える手法。 ビルドに使うDockerイメージのサイ ズは約250MBある。Dart SDKなど が含まれるため。 実行用のDockerイメージは、開発 用のツールが一切入っていないの
でサイズは約2.2MB。 (ビルドしたバイナリファイルのサイ ズは約8.7MB) 4.サンプルのポイント解説(Docker) # ランタイムなしで実行可能なサーバのバイナリファイルをビルドするイメージ FROM google/dart:2.12-beta as builder WORKDIR /app ADD pubspec.* /app/ RUN pub get ADD . /app RUN pub get --offline RUN dart compile exe bin/server.dart -o bin/server # ビルドしたバイナリを実行するイメージ FROM subfuzion/dart:slim WORKDIR /app COPY --from=builder /app/bin/server . CMD [] ENTRYPOINT ["./server"]
4.サンプルのポイント解説(docker-compose) • Docker単独よりもサーバの実行が簡単にできる ◦ サーバの起動時のコマンドがDockerコマンドよりも簡潔に なる ◦ コンテナ間の依存関係を設定できる ▪ DBのコンテナをDartサーバのコンテナより先に実行できる
4.サンプルのポイント解説(client) Future<void> main(List<String> args) async { // 1. gRPC接続チャンネルを作る final
channel = ClientChannel( 'localhost', port: 50051, options: ChannelOptions( credentials: ChannelCredentials.insecure(), codecRegistry: CodecRegistry(codecs: const [GzipCodec(), IdentityCodec()]), ), ); // 2. protoファイルから生成したClientのオブジェクトを作る final stub = TodoServiceClient(channel); // 3. gRPCのAPIを呼ぶ。 try { final response = await stub.createTodo( CreateTodoRequest( todo: Todo(title: 'title3', description: 'description3')), options: CallOptions(compression: const GzipCodec()), ); } catch (e) { ... } await channel.shutdown(); }
• 良かったこと ◦ アプリ開発とノウハウは共有できる ▪ riverpodは初めて使ったが、モバイルアプリ開発にも知見を転用でき る ◦ Dartの書き方をほぼ忘れていたが、Goよりは書きやすい ▪
並列処理が出てきたら、感想は変わりそう • 懸念 ◦ サーバ向けライブラリが充実していない ▪ 有力なORMが少ない • Web Framework Aqueductの一部としてならORMあるが・・・ ▪ AWSの公式SDKはなさそう・・・ 5.感想
• モバイルアプリ用のAPI Gatewayで採用する 6.実戦投入のはじめの一歩 BFFでは、API GatewayはAPIクライアント ごとの要件に沿って実装する。 開発の担当は、APIクライアント開発者が 良いらしい。クライアントの要件に詳しいの は、クライアントの開発者のため。
モバイルアプリ開発者が慣れている Dart をAPI Gatewayに採用すると、開発効率 は上がるはず。 ※今のANDPADにはAPI Gatewayなし
ANDPADでは、マイクロサービスを開発する メンバーを募集しています! こんな方におすすめです。 • アプリ開発以外もやってみたい • ユーザの業務を考えつつ開発をしたい • サービスの基盤を考えたい 最後に
番外 言語 MSにたとえると 補足 Kotlin ゲルググ Dart リック・ドムⅡ C# ドワッジ
Java ドム Go イフリート グフとドムの中間。 Rust グフ ゲームだと格闘が強い。使ったことはない。 C++ ザク C 旧ザク GCの壁