네, React Query의 mutate
와 mutateAsync
차이점을 노션(Notion)에 정리하기 쉽도록 작성해 드릴게요. 아래 내용을 그대로 복사해서 붙여넣으시면 됩니다.
mutate
vs mutateAsync
핵심 차이점 💡React Query에서 서버 데이터를 변경(Create, Update, Delete)할 때 useMutation
훅을 사용합니다. 이 훅은 mutate
와 mutateAsync
라는 두 가지 함수를 제공하며, 두 함수의 가장 큰 차이는 비동기 처리 방식과 그에 따른 후속 작업의 유연성에 있습니다.
mutate
(+ onSuccess)mutate
는 "실행하고 잊어버리는(fire-and-forget)" 방식으로 동작합니다. 요청을 보낸 후 결과를 기다리지 않고 다음 코드를 즉시 실행하며, 성공/실패에 따른 로직은 useMutation
훅을 정의할 때 옵션으로 전달하는 콜백 함수(onSuccess
, onError
) 에서 처리합니다.
useMutation
훅 내부에 고정됩니다.mutate
를 호출하든 항상 동일한 onSuccess
로직이 실행되므로 유연성이 떨어집니다.const { mutate } = useMutation(updateTodo, {
// 성공 시 실행될 로직이 이곳에 '고정'됩니다.
onSuccess: (data) => {
console.log('업데이트 성공:', data);
queryClient.invalidateQueries(['todos']); // 캐시 무효화
},
onError: (error) => {
console.error('업데이트 실패:', error);
},
});
const handleUpdate = () => {
// mutate 함수는 바로 리턴되며, 위의 onSuccess 콜백이 나중에 실행됩니다.
mutate({ id: 1, text: '새로운 할 일' });
console.log('업데이트 요청을 보냈습니다.');
};
mutateAsync
mutateAsync
는 Promise
를 반환합니다. 따라서 async/await
문법을 사용하여 비동기 작업의 흐름을 동기적인 코드처럼 순차적으로 제어할 수 있습니다. 성공 및 실패 처리를 try...catch
블록 안에서 직접 할 수 있습니다.
mutateAsync
를 호출하는 곳에서 자유롭게 정의할 수 있습니다.try...catch
구문을 매번 작성해야 할 수 있습니다.const { mutateAsync, isLoading } = useMutation(updateTodo);
const handleSubmit = async () => {
try {
console.log('업데이트를 시작합니다.');
// await: 요청이 성공할 때까지 여기서 코드 실행을 기다립니다.
const data = await mutateAsync({ id: 1, text: '새로운 할 일' });
// ✅ 성공 시에만 실행될 로직을 자유롭게 작성
console.log('업데이트 성공:', data);
alert('성공적으로 업데이트 되었습니다!');
// 예: 성공 후 페이지 이동
// router.push('/todos');
} catch (error) {
// ❌ 실패 시 실행될 로직
console.error('업데이트 실패:', error);
}
};