📝 실무에서 자주 사용하는 React 도구들 정리
React는 라이브러리를 중심으로 필요한 도구들을 조립해 나가는 형태이기 때문에, 실무에서는 다양한 도구들이 조합되어 사용된다.
React Hook Form, createPortal 처럼 기능별로 특화된 도구들이 많다.
| 도구 | 주요 용도 | 언제 사용하는가? |
|---|---|---|
React Hook Form | 폼 상태 관리 | 인풋 입력값, 유효성 검사, 에러 메시지 처리 |
createPortal | UI 계층 분리 | 모달, 툴팁, 드롭다운처럼 부모 DOM 흐름에서 벗어나야 할 때 |
React Query (@tanstack/react-query) | 서버 상태 관리, 캐싱 | API 데이터를 불러오고, 로딩/에러/갱신 상태를 쉽게 처리할 때 |
Zod / Yup | 스키마 기반 유효성 검사 | 폼 데이터나 API 응답의 구조를 타입 기반으로 검증할 때 |
Framer Motion | 애니메이션 처리 | 자연스럽고 고급스러운 전환 효과를 구현하고 싶을 때 |
Recoil / Zustand | 전역 상태 관리 | 로그인 유저 정보, 다크모드 설정 등 앱 전역에서 공유되는 상태 처리 |
react-error-boundary | 에러 경계 처리 | 에러 발생 시 fallback UI를 선언형으로 작성할 때 |
react-intersection-observer | 뷰포트 감지 | 무한 스크롤, Lazy load, 애니메이션 트리거 등 |
react-toastify / sonner | 알림 UI | 요청 성공/실패 알림, 사용자 피드백 표시 |
date-fns / dayjs | 날짜 처리 유틸 | 날짜 계산, 포맷, 상대시간 표현 등 (3일 전, 2025-03-24 형식 등) |
이 중에서 몇 가지만 선택해서 간단히 정리해보려고 한다.
import { useForm } from 'react-hook-form';
const { register, handleSubmit, formState: { errors } } = useForm();
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register("email", { required: "이메일은 필수입니다" })} />
{errors.email && <p>{errors.email.message}</p>}
</form>
Zod와 결합하여 안전한 유효성 검사 가능⚠️ 사용 시 주의할 점
defaultValues를 지정하지 않으면 watch, reset 등 일부 기능이 예상대로 동작하지 않음useEffect로 동기화할 값은 반드시 reset() 또는 setValue()를 명시적으로 호출해야 한다.✅ 올바른 사용법
defaultValues는 useForm 내부에서 초기값으로 명확히 지정const { register, handleSubmit } = useForm({
defaultValues: { email: "" },
mode: "onBlur",
});Controller는 커스텀 컴포넌트 또는 제어 컴포넌트(Input, DatePicker 등)에만 사용mode: 'onBlur' 또는 onTouched로 validation 타이밍 조절 가능함import { createPortal } from 'react-dom';
const Modal = ({ children }) => {
return createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root') // 별도 위치에 모달 렌더링
);
};
z-index나 overflow에 영향을 받지 않도록 격리시킴⚠️ 사용 시 주의할 점
#modal-root)z-index, position: fixed 등을 부모 레이아웃에 맞춰 별도로 지정해야한다.✅ 올바른 사용법
#modal-root는 HTML 파일에 미리 정의const { data, isLoading, isError } = useQuery({
queryKey: ['user'],
queryFn: fetchUserData
});
⚠️ 사용 시 주의할 점
ZodError를 직접 파싱하지 않으면 UI에서 에러 메시지를 깔끔하게 보여주기 어렵다.try-catch 필수!✅ 올바른 사용법
zodResolver를 활용해 에러 핸들링 일관성 유지한다.const { register, formState } = useForm({
resolver: zodResolver(schema),
});const schema = z.object({
name: z.string().min(1, "이름은 필수입니다."),
});.optional(), .nullable()을 명확히 구분import { toast } from "react-toastify";
export const notifySuccess = (msg: string) => toast.success(msg);
export const notifyError = (msg: string) => toast.error(msg);
notifySuccess("저장되었습니다!");
⚠️ 사용 시 주의할 점
ToastContainer는 앱에 단 한 번만 렌더링되어야 함✅ 올바른 사용법
<ToastContainer /> 렌더링📚 참고자료