React์ experimental_useFormStatus ํ ์ ์ฌ์ฉํ์ฌ ์ค์๊ฐ ํผ ๋ชจ๋ํฐ๋ง์ ํ์ํ๊ณ UX๋ฅผ ๊ฐ์ ํ๋ฉฐ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํฉ๋๋ค. ๊ตฌํ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐฐ์ฐ์ธ์.
React experimental_useFormStatus ์ค์๊ฐ ์์ง: ๋ผ์ด๋ธ ํผ ๋ชจ๋ํฐ๋ง
ํ๋ ์น์ ๋ฐ์์ฑ์ด ๋ฐ์ด๋๊ณ ์ง๊ด์ ์ธ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์๊ตฌํฉ๋๋ค. ํผ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์์ด๋ฏ๋ก ์ฌ์ฉ์ ๊ฒฝํ(UX)์ ์ธ์ฌํ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ์ผ ํฉ๋๋ค. React์ experimental_useFormStatus
ํ
์ ํผ ์ ์ถ ์ค์ ์ค์๊ฐ ํผ๋๋ฐฑ์ ์ ๊ณตํ๋ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํฌ๊ฒ ํฅ์์ํต๋๋ค. ์ด ๊ธฐ์ฌ์์๋ ์ด ์คํ์ API์ ๊ธฐ๋ฅ์ ๋ํด ์์ธํ ์์๋ณด๊ณ , ์ฌ์ฉ ์ฌ๋ก, ๊ตฌํ ์ธ๋ถ ์ฌํญ ๋ฐ ๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ๋งค๋ ฅ์ ์ด๊ณ ์ ์ตํ ํผ์ ๋ง๋ค๊ธฐ ์ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ดํด๋ด
๋๋ค.
experimental_useFormStatus๋ ๋ฌด์์ ๋๊น?
experimental_useFormStatus
๋ React ์๋ฒ ์ปดํฌ๋ํธ์์ ์์๋ ํผ ์ ์ถ ์ํ์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋๋ก ์ค๊ณ๋ React Hook์
๋๋ค. ์ด๋ React ์ปดํฌ๋ํธ์์ ์ง์ ์๋ฒ ์ธก ๋ก์ง์ ์คํํ ์ ์๋๋ก ํ๋ ์๋ฒ ์ก์
์ ๋ํ React์ ์ง์์ ์ธ ํ์์ ์ผ๋ถ์
๋๋ค. ์ด ํ
์ ๋ณธ์ง์ ์ผ๋ก ์๋ฒ์ ํผ ์ฒ๋ฆฌ ์ํ์ ๋ํ ํด๋ผ์ด์ธํธ ์ธก ๋ทฐ๋ฅผ ์ ๊ณตํ์ฌ ๊ฐ๋ฐ์๊ฐ ๋งค์ฐ ์ํธ ์์ฉ์ ์ด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ํผ ๊ฒฝํ์ ๊ตฌ์ถํ ์ ์๋๋ก ํฉ๋๋ค.
experimental_useFormStatus
์ด์ ์๋ ํผ ์ ์ถ์ ๋ํ ์ค์๊ฐ ์
๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ๋ ค๋ฉด ๋ณต์กํ ์ํ ๊ด๋ฆฌ, ๋น๋๊ธฐ ์์
, ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ์ ์๋ ์ฒ๋ฆฌ๊ฐ ํ์ํ์ต๋๋ค. ์ด ํ
์ ์ด ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ํํ์ฌ ํผ ์ ์ถ ์ํ์ ์ก์ธ์คํ๋ ์ ์ธ์ ์ด๊ณ ๊ฐ๊ฒฐํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
experimental_useFormStatus ์ฌ์ฉ์ ์ฃผ์ ์ด์
- ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ: ํผ ์ ์ถ ์งํ ์ํฉ์ ๋ํ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ์ฌ ๋ถํ์ค์ฑ์ ์ค์ด๊ณ ์ ๋ฐ์ ์ธ ๋ง์กฑ๋๋ฅผ ํฅ์์ํต๋๋ค.
- ์ค์๊ฐ ์ค๋ฅ ์ฒ๋ฆฌ: ๊ฐ๋ฐ์๊ฐ ํผ ํ๋์ ํจ๊ป ํน์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ํ์ํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๋ ฅ์ ์์ ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ๊ฐ์ํ๋ ์ํ ๊ด๋ฆฌ: ํผ ์ ์ถ ์ํ์ ๊ด๋ จ๋ ์๋ ์ํ ๊ด๋ฆฌ์ ํ์์ฑ์ ์์ ์ฝ๋ ๋ณต์ก์ฑ์ ์ค์ ๋๋ค.
- ํฅ์๋ ์ ๊ทผ์ฑ: ๊ฐ๋ฐ์๊ฐ ๋ณด์กฐ ๊ธฐ์ ์ ํผ ์ํ์ ๋ํ ์ค์๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ์ฌ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์์ ์ ๊ทผ์ฑ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
- ์ ์ง์ ํฅ์: JavaScript๊ฐ ๋นํ์ฑํ๋๊ฑฐ๋ ๋ก๋์ ์คํจํ๋๋ผ๋ ํผ์ ๊ณ์ ์๋ํ์ฌ ๊ธฐ๋ณธ ์์ค์ ๊ธฐ๋ฅ์ ๋ณด์ฅํฉ๋๋ค.
experimental_useFormStatus ์๋ ๋ฐฉ์
์ด ํ ์ ๋ค์ ์์ฑ์ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
pending
: ํผ ์ ์ถ์ด ํ์ฌ ์งํ ์ค์ธ์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ์ธ์ ๋๋ค.data
: ํผ ์ ์ถ์ด ์ฑ๊ณตํ ํ ์๋ฒ ์ก์ ์์ ๋ฐํ๋ ๋ฐ์ดํฐ์ ๋๋ค. ์ฌ๊ธฐ์๋ ํ์ธ ๋ฉ์์ง, ์ ๋ฐ์ดํธ๋ ๋ฐ์ดํฐ ๋๋ ๊ธฐํ ๊ด๋ จ ์ ๋ณด๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค.error
: ํผ ์ ์ถ ์ค์ ๋ฐ์ํ ์ค๋ฅ์ ๋ํ ์ธ๋ถ ์ ๋ณด๋ฅผ ํฌํจํ๋ ์ค๋ฅ ๊ฐ์ฒด์ ๋๋ค.action
: ํผ์ด ์ ์ถ๋ ๋ ํธ์ถ๋ ์๋ฒ ์ก์ ํจ์์ ๋๋ค. ์ด๋ฅผ ํตํด ์ํ๋๋ ํน์ ์ก์ ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ํ UI ์์๋ฅผ ์กฐ๊ฑด๋ถ๋ก ๋ ๋๋งํ ์ ์์ต๋๋ค.
์ค์ ์์ ๋ฐ ๊ตฌํ
experimental_useFormStatus
๋ฅผ ํ์ฉํ๋ ๊ฐ๋จํ ์ฐ๋ฝ์ฒ ํผ์ ์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
์์ 1: ๊ธฐ๋ณธ ์ฐ๋ฝ์ฒ ํผ
๋จผ์ , ํผ ์ ์ถ์ ์ฒ๋ฆฌํ ์๋ฒ ์ก์ ์ ์ ์ํฉ๋๋ค(๋ณ๋์ ํ์ผ, ์: `actions.js`์ ๋ฐฐ์น).
"use server";
import { revalidatePath } from 'next/cache';
export async function submitContactForm(prevState: any, formData: FormData) {
const name = formData.get('name');
const email = formData.get('email');
const message = formData.get('message');
if (!name || !email || !message) {
return {
message: 'Please fill in all fields.',
};
}
// Simulate a database operation or API call
await new Promise((resolve) => setTimeout(resolve, 2000));
try {
// In a real application, you would send the data to your backend
console.log('Form data submitted:', { name, email, message });
// Simulate success
revalidatePath('/'); // Optional: revalidate the root route if needed
return { message: 'Thank you for your message!' };
} catch (error: any) {
console.error('Error submitting form:', error);
return { message: 'Failed to submit the form. Please try again later.' };
}
}
์ด์ experimental_useFormStatus
๋ฅผ ์ฌ์ฉํ์ฌ ํผ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํฉ๋๋ค.
'use client';
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
import { submitContactForm } from './actions';
function ContactForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
export default ContactForm;
์ด ์์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
useFormStatus
ํ ์ด ํธ์ถ๋์ด ํผ ์ ์ถ ์ํ๋ฅผ ๊ฒ์ํฉ๋๋ค.pending
์์ฑ์ ํผ์ด ์ ์ถ๋๋ ๋์ ํผ ์ ๋ ฅ ๋ฐ ์ ์ถ ๋ฒํผ์ ๋นํ์ฑํํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฌ์ฉ์๊ฐ ํผ์ ์ฌ๋ฌ ๋ฒ ์ ์ถํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.error
์์ฑ์ ํผ ์ ์ถ์ ์คํจํ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.data
์์ฑ(ํนํ, `data.message`)์ ํผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ถ๋ ํ ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์์ 2: ๋ก๋ฉ ํ์๊ธฐ ํ์
ํผ ์ ์ถ ์ค์ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ํ์ํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ๋์ฑ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ด๋ CSS ์ ๋๋ฉ์ด์ ๋๋ ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
'use client';
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
import { submitContactForm } from './actions';
function ContactForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
export default ContactForm;
CSS (์: ๋ณ๋์ CSS ํ์ผ ๋๋ ์คํ์ผ ์ง์ ๋ ์ปดํฌ๋ํธ):
.loading {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid #fff;
border-radius: 50%;
border-top-color: #0070f3; /* Example color */
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
์ด ์๋ ํผ์ด pending
์ํ์ ์์ ๋ ์ ์ถ ๋ฒํผ์ ๊ฐ๋จํ CSS ์ ๋๋ฉ์ด์
์ ์ถ๊ฐํฉ๋๋ค.
์์ 3: ์ธ๋ผ์ธ ์ค๋ฅ ์ ํจ์ฑ ๊ฒ์ฌ
์ธ๋ผ์ธ ์ค๋ฅ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ ๊ณตํ๋ฉด ์ฌ์ฉ์๊ฐ ์
๋ ฅ์์ ์ค๋ฅ๋ฅผ ์๋ณํ๊ณ ์์ ํ๊ธฐ๊ฐ ๋ ์ฌ์์ง๋๋ค. error
์์ฑ์ ์ฌ์ฉํ์ฌ ํด๋น ํผ ํ๋ ์์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
'use client';
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
import { submitContactForm } from './actions';
function ContactForm() {
const { pending, data, error } = useFormStatus();
// Simulated validation errors (replace with your actual validation logic)
const validationErrors = {
name: error?.message?.includes('name') ? 'Name is required.' : null,
email: error?.message?.includes('email') ? 'Invalid email address.' : null,
message: error?.message?.includes('message') ? 'Message is required.' : null,
};
return (
);
}
export default ContactForm;
์ด ์์์๋ ์์ ๋ ์ค๋ฅ์ ๋ฐ๋ผ ๋ค์ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค. ์ค์ ๊ตฌํ์์๋ ์๋ฒ ์ก์ ์์ฒด ๋ด์์ ๋ ์ ๊ตํ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ด ํ์ํ๋ฉฐ, ํผ ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์กฐํ๋ ์ค๋ฅ ์ ๋ณด๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ ์ค๋ฅ๋ฅผ ์ฌ๋ฐ๋ฅธ ์ ๋ ฅ ํ๋์ ๋งคํํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค.
experimental_useFormStatus ์ฌ์ฉ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ฌ์ฉ์ ๊ฒฝํ ์ฐ์ :
experimental_useFormStatus
์ฌ์ฉ์ ์ฃผ์ ๋ชฉํ๋ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๊ฒ์ ๋๋ค. ํผ ์ ์ถ ์ํ์ ๋ํ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ ํผ๋๋ฐฑ์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ๋ ๋ฐ ์ง์คํ์ธ์. - ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ: ์๊ธฐ์น ์์ ์ค๋ฅ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํฉ๋๋ค. ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๋ ์ ์ฉํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํฉ๋๋ค.
- ์ ์ ํ ๋ก๋ฉ ํ์๊ธฐ ์ฌ์ฉ: ํผ์ด ์ ์ถ๋๊ณ ์์์ ์๊ฐ์ ์ผ๋ก ์ ๋ฌํ๊ธฐ ์ํด ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ปจํ ์คํธ์ ์ ์ถ ํ๋ก์ธ์ค ๊ธฐ๊ฐ์ ์ ํฉํ ๋ก๋ฉ ํ์๊ธฐ๋ฅผ ์ ํํฉ๋๋ค.
- ์ ์ถ ์ค ํผ ์ ๋ ฅ ๋นํ์ฑํ: ํผ์ด ์ฌ๋ฌ ๋ฒ ์ ์ถ๋์ง ์๋๋ก ํผ์ด ์ ์ถ๋๋ ๋์ ํผ ์ ๋ ฅ์ ๋นํ์ฑํํฉ๋๋ค.
- ์ ๊ทผ์ฑ ๊ณ ๋ ค: ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๊ฐ ํผ์ ์ ๊ทผํ ์ ์๋์ง ํ์ธํฉ๋๋ค. ARIA ์์ฑ์ ์ฌ์ฉํ์ฌ ๋ณด์กฐ ๊ธฐ์ ์ ํผ ์ํ์ ๋ํ ์ค์๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์๋ฒ ์ธก ์ ํจ์ฑ ๊ฒ์ฌ ๊ตฌํ: ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ฐ ๋ณด์์ ๋ณด์ฅํ๊ธฐ ์ํด ํญ์ ์๋ฒ ์ธก์์ ํผ ๋ฐ์ดํฐ๋ฅผ ์ ํจ์ฑ ๊ฒ์ฌํฉ๋๋ค.
- ์ ์ง์ ํฅ์: JavaScript๊ฐ ๋นํ์ฑํ๋๊ฑฐ๋ ๋ก๋์ ์คํจํ๋๋ผ๋ ํผ์ด ์ฌ์ ํ ์๋ํ๋์ง ํ์ธํฉ๋๋ค. JavaScript๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ํผ ์ ์ถ์ ํ์ค HTML ํผ ์ ์ถ์ ์ฌ์ฉํ์ฌ ์๋ํด์ผ ํฉ๋๋ค.
- ์๋ฒ ์ก์ ์ต์ ํ: ์๋ฒ ์ก์ ์ด ํจ์จ์ ์ผ๋ก ์ํ๋๋๋ก ์ต์ ํํฉ๋๋ค. ๋ฉ์ธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ๊ณ ์ฑ๋ฅ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ์ ์๋ ์ฅ๊ธฐ ์คํ ์์ ์ ํผํฉ๋๋ค.
- ์ฃผ์ํด์ ์ฌ์ฉ (์คํ์ API):
experimental_useFormStatus
๋ ์คํ์ API์ด๋ฉฐ ํฅํ React ๋ฆด๋ฆฌ์ค์์ ๋ณ๊ฒฝ๋ ์ ์๋ค๋ ์ ์ ์ ์ํ์ธ์. ํ๋ก๋์ ํ๊ฒฝ์์ ์ฃผ์ํด์ ์ฌ์ฉํ๊ณ ํ์ํ ๊ฒฝ์ฐ ์ฝ๋๋ฅผ ์กฐ์ ํ ์ค๋น๋ฅผ ํ์ธ์. - ๊ตญ์ ํ ๋ฐ ์ง์ญํ (i18n/l10n): ๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ๋ชจ๋ ๋ฉ์์ง (์ฑ๊ณต, ์ค๋ฅ, ๋ก๋ฉ)๊ฐ ๋ค์ํ ์ธ์ด ๋ฐ ์ง์ญ์ ์ง์ํ๋๋ก ์ ์ ํ๊ฒ ๊ตญ์ ํ ๋ฐ ์ง์ญํ๋์๋์ง ํ์ธํฉ๋๋ค.
๊ธ๋ก๋ฒ ๊ณ ๋ ค ์ฌํญ ๋ฐ ์ ๊ทผ์ฑ
๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ํผ์ ๊ตฌ์ถํ ๋๋ ๋ค์ ์ฌํญ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
- ๊ตญ์ ํ (i18n): ๋ ์ด๋ธ, ์ค๋ฅ ๋ฉ์์ง ๋ฐ ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ํฌํจํ ๋ชจ๋ ํ
์คํธ๋ ์ฌ๋ฌ ์ธ์ด๋ฅผ ์ง์ํ๋๋ก ๊ตญ์ ํ๋์ด์ผ ํฉ๋๋ค.
react-intl
๋๋i18next
์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒ์ญ์ ๊ด๋ฆฌํฉ๋๋ค. - ์ง์ญํ (l10n): ๋ ์ง, ์ซ์ ๋ฐ ํตํ์ ๋ํ ํ์์ ์ฌ์ฉ์์ ๋ก์บ์ ๋ง๊ฒ ์ง์ญํ๋์ด์ผ ํฉ๋๋ค.
Intl
๊ฐ์ฒด ๋๋date-fns
์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ๊ฒ ํฌ๋งทํฉ๋๋ค. - ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ (RTL) ๋ ์ด์์: ํผ ๋ ์ด์์์ด ์๋์ด ๋ฐ ํ๋ธ๋ฆฌ์ด์ ๊ฐ์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ ์ธ์ด๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํฉ๋๋ค. CSS ๋ ผ๋ฆฌ์ ์์ฑ ๋ฐ ๋ ์ด์์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋ค์ํ ์ฐ๊ธฐ ๋ฐฉํฅ์ ๋ง๊ฒ ์กฐ์ ๋๋ ์ ์ฐํ ๋ ์ด์์์ ๋ง๋ญ๋๋ค.
- ์ ๊ทผ์ฑ (a11y): ์ ๊ทผ์ฑ ์ง์นจ์ ์ค์ํ์ฌ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๊ฐ ํผ์ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํฉ๋๋ค. ์๋ฏธ๋ก ์ HTML ์์๋ฅผ ์ฌ์ฉํ๊ณ ์ด๋ฏธ์ง์ ๋ํ ๋์ฒด ํ ์คํธ๋ฅผ ์ ๊ณตํ๊ณ ํผ์ด ํค๋ณด๋๋ก ์ ๊ทผ ๊ฐ๋ฅํ์ง ํ์ธํฉ๋๋ค. ARIA ์์ฑ์ ์ฌ์ฉํ์ฌ ๋ณด์กฐ ๊ธฐ์ ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๊ตญ์ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ: ์ ํ ๋ฒํธ, ์ฃผ์ ๋ฐ ์ฐํธ ๋ฒํธ์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ํจ์ฑ ๊ฒ์ฌํ ๋ ๊ตญ์ ํ์์ ์ง์ํ๋ ์ ํจ์ฑ ๊ฒ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ์๊ฐ๋: ๋ ์ง์ ์๊ฐ์ ์์งํ ๋ ์๊ฐ๋๋ฅผ ์ผ๋์ ๋๊ณ ์ฌ์ฉ์์๊ฒ ์ ํธํ๋ ์๊ฐ๋๋ฅผ ์ ํํ ์ ์๋ ์ต์ ์ ์ ๊ณตํฉ๋๋ค.
๊ฒฐ๋ก
React์ experimental_useFormStatus
ํ
์ ์ํธ ์์ฉ์ ์ด๊ณ ์ฌ์ฉ์ ์นํ์ ์ธ ํผ์ ๊ตฌ์ถํ๋ ๋ฐ ์๋นํ ๋ฐ์ ์ ์ ๊ณตํฉ๋๋ค. ํผ ์ ์ถ ์ํ์ ๋ํ ์ค์๊ฐ ํผ๋๋ฐฑ์ ์ ๊ณตํจ์ผ๋ก์จ ๊ฐ๋ฐ์๋ ์ฌ์ฉ์ ๋ง์กฑ๋๋ฅผ ๋์ด๊ณ ๋ถ๋ง์ ์ค์ด๋ ๋งค๋ ฅ์ ์ธ ๊ฒฝํ์ ๋ง๋ค ์ ์์ต๋๋ค. ํ์ฌ ์คํ์ API์ด์ง๋ง ํผ ์ํ ๊ด๋ฆฌ๋ฅผ ๋จ์ํํ๊ณ UX๋ฅผ ํฅ์์ํค๋ ์ ์ฌ๋ ฅ์ ํ์ํ ๊ฐ์น๊ฐ ์๋ ๋๊ตฌ์
๋๋ค. ๊ธ๋ก๋ฒ ์ ๊ทผ์ฑ ๋ฐ ๊ตญ์ ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ฌ ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ํฌ๊ด์ ์ธ ํผ์ ๋ง๋๋ ๊ฒ์ ์์ง ๋ง์ธ์. React๊ฐ ๊ณ์ ๋ฐ์ ํจ์ ๋ฐ๋ผ experimental_useFormStatus
์ ๊ฐ์ ๋๊ตฌ๋ ํ๋์ ์ด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ๋ ๋ฐ ์ ์ ๋ ์ค์ํด์ง ๊ฒ์
๋๋ค.