React 19에 새로 추가된 내장 훅들 React 19에서는 use 외에도 여러 새로운 내장 훅들이 추가되었습니다:
1. useFormStatus
핵심 목적: 폼 제출 과정에서 발생하는 비동기 상태 관리 문제 해결
이전에는 폼 제출 상태를 추적하려면 직접 상태를 만들고 관리해야 했다. 이 훅은 폼의 로딩 상태를 자동으로 추적해 사용자 피드백을 쉽게 제공할 수 있게 한다.
import { useFormStatus } from "react";
function SubmitButton() {
const { pending, data, method } = useFormStatus();
return (
<button disabled={pending} type="submit">
{pending ? "제출 중..." : "제출하기"}
</button>
);
}
function SignupForm() {
return (
<form action={submitForm}>
<input name="email" />
<SubmitButton />
</form>
);
}
언제 사용하나요?
- 폼이 제출 중일 때 버튼을 비활성화하거나 로딩 상태를 표시할 때
- 폼 제출 진행 상황에 따라 UI를 다르게 보여줘야 할 때
- 여러 폼 요소에서 공통된 제출 상태를 공유해야 할 때
로그인 폼: 로그인 버튼을 클릭하면 “로그인 중…” 표시와 함께 버튼 비활성화 파일 업로드: 업로드 버튼 클릭 후 진행 상태 표시와 취소 버튼 활성화 결제 프로세스: 결제 버튼 클릭 시 “처리 중…” 표시와 중복 클릭 방지 회원가입: 가입 진행 중 모든 입력 필드 비활성화 및 진행 상태 표시
2. useFormState
핵심 목적: 서버 측 폼 처리 결과를 클라이언트에 반영하기 위한 문제 해결
서버 액션으로부터 반환된 상태(오류 메시지, 성공 데이터 등)를 폼에 자연스럽게 연결해 서버-클라이언트 간 상태 동기화를 간소화합니다.
import { useFormState } from "react";
function Form() {
const [state, formAction] = useFormState(serverAction, initialState);
return (
<form action={formAction}>
{state.error && <p className="error">{state.error}</p>}
<input name="username" />
<button type="submit">저장</button>
</form>
);
}
언제 사용하나요?
- 폼 제출 후 서버에서 반환된 상태나 에러를 처리할 때
- 서버 유효성 검사 결과를 사용자에게 보여줘야 할 때
- 폼 제출 후 UI를 업데이트해야 할 때 (성공/실패 메시지 표시 등)
로그인 실패 처리: “아이디 또는 비밀번호가 일치하지 않습니다” 메시지 표시 회원가입 유효성 검사: “이미 사용 중인 이메일입니다” 같은 서버 검증 결과 표시 주문 폼: 할인 코드 적용 후 서버에서 계산된 최종 가격 표시 설문조사: 각 단계별 제출 후 다음 질문 세트 로드
3. useOptimistic
핵심 목적: 네트워크 지연으로 인한 사용자 경험 저하 문제 해결
서버 응답을 기다리지 않고 즉시 UI를 업데이트함으로써 애플리케이션이 더 반응적으로 느껴지게 만듭니다. 특히 네트워크 환경이 좋지 않은 상황에서 체감 성능을 크게 향상시킵니다.
import { useOptimistic } from "react";
function TodoList({ todos }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(currentTodos, newTodo) => [...currentTodos, { ...newTodo, pending: true }]
);
async function addTodo(formData) {
const text = formData.get("text");
const newTodo = { id: Math.random(), text };
// 낙관적 업데이트 적용
addOptimisticTodo(newTodo);
// 실제 서버 요청
await saveTodo(newTodo);
}
return (
<>
<form action={addTodo}>
<input name="text" />
<button type="submit">추가</button>
</form>
<ul>
{optimisticTodos.map((todo) => (
<li key={todo.id} style=>
{todo.text}
</li>
))}
</ul>
</>
);
}
언제 사용하나요?
- 네트워크 지연이 사용자 경험을 저하시킬 수 있는 상황에서
- 사용자가 데이터 변경 결과를 즉시 확인해야 할 때 (좋아요, 댓글, 할일 추가 등)
- 대부분의 요청이 성공할 것으로 예상되어 바로 UI를 업데이트해도 될 때
- 소셜 미디어 인터랙션, 장바구니 업데이트, 실시간 채팅 등에 유용
소셜 미디어 좋아요: 버튼 클릭 즉시 카운트 증가, 실패 시에만 롤백 채팅 애플리케이션: 메시지 전송 즉시 대화창에 표시, 전송 중 상태 표시 쇼핑 카트: “장바구니에 추가” 즉시 반영, 네트워크 지연 없는 경험 제공 댓글 시스템: 댓글 작성 즉시 목록에 표시, 배경에서 서버 저장 진행 실시간 협업 도구: 문서 편집 내용 즉시 반영, 동기화는 배경에서 처리
4. useActionState
핵심 목적: 복잡한 서버 액션 상태 관리 문제 해결
서버 액션의 다양한 상태(대기, 성공, 실패 등)를 체계적으로 관리하고 이에 따른 UI 피드백을 제공하는 과정을 단순화합니다.
import { useActionState } from "react";
function ProfileForm() {
const [state, action] = useActionState(updateProfile, { status: "idle" });
return (
<form action={action}>
{state.status === "error" && <p>{state.error}</p>}
{state.status === "success" && <p>프로필이 업데이트되었습니다!</p>}
<input name="name" />
<button type="submit">
{state.status === "pending" ? "저장 중..." : "저장"}
</button>
</form>
);
}
언제 사용하나요?
- 서버 액션의 여러 상태(idle, pending, success, error)를 한 번에 관리할 때
- 액션 상태에 따라 다양한 UI 피드백을 제공해야 할 때
- 폼 외부에서도 서버 액션 상태를 참조해야 할 때
- 복잡한 폼 워크플로우나 다단계 프로세스를 관리할 때
다단계 가입 프로세스: 각 단계별 상태(완료, 진행 중, 오류) 관리 및 표시 복잡한 예약 시스템: 날짜 확인, 좌석 확인, 결제 처리 등 여러 단계 상태 추적 대용량 미디어 업로드: 업로드, 처리, 인코딩, 완료 등 다양한 상태 관리 비즈니스 대시보드: 여러 데이터 소스 업데이트 상태를 한 번에 관리
5. useTransition의 개선
핵심 목적: 무거운 UI 업데이트로 인한 응답성 저하 문제 해결
사용자 인터랙션은 즉시 반영하면서 무거운 계산과 렌더링은 우선순위를 낮춰 UI가 끊기는 문제를 해결합니다.
import { useTransition } from "react";
function SearchFilter() {
const [isPending, startTransition] = useTransition();
const [filter, setFilter] = useState("");
function handleChange(e) {
// 입력은 즉시 반영하되
setFilter(e.target.value);
// 무거운 필터링 작업은 우선순위를 낮춤
startTransition(() => {
applyComplexFilter(e.target.value);
});
}
return (
<>
<input value={filter} onChange={handleChange} />
{isPending && <div>필터링 중...</div>}
<ItemList />
</>
);
}
언제 사용하나요?
- 사용자 입력에 즉시 반응해야 하지만, 그로 인한 처리는 무거울 때
- 타이핑이나 UI 인터랙션이 무거운 렌더링으로 인해 느려지는 것을 방지할 때
- 대량의 데이터 필터링, 복잡한 계산, 큰 리스트 렌더링 등을 지연시켜야 할 때
- 라이브 검색, 데이터 시각화, 복잡한 폼 유효성 검사 등에 특히 유용
제품 카탈로그 필터링: 수천 개 상품 중 실시간 필터링 시 UI 응답성 유지 데이터 시각화 대시보드: 복잡한 차트와 그래프 데이터 변경 시 UI 끊김 방지 고급 검색 인터페이스: 검색어 입력 즉시 반영하되 결과 계산은 우선순위 낮춤 이미지 갤러리: 수백 장의 고해상도 이미지 필터링/정렬 시 UI 반응성 유지 코드 에디터: 구문 강조, 자동 완성 등 무거운 계산 처리하면서도 타이핑 지연 없음