React 19 RC의 useActionState와 Server Actions 실험
배경
React 19 RC가 공개되면서 useActionState(이전 useFormState에서 개명)와 Server Actions에 대한 관심이 높아졌다. 기존 프로젝트에서 폼 상태 관리를 위해 react-hook-form과 react-query를 조합해서 사용하고 있었는데, 새로운 방식이 실제로 얼마나 단순화할 수 있는지 확인해보고 싶었다.
기존 방식
const { register, handleSubmit } = useForm();
const mutation = useMutation({
mutationFn: createPost,
onSuccess: () => queryClient.invalidateQueries(['posts'])
});
const onSubmit = (data) => mutation.mutate(data);
useActionState 적용
Next.js 14 App Router 환경에서 Server Action과 함께 사용해봤다.
// app/actions.ts
'use server';
export async function createPost(prevState: any, formData: FormData) {
const title = formData.get('title');
// validation & DB insert
return { success: true, message: '작성 완료' };
}
// app/components/PostForm.tsx
'use client';
import { useActionState } from 'react';
function PostForm() {
const [state, formAction, isPending] = useActionState(createPost, null);
return (
<form action={formAction}>
<input name="title" />
<button disabled={isPending}>제출</button>
{state?.message && <p>{state.message}</p>}
</form>
);
}
장단점
장점:
- 클라이언트 코드가 확실히 줄어들었다
- isPending 상태를 자동으로 제공
- Progressive Enhancement 지원 (JS 없이도 동작)
단점:
- TypeScript 타입 추론이 아직 불완전
- 복잡한 validation은 여전히 zod 같은 라이브러리 필요
- React 19가 아직 RC라 프로덕션 적용 리스크
결론
단순한 CRUD 폼에는 충분히 매력적인 방식이다. 하지만 복잡한 비즈니스 로직이 있는 폼은 여전히 기존 방식이 더 안정적이다. React 19 정식 릴리즈 이후 점진적으로 적용해볼 계획이다.