폼 검증
폼 검증(Form Validation): 회원가입 폼으로 배우는 검증 흐름
이 가이드는 Remix에서 간단한 회원가입 폼을 구현하며 폼 검증을 적용하는 과정을 단계별로 보여줘요. 여기서는 action, 액션 데이터, 에러 렌더링처럼 Remix 폼 검증의 핵심 요소를 이해하는 데 집중할게요. 검증 규칙 자체보다는 메커니즘의 큰 그림을 잡는 데 목표를 두죠.
본문
1단계: 회원가입 폼 만들기
Remix의 Form 컴포넌트를 사용해 기본 회원가입 폼부터 만드세요.
import { Form } from "@remix-run/react";
export default function Signup() {
return (
<Form method="post">
<p>
<input type="email" name="email" />
</p>
<p>
<input type="password" name="password" />
</p>
<button type="submit">Sign Up</button>
</Form>
);
}
2단계: action 정의하기
다음으로 Signup 컴포넌트와 같은 파일에 서버 action을 정의해요. 여기서는 폼 검증 규칙이나 에러 객체 구조를 깊이 파기보다는 동작 메커니즘을 넓게 보여주는 게 목적이라, 이메일과 비밀번호에 대한 기초적인 검사만 사용할게요.
import type { ActionFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json, redirect } from "@remix-run/node"; // or cloudflare/deno
import { Form } from "@remix-run/react";
export default function Signup() {
// omitted for brevity
}
export async function action({
request,
}: ActionFunctionArgs) {
const formData = await request.formData();
const email = String(formData.get("email"));
const password = String(formData.get("password"));
const errors = {};
if (!email.includes("@")) {
errors.email = "Invalid email address";
}
if (password.length < 12) {
errors.password =
"Password should be at least 12 characters";
}
if (Object.keys(errors).length > 0) {
return json({ errors });
}
// Redirect to dashboard if validation is successful
return redirect("/dashboard");
}
검증 에러가 있으면 action에서 클라이언트로 반환돼요. 이게 "고쳐야 할 게 있다"고 UI에 알리는 신호이고, 문제가 없다면 사용자는 대시보드로 리다이렉트되죠.
3단계: 검증 에러 표시하기
마지막으로 Signup 컴포넌트를 수정해 검증 에러가 있을 때 표시하게 해요. useActionData로 에러에 접근해 보여줄게요.
import type { ActionFunctionArgs } from "@remix-run/node"; // or cloudflare/deno
import { json, redirect } from "@remix-run/node"; // or cloudflare/deno
import { Form, useActionData } from "@remix-run/react";
export default function Signup() {
const actionData = useActionData<typeof action>();
return (
<Form method="post">
<p>
<input type="email" name="email" />
{actionData?.errors?.email ? (
<em>{actionData?.errors.email}</em>
) : null}
</p>
<p>
<input type="password" name="password" />
{actionData?.errors?.password ? (
<em>{actionData?.errors.password}</em>
) : null}
</p>
<button type="submit">Sign Up</button>
</Form>
);
}
export async function action({
request,
}: ActionFunctionArgs) {
// omitted for brevity
}
결론
이렇게 해서 Remix에서 기본 폼 검증 흐름을 성공적으로 구성했어요. 이 방식의 장점은 에러가 action 데이터에 기반해 자동으로 표시되고, 사용자가 폼을 다시 제출할 때마다 갱신된다는 점이에요. 그 덕분에 작성해야 하는 보일러플레이트 코드가 줄어들고 개발 과정이 더 효율적이 돼요.