useTransition vs useOptimistic

발행: (2025년 12월 8일 오후 08:00 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

useTransition vs. useOptimistic 커버 이미지

동적인 듀오: 프로세스 관리 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
  );
}

주요 차이점 요약

기능useTransitionuseOptimistic
주요 목표UI 멈춤 방지; “로딩” 상태 추적서버 확인 전에 결과를 즉시 표시
사용자 경험“잠시 기다려 주세요…” (정직한 지연)“완료!” (즉각적인 만족)
데이터 출처서버 데이터 대기클라이언트 측 예측
서버 실패 시이전 상태 유지 또는 오류 표시UI가 자동으로 올바른 서버 상태로 되돌아감

왜 함께 사용해야 할까?

useOptimisticuseTransition(또는 전환을 감싸는 Server Actions) 없이 거의 쓸모가 없습니다.

  • **useOptimistic**은 데이터를 처리합니다 (예: 100이 아닌 101 좋아요 표시).
  • **useTransition**은 실행을 처리합니다 (버튼 클릭이 서버 요청 중에 페이지를 멈추게 하지 않음).

두 가지를 결합하면 빠르고 부드러운 사용자 경험을 만들 수 있습니다.

Back to Blog

관련 글

더 보기 »