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
Server-Driven UIで frontendの複雑性に立ち向かう
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
nacal
November 05, 2025
Technology
730
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Server-Driven UIで frontendの複雑性に立ち向かう
nacal
November 05, 2025
More Decks by nacal
See All by nacal
新規プロダクトにおけるシステムマイグレーションの判断
nacal
0
29
Linterからはじめるa11y
nacal
2
3.2k
Other Decks in Technology
See All in Technology
Sigmaユーザーのための有用リソース一挙公開 & Sigmaで使えるMCP #sigma_ucj /useful-resources-for-sigma-computing-users-and-mcps-with-sigma
shinyaa31
0
190
Amazon S3 Tablesに全部任せてみた結果——コンパクション/スナップショット管理は本当に手放せるか
shigeruoda
1
470
クロスボーダーM&AのValue Upを支えるプロダクト開発。日米チームのハブになったプロダクトエンジニアの実践 / Product Engineering Conference 2026
genda
0
120
「図書館」という名前のままでいいのか -Code4Lib JAPANカンファレンス2026 アンカンファレンス報告- / Code4Lib JAPAN Conference 2026: Unconference Report
ykiyota
0
160
Gitは怖い?共有ワークスペースから始めるSnowflakeチーム開発
coco_se
0
120
#jawssonic2026 あの時代が悪かった ~動かなかったSageMakerと共に迎えたイベント当日~
ktkn1129
0
140
日経電子版を支えていく Kasane Design System/fec_fukuoka
nikkei_engineer_recruiting
0
700
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
budougumi0617
1
2.6k
2026-09-11 【Snowflake World Tour Tokyo 2026】Snowflakeを起点に、AI Agentが自律稼働し続ける未来へ / Driving AI Agents with Snowflake
civitaspo
0
310
AIに丸投げしないトイル削減 / Eliminating Toil Without Leaving It All to AI
kohbis
4
1.1k
Reactの設計論
uhyo
14
7.9k
Screen Lens - 今見てる画面を翻訳する
komagata
0
240
Featured
See All Featured
Producing Creativity
orderedlist
PRO
348
41k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
330
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
690
A Modern Web Designer's Workflow
chriscoyier
699
190k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
730
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
820
Google's AI Overviews - The New Search
badams
0
1.6k
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
470
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Transcript
1 Server-Driven UIで frontendの複雑性に⽴ち向かう 中⽥ 輝 / nacal 2025.11.05 カバーとGMOペパボが語る、クリエイターの創作‧表現活動を⽀える技術
2 ⾃⼰紹介 ロリポップ‧ムームードメイン事業部 for Gamersチーム 2022年 新卒⼊社 中⽥ 輝 Nakata
Hikaru / nacal • Webアプリケーションエンジニア • フロントエンドがすきです • X : @_nacal
3 - LOLOPOP! for Gamersのゲーム設定管理 にServer-Driven UIを導⼊してみた話 - ビジネスロジックをサーバー側に寄せる ことで、frontendのコード量を削減
- UI変更の作業も簡略化 今⽇話すこと
None
5 - ServerからのResponseでUIを構成する要素を返却する(プレゼンテーションを指⽰) - クライアント側はResponseを元にUIに変換して描画するだけの責務 Server-Driven UIとは https://github.com/csmets/Server-Driven-UI
6 https://github.com/csmets/Server-Driven-UI type NewsCard { image: Image author: String postDate:
String heading: String body: [String] } type Image { url: String description: String } Client-Driven UI
7 https://github.com/csmets/Server-Driven-UI Server-Driven UI
8 https://github.com/csmets/Server-Driven-UI Server-Driven UI type NewsCard { elements: [NewsCardElement] }
type Heading implements Typography { text: String } type Paragraph implements Typography { text: String } ... union NewsCardElement = Button | Image | NewsCardMeta | Heading | Paragraphs
9 - frontendの複雑性 - 多種多様なゲームタイトル/バージョンによって⽣じるビジネスロジックの複雑化 - frontendはなるべく体験の創造に集中責務に集中したい - ゲームのアップデート対応 -
元々の実装ではゲーム単位でそれぞれPRC/Componentsが存在しており、DRYでない - ゲームの最新リリースによる設定項⽬の変更のための作業が⼤変 - schema変更、設定ファイル編集、frontend Component修正... 解決したかった課題 最新アップデートは最速で遊びたいよ!
10 - ゲームの設定項⽬のList/formにServer-Driven UIを導⼊ - 画⾯全体には適⽤しない - 更新頻度/ビジネスロジックによる分岐の複雑性 が⾼い⼀部のView -
UIを構成する要素(attrやElement)をAPIのResponseとする - backend側でビジネスロジックを完結させる - 技術要件:gRPC + Protocol Buffers 導⼊したもの
protobuf schema 11 message GetGameSettingsRequest { string server_id = 1;
} message GetGameSettingsResponse { // 設定グループ(Section) message Group { string group_id = 1; // "gameplay" string title = 2; // "ゲームプレイ設定" repeated Field fields = 3; } repeated Group groups = 1; } サーバーIDからゲーム/バージョン情報の取得 セクションレベルでの配列に格納
protobuf schema 12 // 設定フィールド message Field { string field_id
= 1; // "max_players" string label = 2; // "最大プレイヤー数" optional string description = 3; // ヘルプテキスト SettingValue value = 4; // 現在の値 // フィールドタイプごとの設定 oneof field_config { TextField text_field = 5; SliderField slider_field = 6; ToggleField toggle_field = 7; SelectField select_field = 8; …, etc. } } Fieldの共通要素と各Fieldをoneofで
protobuf schema 13 // テキスト入力フィールド message TextField { optional int32
min_length = 1; optional int32 max_length = 2; optional string pattern = 3; optional string placeholder = 4; } // セレクトフィールド message SelectField { repeated Option options = 1; optional string description = 2; } …, etc. Fieldごとに必要なattrを型として定義
export const DynamicField = ({ field, values, onChange }: Props)
=> { const commonProps = { label: field.label, description: field.description, } switch (field.fieldConfig.case) { case 'textField': { const value = values.get(field.fieldId)?.value return ( <TextField {...commonProps} value={value.case } config={field.fieldConfig.value} onChange={(newValue) => onChange( field.fieldId, new SettingValue({ value: { case: 'stringValue', value: newValue } }), ) } /> ) } case 'sliderField': { … 14 FieldTypeごとに分岐 それぞれのComponentに Responseをそのまま渡す 各Componentの中では Stylingのみのロジック frontendでの変換
15 - コード差分 - (frontend) 共通Component: +12ファイル、+1000Lines - (frontend) 特定ゲームのComponent:
-21ファイル、-1500Lines - 将来的にはこれ×対応ゲームの数削減できる - (backend) RPC: +2個 (List/Update)、共通ロジック: +150Lines、個別ロジック: +500Lines - ゲームのアップデート対応 - Responseの内容を変更するだけでUIの更新が可能になる - schemaの変更も不要、破壊的な変更にならない 「すべてのビジネスロジックはサーバーサイドで管理し、クライアントはUIのレンダリングのみを担当する」 導⼊した結果
16 - 特殊なFiledを扱うか - 現状、特定の設定項⽬にのみ適⽤されるような特殊なUIは対象外としている - 様々なケースを許容することによりschemaの複雑性も増すので判断の基準は必要 - Database-Driven UI?
- DBでUIを構成する要素を管理 - 管理⽤APIなどから項⽬の編集を可能に - アプリケーションのリリースゼロでゲームのバージョンアップ対応が可能になりそう 今後の展望
17 Thank you!