楽観的更新と悲観的更新とは
アプリケーションでデータを更新するとき、
UIとサーバーのどちらを先に更新するか?
という問題が発生します。
そのときの代表的なアプローチが
- 楽観的更新(Optimistic Update)
- 悲観的更新(Pessimistic Update)
です。
この記事では、それぞれの考え方・メリット・デメリット・使い分けをわかりやすく整理します。
楽観的更新(Optimistic Update)とは
「どうせサーバー更新は成功するやろ!」 と楽観して、先にUIを更新する手法を指します。
ユーザー操作 → UI更新 → API呼び出し → 成功確認 の流れになります
メリット
- 画面に更新が反映されるのが早いため、UXが良い
- レスポンス待ち時間がゼロのため、回線が悪くても画面が更新される
デメリット
- API(サーバ側の処理)が失敗したときの巻き戻しが必要
- UIとサーバーとの整合性が一瞬ズレる
楽観的更新が向いているケース
- 「いいね」「フォロー」「お気に入り」など軽い操作
- 頻繁に行われる更新
- API 成功率が高い
コード例
updatePost: builder.mutation({
query: (post) => ({
url: `/posts/${post.id}`,
method: 'PUT',
body: post,
}),
async onQueryStarted(updatedPost, { dispatch, queryFulfilled }) {
// API処理の完了より先にdispatchでUIを更新
const patch = dispatch(
api.util.updateQueryData('getPost', updatedPost.id, (draft) => {
Object.assign(draft, updatedPost)
})
)
try {
await queryFulfilled // APIが正常の完了したらそのまま何もしない
} catch {
patch.undo() // 失敗したら取り消す!
}
},
})
いいねボタンなどは楽観的更新が採用されているケースが多いイメージですね!
悲観的更新(Pessimistic Update)とは
楽観的更新とは逆で
「念の為サーバーでの更新が成功するまでUIを更新せんとこ」 の手法です。
ユーザー操作 → API呼び出し → 成功 → UI更新 の流れになります
メリット
- UIとサーバーの整合性が常に正しい
- 失敗時のUI更新巻き戻しが不要
デメリット
- API側の処理完了を待ち、画面に更新が反映されるのが遅いため、UX若干悪くなる
- 複数人同時更新に弱いケースがある
悲観的更新が向いているケース
- データがクリティカルで失敗できない
- 更新によって他ユーザーに影響が出る
- 決済系や取引系の操作
- 整合性が非常に重要な場面
コード例
updatePost: builder.mutation({
query: (post) => ({
url: `/posts/${post.id}`,
method: 'PUT',
body: post,
}),
invalidatesTags: (result, error, post) => [{ type: 'Post', id: post.id }],
})
複数人同時操作によってデータの整合性がおかしくなりそうなケースでは悲観的更新が多く使われるイメージですね!
おわりに
最後まで読んでいただきありがとうございます!
これまではバックエンドを中心に触ることが多く、楽観的更新、悲観的更新についてはあまり考えることはなかったので良い勉強になりました!