React.js
[React.js] useOptimistic에 대하여
도옹건
2025. 7. 20. 23:22
useOptimistic란?
React 19에 새롭게 추가된 useOptimistic 훅은 낙관적 업데이트(Optimistic Updates)를 구현하기 위한 훅입니다. 사용자가 액션을 수행했을 때 서버 응답을 기다리지 않고 즉시 UI를 업데이트하여 더 나은 사용자 경험을 제공합니다.
낙관적 업데이트란?
- 즉시 UI 업데이트: 서버 응답을 기다리지 않고 UI를 먼저 변경
- 백그라운드 동기화: 동시에 서버에 요청을 보내 실제 데이터 업데이트
- 에러 처리: 실패 시 원래 상태로 되돌리기
예시코드
import { useOptimistic } from 'react';
function AppContainer() {
const [optimisticState, addOptimistic] = useOptimistic(
state,
// updateFn
(currentState, optimisticValue) => {
// merge and return new state
// with optimistic value
}
);
}
useOptimistic 훅의 매개변수와 반환값
- 매개변수
1. state (초기 상태)
- 작업이 대기 중이지 않을 때 반환될 초기 상태값입니다.
2. updateFn (업데이트 함수)
- 현재 상태와 낙관적 값을 받아서 새로운 상태를 반환하는 순수 함수입니다.- 매개변수:
currentState: 현재 상태
optimisticValue: addOptimistic에 전달된 낙관적 값
- 매개변수:
- 반환값
1. optimisticState (낙관적 상태)
- 낙관적 업데이트가 적용된 결과 상태입니다.
2. addOptimistic (낙관적 업데이트 함수)
- 낙관적 업데이트를 트리거하는 dispatch 함수입니다.
사용 예시
'use client';
import { useOptimistic, useState } from 'react';
import styles from './use-comment.module.css';
interface Comment {
id: number;
text: string;
author: string;
timestamp: string;
pending?: boolean;
}
async function addComment(text: string, author: string): Promise<Comment> {
await new Promise((resolve) => setTimeout(resolve, 1200));
return {
id: Date.now(),
text,
author,
timestamp: new Date().toISOString(),
};
}
export default function CommentOptimisticExample() {
const [comments, setComments] = useState<Comment[]>([]);
// 댓글 추가 낙관적 업데이트
const [optimisticComments, addOptimisticComment] = useOptimistic(
comments, // comments 값이 바뀌면 optimisticComments도 바뀜
(state, newComment: Comment) => {
return [...state, { ...newComment, pending: true }];
},
);
const handleAddComment = async (formData: FormData) => {
const text = formData.get('text') as string;
const author = formData.get('author') as string;
const newComment: Comment = {
id: Date.now(),
text,
author,
timestamp: new Date().toISOString(),
};
// 낙관적 업데이트
addOptimisticComment(newComment);
try {
const result = await addComment(text, author);
setComments((prev) => [...prev, result]);
} catch (error) {
console.error('댓글 추가 실패:', error);
// 에러 시 원래 상태로 되돌리기
setComments((prev) =>
prev.filter((comment) => comment.id !== newComment.id),
);
}
};
console.log(optimisticComments);
return (
<div className={styles.container}>
<h2>useOptimistic 댓글 예제</h2>
<form action={handleAddComment} className={styles.commentForm}>
<input
name="author"
placeholder="이름"
className={styles.authorInput}
required
/>
<textarea
name="text"
placeholder="댓글을 입력하세요..."
className={styles.commentInput}
required
/>
<button type="submit" className={styles.submitButton}>
댓글 작성
</button>
</form>
<div className={styles.commentList}>
{optimisticComments.map((comment) => (
<div
key={comment.id}
className={`${styles.commentItem} ${
comment.pending ? styles.pending : ''
}`}
>
<div className={styles.commentHeader}>
<strong>{comment.author}</strong>
<span className={styles.timestamp}>
{new Date(comment.timestamp).toLocaleString()}
</span>
{comment.pending && (
<span className={styles.pendingIndicator}>⏳</span>
)}
</div>
<p className={styles.commentText}>{comment.text}</p>
</div>
))}
</div>
</div>
);
}
동작 과정
1. 사용자가 댓글 입력 후 제출
↓
2. addOptimisticComment(newComment) 호출
↓
3. UI에 즉시 댓글 표시 (pending: true, ⏳ 표시)
↓
4. 백그라운드에서 addComment() 실행 (1.2초 소요)
↓
5. 서버 응답 후 setComments()로 실제 상태 업데이트
↓
6. pending 플래그 제거, ⏳ 표시 사라짐
참고
https://ko.react.dev/reference/react/useOptimistic
useOptimistic – React
The library for web and native user interfaces
ko.react.dev