본문 바로가기

개발 공부/React

useOptimistic

낙관적 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 훅은 두 가지 값을 리턴
    1. optimisticComments → 현재 낙관적 상태(= UI에 즉시 반영될 데이터)
    2. addOptimisticComment → 낙관적 상태를 업데이트하는 함수
    3. 즉, 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