낙관적 UI 업데이트
사용자가 어떤 동작을 했을 때, 서버 응답을 기다리지 않고 "먼저 성공했다고 가정하고 UI를 업데이트"하는 방식을 낙관적 UI 업데이트(Optimistic UI Updates)라고 합니다.
예를 들어, SNS에서 좋아요 버튼을 눌렀을 때 서버 응답을 기다렸다가 하트가 빨개진다면 느리게 느껴집니다.
하지만 버튼 클릭과 동시에 바로 하트가 빨개지면 유저는 빠른 반응성을 경험할 수 있습니다.
이후 서버에서 응답이 도착하면 실제 데이터와 동기화됩니다.
useOptimistic
React 18.3부터 도입된 새로운 훅으로, 낙관적 UI 업데이트를 쉽게 구현하도록 도와줍니다.
- 기존에는 useState나 useReducer를 직접 조작해야 했음
- useOptimistic은 서버 액션(Server Actions)과 결합했을 때 특히 깔끔하게 동작
기본 사용법
"use client";
import { useOptimistic } from "react";
import { addComment } from "@/app/actions";
export default function CommentList({ comments }: { comments: string[] }) {
// 1) 낙관적 상태 관리
const [optimisticComments, addOptimisticComment] = useOptimistic(
comments,
(state, newComment: string) => [...state, newComment]
);
async function handleAddComment(formData: FormData) {
const comment = formData.get("comment") as string;
// 2) UI 먼저 업데이트
addOptimisticComment(comment);
// 3) 실제 서버 액션 호출
await addComment(comment);
}
return (
<div>
<ul>
{optimisticComments.map((c, i) => (
<li key={i}>{c}</li>
))}
</ul>
<form action={handleAddComment}>
<input type="text" name="comment" placeholder="댓글 입력..." />
<button type="submit">추가</button>
</form>
</div>
);
}
- 사용자가 댓글 입력 → addOptimisticComment 호출
- UI 즉시 반영 (optimisticComments)
- 서버 액션 실행 → DB 업데이트
- 서버에서 새 props 내려오면 UI 최종 확정
- useOptimistic 훅은 두 가지 값을 리턴
- optimisticComments → 현재 낙관적 상태(= UI에 즉시 반영될 데이터)
- addOptimisticComment → 낙관적 상태를 업데이트하는 함수
- 즉, useState처럼 [state, setState] 패턴인데, 낙관적 업데이트 전용 버전이라 보시면 됩니다.
- comments 는 서버에서 내려온 실제 데이터의 초기값입니다.
- useOptimistic는 여기서 시작해서 낙관적으로 변형된 버전을 관리합니다
- state → 현재의 낙관적 상태 (optimisticComments)
- newComment → 우리가 UI에 추가하고 싶은 새 값
useOptimistic vs useState
| 구분 | useState | useOptimistic |
| 주 목적 | 로컬 상태 관리 | 낙관적 업데이트 관리 |
| 서버 연동 | 직접 코드 작성 필요 | 서버 액션과 자연스럽게 결합 |
| UX 반응 속도 | 느림(서버 응답 이후) | 빠름(응답 전 UI 즉시 반영) |
예시 - 좋아요 버튼
"use client";
import { useOptimistic } from "react";
import { toggleLike } from "@/app/actions";
export default function LikeButton({ initialLiked }: { initialLiked: boolean }) {
const [optimisticLiked, setOptimisticLiked] = useOptimistic(
initialLiked,
(_, newState: boolean) => newState
);
async function handleClick() {
setOptimisticLiked(!optimisticLiked);
await toggleLike(); // 서버 요청
}
return (
<button onClick={handleClick}>
{optimisticLiked ? "❤️ 좋아요" : "🤍 좋아요"}
</button>
);
}
'개발 공부 > React' 카테고리의 다른 글
| React App Router, Page Route (0) | 2025.10.19 |
|---|---|
| Server Components, Client Components (0) | 2025.09.03 |
| Zustand (1) (2) | 2025.08.17 |
| React Recoil (3) | 2025.08.16 |
| React Query, Redux Toolkit Query (0) | 2025.06.22 |