devlog study react nextjs server-action
Next.js Server Action ๐
๋ด์ด๋ณด๊ธฐ
-
ํด๋ผ์ด์ธํธ(Browser๋ Server Component)์์ ํธ์ถํ ์ ์๋, ์๋ฒ์์ ์คํ๋๋ ํจ์
- ์๋ฒ์์๋ง ์คํํ ์ ์๋ ๋์์ ๋ธ๋ผ์ฐ์ ์์ ์คํํ๋ ๊ฒ
"use server"์ถ๊ฐํ๋ฉด ์๋ฒ์ก์ ์ผ๋ก ์คํ๋จ- ์๋ฒ์ก์ ์ ์คํํ๋ API๊ฐ ์์ฑ๋์ด ๋ธ๋ผ์ฐ์ ์์ ํด๋น ์๋ฒ์ก์ ์ ์คํํ๋ ์์ ์ ํ์๋ ์ด API๋ฅผ ํธ์ถํ๊ฒ ๋จ
- server action์ ๋ฌด์กฐ๊ฑด server์์ ํธ์ถ
-
ํด๋ผ์ด์ธํธ ์ฝ๋(์: ์ปดํฌ๋ํธ, ํผ)์์ ์๋ฒ ์ฝ๋๋ฅผ ์ง์ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ฅ
- The resulting Server Functions can be passed to Client Components through props.
- ๋ณ๋์ API ๋ผ์ฐํธ๋ฅผ ์ ์ํ ํ์ ์์ด ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ๋ฐ์ดํฐ ํต์ ์ ๊ฐ์ํ
-
Because the underlying network calls are always asynchronous,ย
'use server'ย can only be used on async functions.Promise๋ฅผ ๋ฆฌํดํ๋ ํจ์๋ง export ๊ฐ๋ฅ!
-
๊ฐ๊ฒฐํ๊ณ ๊ฐ๋จํ๊ณ ํธํ๊ณ ์์ ํ๊ฒ ์๋ฒ์์ ์คํํ๋ ์ฝ๋๋ฅผ ๋ง๋ค์ ์์!
- ์๋ฒ์์๋ง ์คํ๋๋ ์ฝ๋์ด๊ธฐ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ์์๋ ํธ์ถ๋ง ๊ฐ๋ฅ
- โ ๋ณด์์ ๋ฌธ์ ๊ฐ ๋๋ ์ฝ๋๋ฅผ ๋ค๋ฃจ๊ธฐ ์ข์
- ์๋ฒ์์๋ง ์คํ๋๋ ์ฝ๋์ด๊ธฐ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ์์๋ ํธ์ถ๋ง ๊ฐ๋ฅ
-
HTML
<form>action์์ฑ์ ์๋ฒ ์ก์ ํจ์๋ฅผ ์ง์ ํ๋ฉด, ํผ ์ ์ถ ์ ์ ๋ ฅ๋ ๋ฐ์ดํฐ๊ฐ ์๋์ผ๋กformData๊ฐ์ฒด๋ก ๊ตฌ์ฑ๋จ- ํด๋น ์๋ฒ ์ก์ ํจ์์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ
- ์ด ๊ฐ์ฒด์์
get๋ฉ์๋๋ก ํ์ํ ๊ฐ์ ์ถ์ถ
-
revalidatePath(path)- ์ด ์ต์ ์ผ๋ก ์๋ฒ์ก์ ์ผ๋ก ์ป์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ก ํ๋ฉด์ ๋ ๋๋ง ํ ์ ์์
- ์๋ฒ ์ปดํฌ๋ํธ์์๋ง ํธ์ถ ๊ฐ๋ฅ
- ํด๋น ๊ฒฝ๋ก์ cache๋ ๋ฐ์ดํฐ, full-route-cache๋ ๋ฌดํจํ๋จ
- ๋ฐ์ดํฐ๊ฐ ์ญ์ ๋๊ณ ๋ค์ ์์ฑ๋์ง๋ ์์
- 1)์๋ก๊ณ ์นจ ํ 2)๋ค์ ํด๋น ํ์ด์ง์ ์ ์ํ๋ฉด dynamic page์ฒ๋ผ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋งํ๊ณ , ํด๋น ํ์ด์ง๋ฅผ full-route-cache๋ก ๋ฑ๋ก
-
useActionState- ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ Server Action์ ์ฌ์ฉํ ๋, ํผ ์ ์ถ ์ํ(๋ก๋ฉ ์ค ์ฌ๋ถ ๋ฑ)๋ฅผ ๊ด๋ฆฌํ๊ณ ์ค๋ณต ์ ์ถ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ถ์ฅ๋๋ React ํ
์๋ฌธ๊ฐ๊ธฐ
Sever Action์ async await์ ๋ถ์ด์ง ์์๋ ์๋ํ๋ค?
Next Auth๋ก SNS ๋ก๊ทธ์ธ์ ๊ตฌํํ๋๋ฐ, login ์๋ฒ์ก์ ์ ํธ์ถํ ๋
await์์ด๋ ๋ก๊ทธ์ธ์ด ๋๋๊ฑธ ํ์ธ
// @/app/sign/sign.action.ts
"use server";
import { signIn, signOut } from "@/lib/auth";
type Provider = "google" | "github" | "naver" | "kakao";
export const login = async (provider: Provider, callback?: string) => {
await signIn(provider, { redirectTo: callback || "/bookcase" });
};
export const logout = async () => {
await signOut({ redirectTo: "/" });
};// @/app/sign/google-login-button.tsx
'use client';
import { Button } from "@/components/ui/button";
import { login } from "./sign.action";
export function GoogleLoginButton() {
return (
<Button
onClick={() => login("google")} /> // async - await ์์ด๋ ์คํ O!
// ...
)
// ...
}1. Server Action ์,
- Next.js App Router์์ ํด๋ผ์ด์ธํธ(Browser๋ Server Component)์์ ํธ์ถํ ์ ์๋, ์๋ฒ์์ ์คํ๋๋ ํจ์
use server์ ์ธ์ผ๋ก ํ์๋ ํจ์- ํญ์ ์๋ฒ์์๋ง ์คํ๋จ (hydration X)
- ํธ์ถํ๋ฉด Promise๋ฅผ ๋ฐํ โ ๋ธ๋ผ์ฐ์ - ์๋ฒ ์ฌ์ด์ API ํธ์ถ์ Next.js๊ฐ ์ฒ๋ฆฌํด์ฃผ๊ธฐ ๋๋ฌธ์ API route๋ฅผ ๋ฐ๋ก ๋ง๋ค์ง ์์๋ OK
2. async / await๋ ์ ์ฐ๋๊ฑฐ์ง?
JS์ single thread ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด!
- ๋น๋๊ธฐ ์์
(
Promise,callback)์ ๋๊ธฐ์ ์ผ๋ก ์คํํ๊ฒ ํด์คawait: Promise์ ์คํ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดasync: ์ด๊ฒ ๋ถ์ ํจ์๋ ํญ์Promise๋ฅผ ๋ฆฌํดํ๋๋ก ํจ โawait์ฌ์ฉ ๊ฐ๋ฅ
3. ๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ await ์์ด๋ ์๋ฒ์ก์
์ด ์คํ๋ ๊น?
- ์ ์ฝ๋๋ฅผ ๋ณด๋ฉด, ๋ฒํผ์ onClick ์ด๋ฒคํธ์ login ์๋ฒ์ก์ ์ ํธ์ถํ๋ ํ์ดํ ํจ์๊ฐ ์คํ๋๋ค
- login ์๋ฒ์ก์
์ ํธ์ถํ๋ฉด Next Auth๋ ๋ด๋ถ์ ์ผ๋ก Redirect๋ฅผ ์ผ์ผํจ๋ค
- await ์ฌ๋ถ์ ์๊ด์์ด(๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํด๋ฐ๋์ง์ ๊ด๊ณ์์ด) ํด๋น ์๋ฒ์ก์ ์ ํธ์ถํ๋ฉด ๋ธ๋ผ์ฐ์ ๊ฐ ๊ณง๋ฐ๋ก ์ด๋
- ์ ์ ์ ์ฅ์์๋ ํ๋ฉด์ด ์ ํ๋๊ธฐ๋๋ฌธ์ = ๋ก๊ทธ์ธ ๋ ํ์ด์ง๋ก ์ด๋ํ๊ธฐ๋๋ฌธ์ ๋์ผํ ๋์์ ํ๋๊ฒ์ฒ๋ผ ๋ณด๊ฒ ๋จ
4. ๊ทธ๋ฌ๋ฉด ์ธ์ await์ ์ฌ์ฉํ ๊น?
- server action์ ๊ฒฐ๊ณผ(๋ฆฌํด)๊ฐ์ ์ฌ์ฉํ๊ฑฐ๋
- ์คํ ์๋ฃ๋ฅผ ๋ณด์ฅํ๊ณ ์ถ์๋
- ๋ง์ฝ ์๋์ฒ๋ผ Promise ๋ฆฌํด ๊ฐ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ผ๋ฉด
async / await์ ๊ผญ ํ์ํจ!
// ๊ฒฐ๊ณผ๊ฐ ํ์ O โ await ํ์
onClick={async () => {
const user = await login("google");
console.log(user); // Promise ๋ฆฌํด๊ฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
}}Server Action์์ async/await ์ฌ์ฉ ๊ตฌ๋ถ
| ์ก์ ์ข ๋ฅ | ์์ | await ํ์ ์ฌ๋ถ | ์ด์ |
|---|---|---|---|
| ๋ฆฌ๋ค์ด๋ ํธ ๊ธฐ๋ฐ ์ก์ | signIn(), signOut() (NextAuth) | โ ์ ํ์ | ํธ์ถ๋ง ํด๋ ๋ธ๋ผ์ฐ์ ๋ฆฌ๋ค์ด๋ ํธ๊ฐ ์ผ์ด๋๋ฏ๋ก Promise ๊ฒฐ๊ณผ๋ฅผ ์ ์จ๋ ๋จ |
| ๋ฐ์ดํฐ ๋ฐํ ์ก์ | DB ์กฐํ, API ํธ์ถ ๊ฒฐ๊ณผ ๋ฐํ | โ ํ์ | ๋ฐํ๋ ๋ฐ์ดํฐ๋ฅผ UI๋ ๋ก์ง์์ ํ์ฉํด์ผ ํ๋ฏ๋ก ๋ฐ๋์ ๊ฒฐ๊ณผ ๋๊ธฐ ํ์ |
| ๋ถ์ ํจ๊ณผ(side effect)๋ง ์๋ ์ก์ | ๋ก๊ทธ ๊ธฐ๋ก, ํต๊ณ ์ ์ฅ | โ ์ ํ์ | ๊ฒฐ๊ณผ๊ฐ์ด ์ค์ํ์ง ์๊ณ ์คํ๋ง ๋ณด์ฅ๋๋ฉด ๋จ. ๋จ, ์คํ ์๋ฃ ํ์ธํ๋ ค๋ฉด await ํ์ |
| ํ์ ๋ก์ง์ด ์๋ ์ก์ | ๋ก๊ทธ์ธ ํ toast("์ฑ๊ณต") ๋์ฐ๊ธฐ | โ ํ์ | ์ก์
์ด ๋๋ ๋ค์๋ง ์คํ๋ผ์ผ ํ๋ฏ๋ก await ํ์ |
| ์๋ฌ ํธ๋ค๋ง์ด ํ์ํ ๊ฒฝ์ฐ | try/catch๋ก ์ก์์ ์ฒ๋ฆฌ | โ ํ์ | await์ด ์์ผ๋ฉด ์๋ฌ๊ฐ Promise์ ๋ฌถ์ฌ์ catch๋์ง ์์ |