React 19가 정식 출시되면서, 개발자 경험(Developer Experience, DX) 측면에서 많은 변화가 생겼습니다.
특히 이번 버전에서는 useActionState와 use 훅이 도입되어, 기존 React 18에서보다 서버 액션과 비동기 데이터 처리가 훨씬 간단해졌습니다.
이번 글에서는 React 18과 React 19의 주요 차이점을 비교하고, useActionState를 직접 써본 경험과 react-hook-form과의 차이점까지 정리해보겠습니다.
구분 | React 18 | React 19 |
|---|---|---|
렌더링 | Concurrent Rendering, Automatic Batching | 동일 + 개선 |
Suspense | 실험적 데이터 Fetching 지원 | 공식 지원 강화 |
폼 상태 관리 | 직접 |
|
비동기 데이터 |
|
|
React 18이 렌더링 모델 개선에 집중했다면, React 19는 개발자가 상태와 서버 액션을 더 직관적으로 다루는 DX 개선이 중심입니다.
useActionState: 폼/액션 상태를 단순화const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
setError(null);
try {
await login();
} catch {
setError("로그인 실패");
} finally {
setLoading(false);
}
}상태(loading, error)를 직접 관리해야 하고
try/catch/finally 블록이 반복되어 보일러플레이트가 많음
useActionStateimport { useActionState } from "react";
async function login(prevState: any, formData: FormData) {
// 서버 액션 로직
return { success: true };
}
function LoginForm() {
const [state, action] = useActionState(login, {});
return (
<form action={action}>
<input type="email" name="email" />
<input type="password" name="password" />
<button disabled={state.pending}>
{state.pending ? "로그인 중..." : "로그인"}
</button>
{state.error && <p>{state.error}</p>}
</form>
);
}pending, error, success 상태를 자동 관리
서버 액션과 자연스럽게 연계
불필요한 상태 변수를 줄여 코드 가독성 향상
서버 액션과 상태 관리가 자연슬버게 연결되어 로딩/성공/실패 처리가 간단함
중복 코드 감소로 가독성이 좋아짐
다만 복잡한 폼 필드 관리와 validation은 여전히 react-hook-form 이 필요
import { useForm } from "react-hook-form";
function HookForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("email", { required: "필수 입력" })} />
{errors.email && <p>{errors.email.message}</p>}
<input type="password" {...register("password")} />
<button type="submit">Login</button>
</form>
);
}useActionState : 서버 액션과 결합, 단순 폼/액션 처리에 좋음
react-hook-form : 클라이언트 상태, validation, 대규모 폼에 적합
즉, React 19에서 useActionState 가 나왔다고 해서 RHF가 필요 없어진 것은 아니고, 상황에 따라 적절하게 선택하면 될 거 같습니다.
import { use } from "react";
async function fetchUser(id: string) {
const res = await fetch(`/api/user/${id}`);
return res.json();
}
function UserProfile({ userId }: { userId: string }) {
const user = use(fetchUser(userId)); // Suspense와 함께 사용 가능
return <h1>{user.name}</h1>;
}Promise를 컴포넌트 렌더링 단계에서 동기처럼 사용 가능
Suspense와 결합하면 로딩 UI 처리도 자연스럽게 가능
단순한 폼 > useActionState 추천
복잡한 validation, 다중 필드, 퍼포먼스 최적화 > react-hook-form 여전히 필요
use 훅과 함께 사용하면 데이터 fetching과 렌더링 로직이 깔끔해짐