๋น๋๊ธฐ ์ก์ ์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋๋ ๊ฐ์ํ๋ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํด React์ useActionState ํ ์ ์์๋ณด์ธ์. ์ ํ๋ฆฌ์ผ์ด์ ์ ํจ์จ์ฑ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค์ธ์.
React useActionState ๊ตฌํ: ์ก์ ๊ธฐ๋ฐ ์ํ ๊ด๋ฆฌ
์ต์ ๋ฒ์ ์ ๋์
๋ React์ useActionState ํ
์ ๋น๋๊ธฐ ์ก์
์ผ๋ก ์ธํด ๋ฐ์ํ๋ ์ํ ์
๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ์ธ๋ จ๋ ์ ๊ทผ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ฐ๋ ฅํ ๋๊ตฌ๋ ํนํ React ์๋ฒ ์ปดํฌ๋ํธ(RSC) ๋ฐ ์๋ฒ ์ก์
๊ณผ ํจ๊ป ์์
ํ ๋ ๋ฎคํ
์ด์
์ฒ๋ฆฌ, UI ์
๋ฐ์ดํธ ๋ฐ ์ค๋ฅ ์ํ ๊ด๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ๊ฐ์ํํฉ๋๋ค. ์ด ๊ฐ์ด๋์์๋ useActionState์ ๋ณต์กํ ๋ถ๋ถ์ ํ์ํ๊ณ ๊ตฌํ์ ์ํ ์ค์ฉ์ ์ธ ์์ ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ก์ ๊ธฐ๋ฐ ์ํ ๊ด๋ฆฌ์ ํ์์ฑ ์ดํดํ๊ธฐ
์ ํต์ ์ธ React ์ํ ๊ด๋ฆฌ๋ ์ข
์ข
์ปดํฌ๋ํธ ๋ด์์ ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ๋ณ๋๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ก์
(์: ํผ ์ ์ถ, ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ)์ด ์ํ ์
๋ฐ์ดํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ ๋ ๊ฐ๋ฐ์๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ๋ฌ useState ํธ์ถ๊ณผ ์ ์ฌ์ ์ผ๋ก ๋ณต์กํ ์กฐ๊ฑด๋ถ ๋ก์ง์ผ๋ก ์ด๋ฌํ ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. useActionState๋ ๋ ๊นจ๋ํ๊ณ ํตํฉ๋ ์๋ฃจ์
์ ์ ๊ณตํฉ๋๋ค.
๊ฐ๋จํ ํผ ์ ์ถ ์๋๋ฆฌ์ค๋ฅผ ์๊ฐํด ๋ด
์๋ค. useActionState๊ฐ ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค:
- ํผ ๋ฐ์ดํฐ๋ฅผ ์ํ ์ํ ๋ณ์.
- ํผ์ด ์ ์ถ ์ค์ธ์ง(๋ก๋ฉ ์ํ)๋ฅผ ์ถ์ ํ๊ธฐ ์ํ ์ํ ๋ณ์.
- ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ด์ ์ํ ๋ณ์.
์ด ์ ๊ทผ ๋ฐฉ์์ ์ฝ๋๋ฅผ ์ฅํฉํ๊ฒ ๋ง๋ค๊ณ ์ ์ฌ์ ์ธ ๋ถ์ผ์น๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค. useActionState๋ ์ด๋ฌํ ๋ฌธ์ ๋ค์ ๋จ์ผ ํ
์ผ๋ก ํตํฉํ์ฌ ๋ก์ง์ ๋จ์ํํ๊ณ ์ฝ๋ ๊ฐ๋
์ฑ์ ํฅ์์ํต๋๋ค.
useActionState ์๊ฐ
useActionState ํ
์ ๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค:
- ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์ํํ๋ ๋น๋๊ธฐ ํจ์("์ก์ "). ์ด๋ ์๋ฒ ์ก์ ๋๋ ๋ชจ๋ ๋น๋๊ธฐ ํจ์๊ฐ ๋ ์ ์์ต๋๋ค.
- ์ด๊ธฐ ์ํ ๊ฐ.
์ด ํ ์ ๋ ๊ฐ์ ์์๋ฅผ ํฌํจํ๋ ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค:
- ํ์ฌ ์ํ ๊ฐ.
- ์ก์ ์ ๋์คํจ์นํ๋ ํจ์. ์ด ํจ์๋ ์ก์ ๊ณผ ๊ด๋ จ๋ ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
๊ธฐ๋ณธ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
import { useActionState } from 'react';
async function updateServer(prevState, formData) {
// ๋น๋๊ธฐ ์๋ฒ ์
๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
return '์๋ฒ ์
๋ฐ์ดํธ์ ์คํจํ์ต๋๋ค.';
}
return `์ด๋ฆ์ด ${data.name}(์ผ)๋ก ์
๋ฐ์ดํธ๋์์ต๋๋ค`;
}
function MyComponent() {
const [state, dispatch] = useActionState(updateServer, '์ด๊ธฐ ์ํ');
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const result = await dispatch(formData);
console.log(result);
}
return (
);
}
์ด ์์์์:
updateServer๋ ์๋ฒ ์ ๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๋ ๋น๋๊ธฐ ์ก์ ์ ๋๋ค. ์ด์ ์ํ์ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ต๋๋ค.useActionState๋ ์ํ๋ฅผ '์ด๊ธฐ ์ํ'๋ก ์ด๊ธฐํํ๊ณ ํ์ฌ ์ํ์dispatchํจ์๋ฅผ ๋ฐํํฉ๋๋ค.handleSubmitํจ์๋ ํผ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌdispatch๋ฅผ ํธ์ถํฉ๋๋ค.useActionState๋ ์ก์ ์คํ ์ค ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ ์ฒ๋ฆฌํ๊ธฐ
useActionState์ ์ฃผ์ ์ด์ ์ค ํ๋๋ ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ๋ด์ฅํ์ฌ ๊ด๋ฆฌํ๋ค๋ ์ ์
๋๋ค. dispatch ํจ์๋ ์ก์
์ ๊ฒฐ๊ณผ๋ก ํด๊ฒฐ๋๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํฉ๋๋ค. ์ก์
์ด ์ค๋ฅ๋ฅผ ๋์ง๋ฉด ํ๋ก๋ฏธ์ค๋ ํด๋น ์ค๋ฅ๋ก ๊ฑฐ๋ถ๋ฉ๋๋ค. ์ด๋ฅผ ์ฌ์ฉํ์ฌ UI๋ฅผ ์ ์ ํ๊ฒ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
์ด์ ์์ ๋ฅผ ์์ ํ์ฌ ๋ก๋ฉ ๋ฉ์์ง์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํด ๋ณด๊ฒ ์ต๋๋ค:
import { useActionState } from 'react';
import { useState } from 'react';
async function updateServer(prevState, formData) {
// ๋น๋๊ธฐ ์๋ฒ ์
๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
throw new Error('์๋ฒ ์
๋ฐ์ดํธ์ ์คํจํ์ต๋๋ค.');
}
return `์ด๋ฆ์ด ${data.name}(์ผ)๋ก ์
๋ฐ์ดํธ๋์์ต๋๋ค`;
}
function MyComponent() {
const [state, dispatch] = useActionState(updateServer, '์ด๊ธฐ ์ํ');
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
setIsSubmitting(true);
setErrorMessage(null);
try {
const result = await dispatch(formData);
console.log(result);
} catch (error) {
console.error("์ ์ถ ์ค ์ค๋ฅ ๋ฐ์:", error);
setErrorMessage(error.message);
} finally {
setIsSubmitting(false);
}
}
return (
);
}
์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ:
- ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ์ถ์ ํ๊ธฐ ์ํด
isSubmitting๊ณผerrorMessage์ํ ๋ณ์๋ฅผ ์ถ๊ฐํ์ต๋๋ค. handleSubmit์์dispatch๋ฅผ ํธ์ถํ๊ธฐ ์ ์isSubmitting์true๋ก ์ค์ ํ๊ณ , ์ค๋ฅ๋ฅผ ์ก์errorMessage๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.- ์ ์ถ ์ค์๋ ์ ์ถ ๋ฒํผ์ ๋นํ์ฑํํ๊ณ ์กฐ๊ฑด๋ถ๋ก ๋ก๋ฉ ๋ฐ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํฉ๋๋ค.
React ์๋ฒ ์ปดํฌ๋ํธ(RSC)์์ ์๋ฒ ์ก์ ๊ณผ ํจ๊ป useActionState ์ฌ์ฉํ๊ธฐ
useActionState๋ React ์๋ฒ ์ปดํฌ๋ํธ(RSC) ๋ฐ ์๋ฒ ์ก์
๊ณผ ํจ๊ป ์ฌ์ฉํ ๋ ๋น์ ๋ฐํฉ๋๋ค. ์๋ฒ ์ก์
์ ์๋ฒ์์ ์คํ๋๋ฉฐ ๋ฐ์ดํฐ ์์ค๋ฅผ ์ง์ ๋ณ๊ฒฝํ ์ ์๋ ํจ์์
๋๋ค. ์ด๋ฅผ ํตํด API ์๋ํฌ์ธํธ๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์๋ฒ ์ธก ์์
์ ์ํํ ์ ์์ต๋๋ค.
์ฐธ๊ณ : ์ด ์์ ๋ ์๋ฒ ์ปดํฌ๋ํธ์ ์๋ฒ ์ก์ ์ด ๊ตฌ์ฑ๋ React ํ๊ฒฝ์ด ํ์ํฉ๋๋ค.
// app/actions.js (์๋ฒ ์ก์
)
'use server';
import { cookies } from 'next/headers'; // ์์, Next.js์ฉ
export async function updateName(prevState, formData) {
const name = formData.get('name');
if (!name) {
return '์ด๋ฆ์ ์
๋ ฅํด์ฃผ์ธ์.';
}
try {
// ๋ฐ์ดํฐ๋ฒ ์ด์ค ์
๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 1000));
cookies().set('userName', name);
return `์ด๋ฆ์ด ${name}(์ผ)๋ก ์
๋ฐ์ดํธ๋์์ต๋๋ค`; // ์ฑ๊ณต!
} catch (error) {
console.error("๋ฐ์ดํฐ๋ฒ ์ด์ค ์
๋ฐ์ดํธ ์คํจ:", error);
return '์ด๋ฆ ์
๋ฐ์ดํธ์ ์คํจํ์ต๋๋ค.'; // ์ค์: Error๋ฅผ ๋์ง๋ ๋์ ๋ฉ์์ง๋ฅผ ๋ฐํํ์ธ์
}
}
// app/page.jsx (React ์๋ฒ ์ปดํฌ๋ํธ)
'use client';
import { useActionState } from 'react';
import { updateName } from './actions';
function MyComponent() {
const [state, dispatch] = useActionState(updateName, '์ด๊ธฐ ์ํ');
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const result = await dispatch(formData);
console.log(result);
}
return (
);
}
export default MyComponent;
์ด ์์ ์์:
updateName์app/actions.js์ ์ ์๋ ์๋ฒ ์ก์ ์ ๋๋ค. ์ด์ ์ํ์ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ ๋ฐ์ดํธ(์๋ฎฌ๋ ์ด์ )ํ๊ณ ์ฑ๊ณต ๋๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฐํํฉ๋๋ค. ์ค์ํ ์ ์, ์ก์ ์ด ์ค๋ฅ๋ฅผ ๋์ง๋ ๋์ ๋ฉ์์ง๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์ ๋๋ค. ์๋ฒ ์ก์ ์ ์ ์ฉํ ์ ๋ณด๋ฅผ ๋ด์ ๋ฉ์์ง๋ฅผ ๋ฐํํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค.- ์ปดํฌ๋ํธ๋
useActionStateํ ์ ์ฌ์ฉํ๊ธฐ ์ํด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ('use client')๋ก ํ์๋ฉ๋๋ค. handleSubmitํจ์๋ ํผ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌdispatch๋ฅผ ํธ์ถํฉ๋๋ค.useActionState๋ ์๋ฒ ์ก์ ์ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
์๋ฒ ์ก์ ์ ๋ํ ์ค์ ๊ณ ๋ ค์ฌํญ
- ์๋ฒ ์ก์
์์์ ์ค๋ฅ ์ฒ๋ฆฌ: ์ค๋ฅ๋ฅผ ๋์ง๋ ๋์ ์๋ฒ ์ก์
์์ ์๋ฏธ ์๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฐํํ์ธ์.
useActionState๋ ์ด ๋ฉ์์ง๋ฅผ ์๋ก์ด ์ํ๋ก ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์์ ์ฐ์ํ ์ค๋ฅ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. - ๋๊ด์ ์ ๋ฐ์ดํธ: ์๋ฒ ์ก์ ์ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด ๋๊ด์ ์ ๋ฐ์ดํธ์ ํจ๊ป ์ฌ์ฉ๋ ์ ์์ต๋๋ค. UI๋ฅผ ์ฆ์ ์ ๋ฐ์ดํธํ๊ณ ์ก์ ์ด ์คํจํ๋ฉด ๋๋๋ฆด ์ ์์ต๋๋ค.
- ์ฌ๊ฒ์ฆ(Revalidation): ์ฑ๊ณต์ ์ธ ๋ฎคํ ์ด์ ํ์๋ ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ๊ฒ์ฆํ์ฌ UI๊ฐ ์ต์ ์ํ๋ฅผ ๋ฐ์ํ๋๋ก ํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
๊ณ ๊ธ useActionState ๊ธฐ๋ฒ
1. ๋ณต์กํ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์ํ ๋ฆฌ๋์ ์ฌ์ฉ
๋ ๋ณต์กํ ์ํ ๋ก์ง์ ๊ฒฝ์ฐ, useActionState๋ฅผ ๋ฆฌ๋์ ํจ์์ ๊ฒฐํฉํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์์ธก ๊ฐ๋ฅํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ์ํ ์
๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
import { useActionState } from 'react';
import { useReducer } from 'react';
const initialState = {
count: 0,
message: '์ด๊ธฐ ์ํ',
};
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
case 'SET_MESSAGE':
return { ...state, message: action.payload };
default:
return state;
}
}
async function updateState(state, action) {
// ๋น๋๊ธฐ ์์
์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 500));
switch (action.type) {
case 'INCREMENT':
return reducer(state, action);
case 'DECREMENT':
return reducer(state, action);
case 'SET_MESSAGE':
return reducer(state, action);
default:
return state;
}
}
function MyComponent() {
const [state, dispatch] = useActionState(updateState, initialState);
return (
์นด์ดํธ: {state.count}
๋ฉ์์ง: {state.message}
);
}
2. useActionState๋ฅผ ์ฌ์ฉํ ๋๊ด์ ์ ๋ฐ์ดํธ
๋๊ด์ ์ ๋ฐ์ดํธ๋ ์ก์ ์ด ์ฑ๊ณตํ ๊ฒ์ฒ๋ผ ์ฆ์ UI๋ฅผ ์ ๋ฐ์ดํธํ ๋ค์, ์ก์ ์ด ์คํจํ๋ฉด ์ ๋ฐ์ดํธ๋ฅผ ๋๋๋ ค ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค. ์ด๋ฅผ ํตํด ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ๋ฐ์์ ์ผ๋ก ๋๊ปด์ง๊ฒ ํ ์ ์์ต๋๋ค.
import { useActionState } from 'react';
import { useState } from 'react';
async function updateServer(prevState, formData) {
// ๋น๋๊ธฐ ์๋ฒ ์
๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 1000));
const data = Object.fromEntries(formData);
if (data.name === "error") {
throw new Error('์๋ฒ ์
๋ฐ์ดํธ์ ์คํจํ์ต๋๋ค.');
}
return `์ด๋ฆ์ด ${data.name}(์ผ)๋ก ์
๋ฐ์ดํธ๋์์ต๋๋ค`;
}
function MyComponent() {
const [name, setName] = useState('์ด๊ธฐ ์ด๋ฆ');
const [state, dispatch] = useActionState(async (prevName, newName) => {
try {
const result = await updateServer(prevName, {
name: newName,
});
return newName; // ์ฑ๊ณต ์ ์
๋ฐ์ดํธ
} catch (error) {
// ์ค๋ฅ ๋ฐ์ ์ ๋๋๋ฆฌ๊ธฐ
console.error("์
๋ฐ์ดํธ ์คํจ:", error);
setName(prevName);
return prevName;
}
}, name);
async function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const newName = formData.get('name');
setName(newName); // UI๋ฅผ ๋๊ด์ ์ผ๋ก ์
๋ฐ์ดํธ
await dispatch(newName);
}
return (
);
}
3. ์ก์ ๋๋ฐ์ด์ฑ
์ด๋ค ์๋๋ฆฌ์ค์์๋ ์ก์ ์ด ๋๋ฌด ์์ฃผ ๋์คํจ์น๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋๋ฐ์ด์ฑํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ฉ์๊ฐ ํน์ ๊ธฐ๊ฐ ๋์ ํ์ดํ์ ๋ฉ์ถ ํ์๋ง ์ก์ ์ ํธ๋ฆฌ๊ฑฐํ๋ ค๋ ๊ฒ์ ์ ๋ ฅ๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค์์ ์ ์ฉํ ์ ์์ต๋๋ค.
import { useActionState } from 'react';
import { useState, useEffect } from 'react';
async function searchItems(prevState, query) {
// ๋น๋๊ธฐ ๊ฒ์์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค.
await new Promise(resolve => setTimeout(resolve, 500));
return `๊ฒ์ ๊ฒฐ๊ณผ: ${query}`;
}
function MyComponent() {
const [query, setQuery] = useState('');
const [state, dispatch] = useActionState(searchItems, '์ด๊ธฐ ์ํ');
useEffect(() => {
const timeoutId = setTimeout(() => {
if (query) {
dispatch(query);
}
}, 300); // 300ms ๋์ ๋๋ฐ์ด์ค
return () => clearTimeout(timeoutId);
}, [query, dispatch]);
return (
setQuery(e.target.value)}
/>
์ํ: {state}
);
}
useActionState๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ก์ ์ ์์ํ๊ฒ ์ ์งํ๊ธฐ: ์ก์ ์ด ์์ ํจ์(๋๋ ๊ฐ๋ฅํ ํ ๊ฐ๊น๊ฒ)์ด๋๋ก ํ์ธ์. ์ํ ์ ๋ฐ์ดํธ ์ธ์ ๋ถ์ ํจ๊ณผ๊ฐ ์์ด์ผ ํฉ๋๋ค.
- ์ฐ์ํ๊ฒ ์ค๋ฅ ์ฒ๋ฆฌํ๊ธฐ: ํญ์ ์ก์ ์์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ฌ์ฉ์์๊ฒ ์ ์ฉํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํ์ธ์. ์๋ฒ ์ก์ ์ ๊ฒฝ์ฐ ์์์ ์ธ๊ธํ๋ฏ์ด ์ค๋ฅ๋ฅผ ๋์ง๋ ๋์ ์๋ฒ ์ก์ ์์ ์ค๋ฅ ๋ฉ์์ง ๋ฌธ์์ด์ ๋ฐํํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค.
- ์ฑ๋ฅ ์ต์ ํํ๊ธฐ: ํนํ ๋์ฉ๋ ๋ฐ์ดํฐ์ ์ ๋ค๋ฃฐ ๋ ์ก์ ์ ์ฑ๋ฅ ์ํฅ์ ์ ์ํ์ธ์. ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ํผํ๊ธฐ ์ํด ๋ฉ๋ชจ์ด์ ์ด์ ๊ธฐ๋ฒ ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์.
- ์ ๊ทผ์ฑ ๊ณ ๋ คํ๊ธฐ: ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๋ฅผ ํฌํจํ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ทผํ ์ ์๋๋ก ํ์ธ์. ์ ์ ํ ARIA ์์ฑ๊ณผ ํค๋ณด๋ ํ์์ ์ ๊ณตํ์ธ์.
- ์ฒ ์ ํ ํ ์คํธ: ๋จ์ ํ ์คํธ์ ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์ก์ ๊ณผ ์ํ ์ ๋ฐ์ดํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ์ธ์.
- ๊ตญ์ ํ(i18n): ๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ, ์ฌ๋ฌ ์ธ์ด์ ๋ฌธํ๋ฅผ ์ง์ํ๊ธฐ ์ํด i18n์ ๊ตฌํํ์ธ์.
- ์ง์ญํ(l10n): ํ์งํ๋ ์ฝํ ์ธ , ๋ ์ง ํ์, ํตํ ๊ธฐํธ๋ฅผ ์ ๊ณตํ์ฌ ํน์ ์ง์ญ์ ๋ง๊ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ์กฐ์ ํ์ธ์.
useActionState ๋ ๋ค๋ฅธ ์ํ ๊ด๋ฆฌ ์๋ฃจ์
useActionState๋ ์ก์
๊ธฐ๋ฐ ์ํ ์
๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง๋ง, ๋ชจ๋ ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ ๋์ฒดํ๋ ๊ฒ์ ์๋๋๋ค. ์ฌ๋ฌ ์ปดํฌ๋ํธ์ ๊ฑธ์ณ ๊ณต์ ๋์ด์ผ ํ๋ ๋ณต์กํ ์ ์ญ ์ํ๋ฅผ ๊ฐ์ง ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฒฝ์ฐ, Redux, Zustand ๋๋ Jotai์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ ์ ํฉํ ์ ์์ต๋๋ค.
useActionState๋ฅผ ์ฌ์ฉํด์ผ ํ ๋:
- ๋จ์ํ๊ฑฐ๋ ์ค๊ฐ ๋ณต์ก๋์ ์ํ ์ ๋ฐ์ดํธ.
- ๋น๋๊ธฐ ์ก์ ๊ณผ ๋ฐ์ ํ๊ฒ ๊ฒฐํฉ๋ ์ํ ์ ๋ฐ์ดํธ.
- React ์๋ฒ ์ปดํฌ๋ํธ ๋ฐ ์๋ฒ ์ก์ ๊ณผ์ ํตํฉ.
๋ค๋ฅธ ์๋ฃจ์ ์ ๊ณ ๋ คํด์ผ ํ ๋:
- ๋ณต์กํ ์ ์ญ ์ํ ๊ด๋ฆฌ.
- ๋ง์ ์์ ์ปดํฌ๋ํธ์์ ๊ณต์ ๋์ด์ผ ํ๋ ์ํ.
- ์๊ฐ ์ฌํ ๋๋ฒ๊น ์ด๋ ๋ฏธ๋ค์จ์ด์ ๊ฐ์ ๊ณ ๊ธ ๊ธฐ๋ฅ.
๊ฒฐ๋ก
React์ useActionState ํ
์ ๋น๋๊ธฐ ์ก์
์ ์ํด ํธ๋ฆฌ๊ฑฐ๋๋ ์ํ ์
๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ๋ ฅํ๊ณ ์ฐ์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๋ก๋ฉ ๋ฐ ์ค๋ฅ ์ํ๋ฅผ ํตํฉํจ์ผ๋ก์จ ์ฝ๋๋ฅผ ๋จ์ํํ๊ณ ๊ฐ๋
์ฑ์ ํฅ์์ํค๋ฉฐ, ํนํ React ์๋ฒ ์ปดํฌ๋ํธ ๋ฐ ์๋ฒ ์ก์
๊ณผ ํจ๊ป ์์
ํ ๋ ์ ์ฉํฉ๋๋ค. ๊ทธ ๊ฐ์ ๊ณผ ํ๊ณ๋ฅผ ์ดํดํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์
์ ์ ํฉํ ์ํ ๊ด๋ฆฌ ์ ๊ทผ ๋ฐฉ์์ ์ ํํ ์ ์์ผ๋ฉฐ, ์ด๋ ๋ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ๊ณ ํจ์จ์ ์ธ ์ฝ๋๋ก ์ด์ด์ง๋๋ค.
์ด ๊ฐ์ด๋์์ ์ค๋ช
ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด, useActionState๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ํฅ์์ํฌ ์ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์
์ ๋ณต์ก์ฑ์ ๊ณ ๋ คํ๊ณ ํ์์ ๊ฐ์ฅ ์ ํฉํ ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ ์ ํํ๋ ๊ฒ์ ์์ง ๋ง์ธ์. ๊ฐ๋จํ ํผ ์ ์ถ๋ถํฐ ๋ณต์กํ ๋ฐ์ดํฐ ๋ฎคํ
์ด์
์ ์ด๋ฅด๊ธฐ๊น์ง, useActionState๋ React ๊ฐ๋ฐ ๋ฌด๊ธฐ๊ณ ์์ ๊ท์คํ ๋๊ตฌ๊ฐ ๋ ์ ์์ต๋๋ค.