'use server'
'use server'
๋ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋์์ ํธ์ถํ ์ ์๋ ์๋ฒ ์ธก ํจ์๋ฅผ ํ์ํฉ๋๋ค.
๋ ํผ๋ฐ์ค
'use server'
ํจ์๊ฐ ํด๋ผ์ด์ธํธ์์ ์คํ๋ ์ ์์์ ํ์ํ๊ธฐ ์ํด, ๋น๋๊ธฐ ํจ์์ ๋งจ ์์ 'use server';
๋ฅผ ์ถ๊ฐํ์ธ์. ์ฐ๋ฆฌ๋ ์ด๋ฅผ Server Actions ์ด๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
async function addToCart(data) {
'use server';
// ...
}
Server Action์ ํด๋ผ์ด์ธํธ์์ ํธ์ถํ๋ฉด, ์ง๋ ฌํ๋ ์ธ์์ ์ฌ๋ณธ์ ํฌํจํ๋ ์๋ฒ๋ก์ ๋คํธ์ํฌ ์์ฒญ์ด ์์ฑ๋ฉ๋๋ค. Server Action์ด ๊ฐ์ ๋ฐํํ๋ฉด, ๊ทธ ๊ฐ์ ์ง๋ ฌํ๋๊ณ ํด๋ผ์ด์ธํธ์ ๋ฐํ๋ฉ๋๋ค.
ํจ์ ๊ฐ๊ฐ์ 'use server'
๋ฅผ ํ๊ธฐํ๋ ๋์ , ํ์ผ์ ๋งจ ์์ ์ง์์ด๋ฅผ ์ถ๊ฐํ์ฌ ํ์ผ์ ๋ชจ๋ export๋ฅผ, ํด๋ผ์ด์ธํธ๋ฅผ ํฌํจํ ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ ์ ์๋ Server Action์ผ๋ก ํ๊ธฐํ ์ ์์ต๋๋ค.
Caveats
'use server'
๋ ํจ์ ๋๋ ๋ชจ๋์ ๋งจ ์ฒ์์ ์์ด์ผ ํฉ๋๋ค. import๋ฅผ ํฌํจํ ๋ค๋ฅธ ์ฝ๋๋ณด๋ค ์์ ์์ด์ผ ํฉ๋๋ค(์ง์์ด ์์ ์ฃผ์์ ๊ด์ฐฎ์ต๋๋ค). ๋ฐฑํฑ์ด ์๋ ๋จ์ผ ๋๋ ์ด์ค ๋ฐ์ดํ๋ก ์์ฑํด์ผ ํฉ๋๋ค.'use server'
๋ ์๋ฒ ์ธก ํ์ผ์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ฒฐ๊ณผ์ ์ธ Server Action์ props๋ฅผ ํตํด ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ์ ๊ณต๋๋ ์ง๋ ฌํ ํ์ ์ ์ฐธ๊ณ ํ์ธ์.- Server Action์ ํด๋ผ์ด์ธํธ ์ฝ๋์์ import ํ๊ธฐ ์ํด, ์ง์์ด๋ ๋ชจ๋ ์์ค์์ ์ฌ์ฉ๋์ด์ผ ํฉ๋๋ค.
- ๊ธฐ๋ณธ ๋คํธ์ํฌ ํธ์ถ์ด ํญ์ ๋น๋๊ธฐ์ด๋ฏ๋ก
'use server'
๋ ๋น๋๊ธฐ ํจ์์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. - ํญ์ Server Action์ ์ธ์๋ฅผ ์ ๋ขฐํ ์ ์๋ ์ ๋ ฅ์ผ๋ก ์ทจ๊ธํ๊ณ ๋ชจ๋ ๋ณ๊ฒฝ์ ๊ฒํ ํ์ธ์. ๋ณด์ ๊ณ ๋ ค์ฌํญ์ ํ์ธํ์ธ์.
- Server Action์ transition ์์์ ํธ์ถ๋์ด์ผํฉ๋๋ค.
<form action>
๋๋formAction
๋ก ์ ๋ฌ๋ Server Action์ ์๋์ผ๋ก transition ๋ด์์ ํธ์ถ๋ฉ๋๋ค. - Server Action์ ์๋ฒ ์ธก ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ mutation์ ์ํด ์ค๊ณ๋์์ผ๋ฉฐ ๋ฐ์ดํฐ fetching์๋ ๊ถ์ฅ๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ์๋ฒ ์ก์ ์ ๊ตฌํํ๋ ํ๋ ์์ํฌ๋ ์ผ๋ฐ์ ์ผ๋ก ํ ๋ฒ์ ํ๋์ ์ก์ ์ ์ฒ๋ฆฌํ๋ฉฐ ๋ฐํ ๊ฐ์ ์บ์ํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋ณด์ ๊ณ ๋ ค์ฌํญ
Server Action์ ๋ํ ์ธ์๋ ์์ ํ ํด๋ผ์ด์ธํธ์์ ์ ์ด๋ฉ๋๋ค. ๋ณด์์ ์ํด ํญ์ ์ ๋ขฐํ ์ ์๋ ์ ๋ ฅ์ผ๋ก ์ทจ๊ธํ์ฌ, ์ธ์๋ฅผ ์ ์ ํ๊ฒ ๊ฒ์ฆํ๊ณ ์ด์ค์ผ์ดํ ํ๋์ง ํ์ธํ์ธ์.
Server Action์์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์๊ฐ ํด๋น ์์ ์ ์ํํ ์ ์๋์ง ํ์ธํ์ธ์.
์ง๋ ฌํ ๊ฐ๋ฅ ์ธ์์ ๋ฐํ ๊ฐ
ํด๋ผ์ด์ธํธ ์ฝ๋๊ฐ ๋คํธ์ํฌ๋ฅผ ํตํด ์๋ฒ ์์ ์ ํธ์ถํ ๋ ์ ๋ฌ๋ ์ธ์๋ ๋ชจ๋ ์ง๋ ฌํ๋์ด์ผ ํฉ๋๋ค.
๋ค์์ ์ง์๋๋ Server Action ์ธ์์ ํ์ ์ ๋๋ค.
- Primitives
- ์ง๋ ฌํ ๊ฐ๋ฅํ ๊ฐ์ ํฌํจํ Iterables
- Date
- FormData ์ธ์คํด์ค
- object initializers๋ก ์ง๋ ฌํ ๊ฐ๋ฅํ ์์ฑ๊ณผ ํจ๊ป ์์ฑ๋ ์ผ๋ฐ objects
- Server Action์ธ ํจ์
- Promises
ํนํ ๋ค์์ ์ง์๋์ง ์์ต๋๋ค.
- React ์๋ฆฌ๋จผํธ ๋๋ JSX
- ์ปดํฌ๋ํธ ํจ์ ๋๋ Server Action์ด ์๋ ๋ค๋ฅธ ํจ์๋ฅผ ํฌํจํ๋ ํจ์
- ํด๋์ค
- ํด๋์ค์ ์ธ์คํด์ค์ธ ๊ฐ์ฒด(์ธ๊ธ๋ ๋ด์ฅ ๊ฐ์ฒด ์ ์ธ)๋๋ null ํ๋กํ ํ์ ์ด ์๋ ๊ฐ์ฒด
- ์ ์ญ์ ๋ฑ๋ก๋์ง ์์ Symbol, ์.
Symbol('my new symbol')
์ง์๋๋ ์ง๋ ฌํ ๊ฐ๋ฅํ ๋ฐํ ๊ฐ์ ๊ฒฝ๊ณ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ ์ง๋ ฌํ ๊ฐ๋ฅํ props์ ๋์ผํฉ๋๋ค.
์ฌ์ฉ๋ฒ
Server Action ํ์
Server Action์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๋, ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ Server Function์ ํธ์ถํ๋ ๊ฒ์ ๋๋ค. ๋ธ๋ผ์ฐ์ ์์ HTML form ์๋ฆฌ๋จผํธ๋ ์ฌ์ฉ์๊ฐ mutation์ ์ ์ถํ๋ ์ ํต์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค. React ์๋ฒ ์ปดํฌ๋ํธ๋ก, React๋ forms์์ Server Action์ ๋ํ ์ต์์ ์ง์์ ์ ๊ณตํฉ๋๋ค.
์ฌ์ฉ์๊ฐ ์ฌ์ฉ์ ์ด๋ฆ์ ์์ฒญํ ์ ์๋ ์์์ด ์์ต๋๋ค.
// App.js
async function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}
export default function App() {
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
);
}
์์์์ requestUsername
๋ <form>
๋ฅผ ํตํ Server Action์ด๋ค. ์ฌ์ฉ์๊ฐ ์ด ์์์ ์ ์ถํ๋ฉด ์๋ฒ ํจ์์ธ requestUsername
์ ๋คํธ์ํฌ ์์ฒญ์ด ์์ต๋๋ค. form์์ Server Action์ ํธ์ถํ ๋ React๋ form์ FormData๋ฅผ Server Action์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๊ณตํฉ๋๋ค.
Server Action์ from action
์ ์ ๋ฌํ์ฌ, React๋ form์ ์ ์ง์ ํฅ์ํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฒ๋ค์ด ๋ก๋๋๊ธฐ ์ ์ ์์์ ์ ์ถํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
form์์ ๋ฐํ ๊ฐ ์ฒ๋ฆฌ
username ์์ฒญ form์์, username์ ์ฌ์ฉํ ์ ์์ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. requestUsername
์ ์คํจ ์ฌ๋ถ๋ฅผ ์๋ ค์ฃผ์ด์ผ ํฉ๋๋ค.
์ ์ง์ ํฅ์์ ์ง์ํ๋ฉฐ Server Action์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก UI๋ฅผ ์
๋ฐ์ดํธํ๋ ค๋ฉด, useFormState
๋ฅผ ์ฌ์ฉํ์ธ์.
// requestUsername.js
'use server';
export default async function requestUsername(formData) {
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
// UsernameForm.js
'use client';
import { useFormState } from 'react-dom';
import requestUsername from './requestUsername';
function UsernameForm() {
const [returnValue, action] = useFormState(requestUsername, 'n/a');
return (
<>
<form action={action}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
<p>Last submission request returned: {returnValue}</p>
</>
);
}
๋๋ถ๋ถ์ Hook๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก useFormState
๋ client code์์๋ง ํธ์ถํ ์ ์์ต๋๋ค.
<form>
์ธ๋ถ์์ Server Action ํธ์ถํ๊ธฐ
Server Action์ ๋ ธ์ถ๋ ์๋ฒ ์๋ํฌ์ธํธ์ด๋ฉฐ ํด๋ผ์ด์ธํธ ์ฝ๋ ์ด๋์์๋ ํธ์ถํ ์ ์์ต๋๋ค.
form ์ธ๋ถ์์ Server Action์ ์ฌ์ฉํ ๋, transition์์ ์๋ฒ ์ก์ ์ ํธ์ถํ๋ฉด ๋ก๋ฉ ์ธ๋์ผ์ดํฐ๋ฅผ ํ์ํ๊ณ , ๋๊ด์ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ํ์ํ๋ฉฐ ์๊ธฐ์น ์์ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. Form์ transition์ Server Action์ ์๋์ผ๋ก ๋ํํฉ๋๋ค.
import incrementLike from './actions';
import { useState, useTransition } from 'react';
function LikeButton() {
const [isPending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);
const onClick = () => {
startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
};
return (
<>
<p>Total Likes: {likeCount}</p>
<button onClick={onClick} disabled={isPending}>Like</button>;
</>
);
}
// actions.js
'use server';
let likeCount = 0;
export default async function incrementLike() {
likeCount++;
return likeCount;
}
Server Action ๋ฐํ ๊ฐ์ ์ฝ์ผ๋ ค๋ฉด ๋ฐํ๋ promise๋ฅผ await
ํด์ผํฉ๋๋ค.