Astro 페이지에서 HTML 양식 작성
요청 시 렌더링되는 Astro 페이지는 양식을 표시하고 처리할 수 있습니다. 이 레시피에서는 표준 HTML 양식을 사용하여 서버에 데이터를 제출합니다. 프런트매터 스크립트는 클라이언트에 JavaScript를 보내지 않고 서버의 데이터를 처리합니다.
:::tip[Astro 액션으로 양식 작성하기]Astro는 v4.15에서 양식 데이터 유효성 검사, 양식 제출에 따른 UI 업데이트 등 기본 HTML 양식에 비해 몇 가지 이점을 제공하는 액션을 추가했습니다. 대신 이 방법을 사용하여 양식을 작성하려면 액션 가이드를 참조하여 이러한 기능에 대해 자세히 알아보세요.:::
사전 준비 사항
- 서버 어댑터가 설치된 Astro 프로젝트
레시피
양식과 처리 코드를 포함할
.astro페이지를 생성하거나 식별합니다. 예를 들어 등록 페이지를 추가할 수 있습니다.--- --- <h1>Register</h1>일부 입력이 포함된
<form>태그를 페이지에 추가하세요. 각 입력에는 해당 입력의 값을 설명하는name속성이 있어야 합니다.양식을 제출하려면
<button>또는<input type="submit">요소를 포함해야 합니다.--- --- <h1>Register</h1> <form> <label> Username: <input type="text" name="username" /> </label> <label> Email: <input type="email" name="email" /> </label> <label> Password: <input type="password" name="password" /> </label> <button>Submit</button> </form>검증 속성을 사용하여 JavaScript가 비활성화된 경우에도 작동하는 기본 클라이언트 측 검증을 제공하세요.
이 예시에서
required는 필드가 채워질 때까지 양식 제출을 방지합니다.minlength는 입력 텍스트에 필요한 최소 길이를 설정합니다.type="email"은 유효한 이메일 형식만 허용하는 검증입니다.
--- --- <h1>Register</h1> <form> <label> Username: <input type="text" name="username" required /> </label> <label> Email: <input type="email" name="email" required /> </label> <label> Password: <input type="password" name="password" required minlength="6" /> </label> <button>Submit</button> </form>:::tip
<script>태그와 Constraint Validation API를 사용하여 여러 필드를 참조하는 사용자 정의 유효성 검사 논리를 추가할 수 있습니다.복잡한 유효성 검사 논리를 더 쉽게 작성하려면 프런트엔드 프레임워크를 사용하여 양식을 작성하고 React Hook Form 또는 Felte와 같은 양식 라이브러리를 선택할 수 있습니다.:::
양식을 제출하면 브라우저가 페이지를 다시 요청하게 됩니다. 양식 데이터를 URL 매개변수가 아닌
Request본문의 일부로 보내려면 양식의 데이터 전송method를POST로 변경하세요.--- --- <h1>Register</h1> <form method="POST"> <label> Username: <input type="text" name="username" required /> </label> <label> Email: <input type="email" name="email" required /> </label> <label> Password: <input type="password" name="password" required minlength="6" /> </label> <button>Submit</button> </form>프런트매터에서
POST메소드를 확인하고Astro.request.formData()를 사용하여 양식 데이터에 액세스합니다.try ... catch블록으로 이를 래핑하여POST요청이 양식에서 전송되지 않아formData가 유효하지 않은 경우를 처리합니다.--- export const prerender = false; // 'server' 모드에서는 필요하지 않습니다. if (Astro.request.method === "POST") { try { const data = await Astro.request.formData(); const name = data.get("username"); const email = data.get("email"); const password = data.get("password"); // 데이터로 작업을 수행합니다. } catch (error) { if (error instanceof Error) { console.error(error.message); } } } --- <h1>Register</h1> <form method="POST"> <label> Username: <input type="text" name="username" required /> </label> <label> Email: <input type="email" name="email" required /> </label> <label> Password: <input type="password" name="password" required minlength="6" /> </label> <button>Submit</button> </form>서버에서 양식 데이터의 유효성을 검사합니다. 여기에는 엔드포인트에 대한 악의적인 제출을 방지하고 양식 유효성 검사가 없는 희귀한 레거시 브라우저를 지원하기 위해 클라이언트에서 수행된 것과 동일한 유효성 검사가 포함되어야 합니다.
클라이언트에서 수행할 수 없는 유효성 검사도 포함될 수 있습니다. 예를 들어, 이 예시에서는 이메일이 이미 데이터베이스에 있는지 확인합니다.
오류 메시지는
errors객체에 저장하고 템플릿에서 액세스하여 클라이언트로 다시 보낼 수 있습니다.--- export const prerender = false; // 'server' 모드에서는 필요하지 않습니다. import { isRegistered, registerUser } from "../../data/users" import { isValidEmail } from "../../utils/isValidEmail"; const errors = { username: "", email: "", password: "" }; if (Astro.request.method === "POST") { try { const data = await Astro.request.formData(); const name = data.get("username"); const email = data.get("email"); const password = data.get("password"); if (typeof name !== "string" || name.length < 1) { errors.username += "Please enter a username. "; } if (typeof email !== "string" || !isValidEmail(email)) { errors.email += "Email is not valid. "; } else if (await isRegistered(email)) { errors.email += "Email is already registered. "; } if (typeof password !== "string" || password.length < 6) { errors.password += "Password must be at least 6 characters. "; } const hasErrors = Object.values(errors).some(msg => msg) if (!hasErrors) { await registerUser({name, email, password}); return Astro.redirect("/login"); } } catch (error) { if (error instanceof Error) { console.error(error.message); } } } --- <h1>Register</h1> <form method="POST"> <label> Username: <input type="text" name="username" /> </label> {errors.username && <p>{errors.username}</p>} <label> Email: <input type="email" name="email" required /> </label> {errors.email && <p>{errors.email}</p>} <label> Password: <input type="password" name="password" required minlength="6" /> </label> {errors.password && <p>{errors.password}</p>} <button>Register</button> </form>