useTransition vs useOptimistic
Source: Dev.to

동적인 듀오: 프로세스 관리 vs. 인식 관리
“속도”라는 환상을 만들려면 두 가지 도구가 필요합니다:
useTransition– 백그라운드 작업을 처리합니다. 브라우저가 멈추는 것을 방지하고 작업이 진행 중인지 (isPending) 알려줍니다.useOptimistic– 즉각적인 시각적 피드백을 처리합니다. 백그라운드 작업이 성공할 것이라고 가정하고 UI를 즉시 업데이트합니다.
시나리오: “좋아요” 버튼
사용자가 게시물에 “좋아요” 버튼을 클릭한다고 가정합니다.
-
낙관적 UI 없이:
사용자가 클릭 → 1초 대기 → 숫자가 올라감. (느리게 느껴짐). -
낙관적 UI와 함께:
사용자가 클릭 → 숫자가 즉시 올라감 → 서버가 백그라운드에서 따라잡음. (빠르게 느껴짐).
표준 접근법 (useTransition만 사용)
여기서는 서버가 새로운 좋아요 수를 알려주기를 기다립니다. useTransition은 로딩 스피너를 표시해 사용자가 무언가 진행 중임을 알 수 있게 합니다.
경험: 사용자가 클릭 → 스피너 표시 → 스피너 사라지고 숫자 업데이트.
'use client';
import { useTransition } from 'react';
import { incrementLike } from './actions'; // Server Action
export default function StandardLikeButton({ likeCount }) {
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(async () => {
// 1. 서버가 끝날 때까지 대기
await incrementLike();
// 2. 서버 응답 후 페이지가 다시 렌더링되면서 UI 업데이트
});
};
return (
{/* 아직 새로운 데이터를 받지 못했으니 로딩 상태 표시 */}
{isPending ? 'Updating...' : `♥ ${likeCount} Likes`}
);
}
환상 접근법 (useTransition + useOptimistic)
우리는 미래를 예측합니다. UI는 즉시 업데이트되고, 서버 요청은 백그라운드에서 실행됩니다. useTransition은 앱을 반응형으로 유지하고, useOptimistic은 즉각적인 시각 변화를 제공합니다.
경험: 사용자가 클릭 → 스피너 없이 숫자가 즉시 업데이트.
'use client';
import { useOptimistic, useTransition } from 'react';
import { incrementLike } from './actions';
export default function OptimisticLikeButton({ likeCount }) {
// 낙관적 상태: 실제 데이터 + “가짜” 새 상태를 계산하는 리듀서
const [optimisticLikes, addOptimisticLike] = useOptimistic(
likeCount,
(currentState, optimisticValue) => currentState + optimisticValue
);
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(async () => {
// 1. 환상: UI를 즉시 업데이트
addOptimisticLike(1);
// 2. 현실: 백그라운드에서 실제 서버 요청 수행
// 실패하면 React가 자동으로 낙관적 상태를 롤백합니다!
await incrementLike();
});
};
return (
{/* 낙관적(예측된) 값을 즉시 표시 */}
♥ {optimisticLikes} Likes
);
}
주요 차이점 요약
| 기능 | useTransition | useOptimistic |
|---|---|---|
| 주요 목표 | UI 멈춤 방지; “로딩” 상태 추적 | 서버 확인 전에 결과를 즉시 표시 |
| 사용자 경험 | “잠시 기다려 주세요…” (정직한 지연) | “완료!” (즉각적인 만족) |
| 데이터 출처 | 서버 데이터 대기 | 클라이언트 측 예측 |
| 서버 실패 시 | 이전 상태 유지 또는 오류 표시 | UI가 자동으로 올바른 서버 상태로 되돌아감 |
왜 함께 사용해야 할까?
useOptimistic은 useTransition(또는 전환을 감싸는 Server Actions) 없이 거의 쓸모가 없습니다.
- **
useOptimistic**은 데이터를 처리합니다 (예: 100이 아닌 101 좋아요 표시). - **
useTransition**은 실행을 처리합니다 (버튼 클릭이 서버 요청 중에 페이지를 멈추게 하지 않음).
두 가지를 결합하면 빠르고 부드러운 사용자 경험을 만들 수 있습니다.