Next.js Server Action์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ ์ฌ์ฉ๋ฒ
Next.js์ ์๋ฒ ์ก์
(Server Action)์ Next.js 13.4 ๋ฒ์ ์์ App Router์ ํจ๊ป ์ ์์ผ๋ก ๋์
๋ ๊ธฐ๋ฅ์
๋๋ค. ์ด๋ ์๋ฒ์์ ์คํ๋๋ ํจ์(Server-side function)๋ฅผ React ์ปดํฌ๋ํธ ๋ด์์ ์์ฝ๊ฒ ํธ์ถํ ์ ์๋๋ก ๋์์ค๋๋ค. use server ์ง์์ด๊ฐ ์๋ ํจ์๋ฅผ ์ ์ํ๋ฉด ํด๋ผ์ด์ธํธ์์ ๊ฐํธํ๊ฒ ์๋ฒ ๋ก์ง์ ํธ์ถํ ์ ์๊ฒ ๋ฉ๋๋ค.
์๋ฒ ์ก์ ์ ํ์ฉํ๋ฉด ๊ธฐ์กด์ฒ๋ผ ๋ณ๋์ API ์๋ํฌ์ธํธ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํ์ง ์์๋ ๋ฉ๋๋ค. ๊ฐ๋ฐ์๋ ์๋ฒ ๋ก์ง์ ์๋ํฌ์ธํธ, ์ธํฐํ์ด์ค ๋ฑ์ ์ ๊ฒฝ ์ธ ํ์ ์์ด, ๋ง์น ๋ก์ปฌ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ์์ฐ์ค๋ฝ๊ฒ ์๋ฒ ๋ก์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฒ ์ก์ ์ด ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ํต์ ์ ์ถ์ํํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์๋ฒ ์ก์ ์ ์ ์ํ๋ ๋ฐฉ์์ผ๋ก๋ React ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ ์ํ๋ ๋ฐฉ๋ฒ๊ณผ ๋ณ๋์ ํ์ผ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ ์ํ๋ ๋ฐฉ์์ด ์์ต๋๋ค. ๋ค์์ ๋ณ๋์ ํ์ผ์ ์ ์ํ๋ ๋ฐฉ์์ ๋๋ค.
'use server';
export default async function createAction({ name, age, email }: { name: string; age: number; email: string; }) {
await connection.query(
'INSERT INTO users (name, age, email) VALUES (?, ?, ?)',
[name, age, email]
);
}
'use client';
import createAction from './create-action.ts';
export default function CreateForm() {
return (
<form action={createAction}>
<input type="text" name="name" />
<input type="number" name="age" />
<input type="email" name="email" />
</form>
)
}
์๋ฒ ์ก์ ์ ๋ด๋ถ ๋์ ๋ฐฉ์
์์์ ์๋ก ๋ CreateForm ์ปดํฌ๋ํธ๋ ๋น๋ ์ ๋ค์๊ณผ ๊ฐ์ ํํ๋ก ๋ณํ๋ฉ๋๋ค. (์ฐธ๊ณ : ์ด๋ ์ดํด๋ฅผ ๋๊ธฐ ์ํ ์ฝ๋์ด๋ฉฐ, ์ค์ ๋น๋๋ ์ฝ๋์๋ ์ฐจ์ด๊ฐ ์์ ์ ์์ต๋๋ค.)
'use client';
import { startTransition } from 'react'
import { callServer } from 'next/client/app-call-server';
// ์๋ฒ ์ก์
ID๋ก ๋ณํ๋จ
const createAction = '$$action_1234567890';
export default function CreateForm() {
return (
<form
onSubmit={async (e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = {
name: formData.get('name'),
age: Number(formData.get('age')),
email: formData.get('email')
};
// startTransition์ผ๋ก UI ๋ธ๋กํน ๋ฐฉ์ง
startTransition(() => {
callServer(createAction, [data]);
});
}}
>
<input type="text" name="name" />
<input type="number" name="age" />
<input type="email" name="email" />
</form>
)
}
์ฆ, ์๋ฒ ์ก์
ํจ์๋ฅผ ๋ก์ปฌ ํจ์์ฒ๋ผ importํด์ ์ฌ์ฉํ๋ ๋ถ๋ถ์ด ์ฌ๋ผ์ง๊ณ , ๋์ onSubmit ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋ formData๊ฐ ์ฒ๋ฆฌ๋๊ณ Next.js์์ ์ ๊ณตํ๋ callServer ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค.
callServer ํจ์๋ ๋ด๋ถ์ ์ผ๋ก fetch API๋ฅผ ์ฌ์ฉํด HTTP ์์ฒญ์ ์ํํฉ๋๋ค. ์์ฒญ ๋ฉ์๋๋ POST๋ก ์ค์ ๋์ด ์์ผ๋ฉฐ, ํค๋์๋ ์์ฑ๋ ์๋ฒ ์ก์
ID ๋ฑ์ด ํฌํจ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ์๋ฒ ์ธก์์ ์ด๋ค ์ก์
์ด ํธ์ถ๋์๋์ง๋ฅผ ์๋ณํ ์ ์์ต๋๋ค. Next.js์ Repository์์ app-call-server.ts ํ์ผ์ ์ฐธ๊ณ ํ๋ฉด ์ด๋ฌํ ๋์ ๋ฐฉ์์ ํ์ธํ ์ ์์ต๋๋ค.
์๋ฒ ์ฌ์ด๋์์๋ callServer๋ก๋ถํฐ ์์ฒญ์ ๋ฐ์ action-handler.ts ํ์ผ์ด ์ฒ๋ฆฌํฉ๋๋ค. ์ด ํธ๋ค๋ฌ๋ CSRF ๋ณดํธ ๋ฑ์ ๊ฒ์ฆ ๊ณผ์ ์ ๊ฑฐ์น ํ, ์์ฒญ ํค๋๋ฅผ ๋ถ์ํ์ฌ ์ ์ ํ ์ก์
์ ์๋ณํ๊ณ ๋ก์ง์ ์ํํ ๋ค ์๋ต์ ๋ฐํํ๋ ํ๋ฆ์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
์๋ฒ ์ก์ ์ด ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ฐ์ ธ์จ ๋ณํ
2010๋ ๋ ์ดํ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ ์ฌ์ด์ ๊ฒฝ๊ณ๊ฐ ๋ช ํํ๊ณ , ์ด๋ฅผ ๋๋๋๋ ์์ ์ ์ข ์ข ๋ฒ๊ฑฐ๋ก์ ์ต๋๋ค. Next.js์ ์๋ฒ ์ก์ ์ ์ด๋ฌํ ๊ฒฝ๊ณ๋ฅผ ์๋น ๋ถ๋ถ ์ ๊ฑฐํ์ฌ ๊ฐ๋ฐ์์๊ฒ ๋งค์ฐ ํธ๋ฆฌํ ํ๊ฒฝ์ ์ ๊ณตํฉ๋๋ค.
๊ธฐ์กด์๋ REST API ์๋ํฌ์ธํธ๋ฅผ ๋ง๋ค์ด ํด๋ผ์ด์ธํธ๊ฐ HTTP ์์ฒญ์ ํตํด ํธ์ถํ๋ ๋ฐฉ์์ด ์ผ๋ฐ์ ์ด์์ต๋๋ค. ํ์ง๋ง ์๋ฒ ์ก์ ์ ๋ก์ปฌ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฏ ์ง๊ด์ ์ด๊ณ ๊ฐ๋จํ ํํ๋ก ์ฌ์ฉํ ์ ์์ด ํธ์์ฑ์ด ๋ฐ์ด๋ฉ๋๋ค.
์์ ์๋ "Full Stack"์ด "Poor Stack"์ด๋ผ๋ฉฐ ์กฐ๋กฑ๋ฐ๊ธฐ๋ ํ์ง๋ง, AI ์๋์ ์ ์ด๋ค๋ฉด์ ๊ฐ๋ฐ์ ํ ์ฌ๋์ด ํ ์ ์๋ ์ผ์ด ํฌ๊ฒ ๋์ด๋ Full Stack์ ์์์ด ๋์์ก์ต๋๋ค. ์ด์ ๋ ์๋ฒ ์ก์ ๊ณผ ๊ฐ์ ๊ธฐ์ ๋๋ถ์ ๋์ฑ ์ฝ๊ณ ํจ์จ์ ์ผ๋ก ํ์คํ ๊ฐ๋ฐ์ด ๊ฐ๋ฅํด์ก์ต๋๋ค.
ํธ๋ฆฌํ์ง๋ง ๋์ณ์๋ ์ ๋๋ ์๋ฒ ์ก์ ์ ๋ณด์ ๋ฌธ์
Next.js์ ์๋ฒ ์ก์ ์ ๋ง์น ๋ง๋ฒ์ฒ๋ผ ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ฐ๊ฒฐ๋ ๋ฏํ ๋๋์ ์ค๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ง๋ฒ ๊ฐ์ ํธ์์ฑ ๋ค์๋ ๋ฐ๋์ ๋ณด์์ด๋ผ๋ ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์ค์ ๋ก๋ HTTP ์์ฒญ๊ณผ ์๋ต์ด ์กด์ฌํ๋ฉฐ, ์ด ๊ณผ์ ์์ ๋ค์ํ ๋ณด์์ ๊ณ ๋ ค ์ฌํญ๋ค์ด ์กด์ฌํฉ๋๋ค.
Next.js ๊ณต์ ๋ฌธ์์์๋ ์๋ฒ ์ก์ ์ ๋ณด์์ ๋ํ ์ฃผ์๋ฅผ ๋น๋ถํ๊ณ ์์ต๋๋ค. ์ด ์ ์ ๋์น ๊ฐ๋ฐ์๋ ์๋ํ์ง ์๊ฒ ์ค์ํ ๋ก์ง์ ๋ฌด๋ฐฉ๋น๋ก ๋ ธ์ถ์ํฌ ์ ์์ผ๋ฉฐ, ์ด๋ ๋งค์ฐ ์น๋ช ์ ์ธ ๋ณด์ ์ด์๋ก ์ด์ด์ง ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.(์ํ๊น๊ฒ๋ Security ์น์ ์ ๊ฐ์ฅ ๋ง์ง๋ง ์น์ ์ ๋๋ค.)
By default, when a Server Action is created and exported, it creates a public HTTP endpoint and should be treated with the same security assumptions and authorization checks. This means, even if a Server Action or utility function is not imported elsewhere in your code, it's still publicly accessible.
๋ฌธ์ ์ด๋ฐ ์๋ฒ ์ก์ ์ ๋ง๋ฒ์ ํ๋ ค ๋ง์ง๋ง Security ์น์ ๊น์ง ๋ณด์ง ๋ชปํ ์ํ๊น์ด ๊ฐ๋ฐ์๋ค์ ์๋ฌด๋ฐ ์ ๊ธ์ฅ์น๋ฅผ ๋ฌ์ง ์์ ์๋ฒ ํจ์๋ฅผ ์จ์ธ์์ ๊ณต๊ฐํด๋ฒ๋ฆด ์ ์์ต๋๋ค. ์ธ์ฆ, ์ธ๊ฐ๊ฐ ํ์ํ๋ฐ ๊ฒ์ฆ๊ณผ์ ์ ๋์ง ์์๋ค๋ฉด ๋ ์์ฐํฉ๋๋ค.
Next.js ์๋ฒ ์ก์ ์ด ์ ๊ณตํ๋ ๊ธฐ๋ณธ์ ์ธ ๋ณด์๊ณผ ๊ฐ๋ฐ์์ ์ญํ
๊ทธ๋ ๋ค๊ณ ์์ฃผ ๋ฌด๋ฐฉ๋น ์ํ๋ ์๋๋๋ค. ๊ณต์ ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด Next.js๋ ์๋ฒ ์ก์ ๊ณผ ๊ด๋ จํ์ฌ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ณธ์ ์ธ ๋ณด์ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค:
- Secure Action IDs: ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ ํต์ ์ ์ ํจ์ฑ์ ๋ด๋ถ์ ์ผ๋ก ์์ฑ๋ ID๋ก ๊ฒ์ฆํฉ๋๋ค.
- CSRF(Cross-Site Request Forgery) ๋ฐฉ์ง: ์๋ฒ ์ก์ ํธ์ถ ์ POST ์์ฒญ๋ง ํ์ฉํ๊ณ ๋์ผ ์ถ์ฒ ์์ฒญ๋ง ํ์ฉํฉ๋๋ค.
- ํด๋ก์ ๋ณ์ ๋ณดํธ: ํด๋ผ์ด์ธํธ๋ก ์ ๋ฌ๋๋ ์ํ๊ฐ์ ์ํธํ ๋ฐ ์๋ช ํ์ฌ ๋ณดํธํฉ๋๋ค.
- ์ฝ๋ ๊ฒฉ๋ฆฌ: ์๋ฒ ์ ์ฉ ์ฝ๋๋ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ๋์ง ์๋๋ก ์ฒ๋ฆฌํฉ๋๋ค.
- ์๋ฌ ๋ฉ์์ง ๋ณดํธ: ํ๋ก๋์ ํ๊ฒฝ์์๋ ๋ฏผ๊ฐํ ์์ธ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ ธ์ถํ์ง ์์ต๋๋ค.
- ๋ฏธ์ฌ์ฉ ์ก์ ์ ๊ฑฐ: ์ฌ์ฉ๋์ง ์๋ ์๋ฒ ์ก์ ์ ์๋์ผ๋ก ์ ๊ฑฐํ์ฌ ๊ณต๊ฒฉ ํ๋ฉด ์ต์ํํฉ๋๋ค.
ํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ๋ฐ๋์ ์ ๊ฒฝ ์จ์ผ ํ ๋ถ๋ถ๋ ์์ต๋๋ค:
- ๋ฐํ์ ์ ๋ ฅ๊ฐ ๊ฒ์ฆ(Validation): ํ์ ์คํฌ๋ฆฝํธ๋ ์ปดํ์ผ ์์ ํ์ ํ์ธ๋ง ๊ฐ๋ฅํ๋ฏ๋ก, ๋ฐํ์ ๊ฒ์ฆ์ด ํ์๋ค. Zod์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ฒ ์ ํ ๊ฒ์ฆํด์ผ ํฉ๋๋ค.
- ์ธ์ฆ๊ณผ ์ธ๊ฐ: ์ก์ ๋ด์์ ์ฌ์ฉ์ ๊ถํ์ ๋งค๋ฒ ์ฌํ์ธํด์ผ ํฉ๋๋ค.
- SSRF(Server Side Request Forgery) ๋ฐฉ์ง: ์ฌ์ฉ์ ์ ๋ ฅ URL ๋ฑ์ ์ ๋ขฐํ์ง ๋ง๊ณ , ๋ฐ๋์ ํ์ดํธ๋ฆฌ์คํธ ๊ธฐ๋ฐ ์ ๊ทผ๋ง ํ์ฉํด์ผ ํฉ๋๋ค.
- ์๋ฒ ๋ก์ง์ด๋ฉด ํ์์ ์ผ๋ก ๊ณ ๋ คํด์ผ ํ ์์๋ค
- ํ๊ฒฝ๋ณ์ ๋ณดํธ: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ ๋ณด ๋ฑ ์์ฐ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ๋ .env ํ์ผ์ ์ ์ฅํ์ฌ ์ค์ ๊ฐ ๋ ธ์ถ์ ๋ฐฉ์งํด์ผ ํฉ๋๋ค.
- Injection ๋ฐฉ์ง:
- SQL Injection: SQL Injection์ ๋ฐฉ์งํ๊ธฐ ์ํด์๋ ORM(Object-Relational Mapping) ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ์์ ํ๊ฒ ์์ฑํด์ผ ํฉ๋๋ค.
- XSS ๋ฐฉ์ง: sanitize-html ๋ฑ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ ฅ๊ฐ์ ๊ฒ์ฆํ๊ณ , ์ ์ฌ์ ์ธ Cross-Site Scripting ๊ณต๊ฒฉ์ ๋๋นํด์ผ ํฉ๋๋ค.
- ๋ณด์ ์ ๋ฐ์ดํธ ๋ฐ ํจ์น ๊ด๋ฆฌ: ์ฌ์ฉ ์ค์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ์ ๋ํ ์ ๊ธฐ์ ์ธ ๋ณด์ ์ ๊ฒ๊ณผ ์ ๋ฐ์ดํธ๋ฅผ ํตํด ์ทจ์ฝ์ ์ ์ฌ์ ์ ๋ฐฉ์งํด์ผ ํฉ๋๋ค.
- ๋ก๊ทธ์ ๋ชจ๋ํฐ๋ง: ์ค์ํ ์๋ฒ ์ด๋ฒคํธ์ ์ค๋ฅ์ ๋ํ ๋ก๊ทธ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ๋ชจ๋ํฐ๋ง ์์คํ ์ ํตํด ์ค์๊ฐ ๋ณด์ ์ํ์ ํ์งํ๋๋ก ์ค์ ํด์ผ ํฉ๋๋ค.
๋ฐํ์ ์ ๋ ฅ๊ฐ ๊ฒ์ฆ ๋ฐ ์ธ์ฆ๊ณผ ์ธ๊ฐ๋ next-safe-action, zsa ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ์ ์ถ์ฒํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ถ์ํ๋ API๋ฅผ ์ ์ธ์ ์ผ๋ก ์์ฑํ ์ ์๊ณ , ์ ๊ณต๋๋ ๋ฏธ๋ค์จ์ด๋ฅผ ํตํด ์ธ์ฆ ๋ฐ ์ธ๊ฐ๋ฅผ ์์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์๋ฒ๋ฟ ์๋๋ผ ํด๋ผ์ด์ธํธ ์ธก ์๋ฒ ์ก์ ๊ด๋ จ Hooks๋ฅผ ์ ๊ณตํด ๋์ฑ ํธ๋ฆฌํ๊ฒ ํ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
๋์ฑ ์ค์ํด์ง๋ ํ๋ก ํธ์๋ ๋ณด์
๊ฐ์ธ์ ์ผ๋ก ํ๋ก ํธ์๋ ์์ญ์์ ์๋ฒ ์ฌ์ด๋ ๊ธฐ๋ฅ์ด ๋ค์ ๋ถ์ํ๋ ํ๋ฆ์ ๊ธ์ ์ ์ผ๋ก ๋ณด๊ณ ์์ต๋๋ค.
๊ณผ๊ฑฐ ์น ๊ฐ๋ฐ ์ด๊ธฐ์๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ์ ๊ตฌ๋ถ์ด ๋ช ํํ์ง ์์์ต๋๋ค. ๊ทธ๋ฌ๋ SPA(Single Page Application)์ ๋ชจ๋ฐ์ผ ์ฑ ์๋์ ํ๋ก ํธ์๋์์ ์๋ฒ์ ์กด์ฌ๊ฐ์ด ์ฝํด์ก๊ณ , ํด๋ผ์ด์ธํธ ์ธก์์ ๋ง์ ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ๋์์ต๋๋ค. ์ฌ์ง์ด ์น ํ๋ก ํธ์๋๋ฅผ ๊ณง ํด๋ผ์ด์ธํธ๋ก ์ดํดํ๋ ์ฌ๋๋ค๋ ์๊ฒจ๋ฌ์ต๋๋ค. ์ด๋ ๋ชจ๋ฐ์ผ ์ฑ ํ๊ฒฝ์ ํจํด์ด ์น ํ๊ฒฝ์ผ๋ก ๋์ด์๊ธฐ ๋๋ฌธ์ ๋๋ค.
ํ์ง๋ง ์น์ ๋ชจ๋ฐ์ผ ์ฑ๊ณผ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅด๋ฉฐ, ์๋ฒ์ ๊ธด๋ฐํ ์ฐ๋๋ ๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋ฐํํฉ๋๋ค. ํด๋ผ์ด์ธํธ ์ค์ฌ SPA์ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ณ ์ SEO์ ์ ๋ฆฌํ Next.js์ ๊ฐ์ SSR(Server Side Rendering)์ ์ง์ํ๋ ํ๋ ์์ํฌ๊ฐ ์ธ๊ธฐ๋ฅผ ๋๊ธฐ ์์ํ์ต๋๋ค. ์ด์ ๋ SSR์ ๋์ด ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ๋ฑ์ฅํ๋ ๋ฑ ํ๋ก ํธ์๋์์๋ ์๋ฒ ๊ธฐ๋ฅ์ ๋ค์ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ๋ ํ๋ฆ์ด ๋ํ๋๊ณ ์์ต๋๋ค.
Next.js์ App Router์ ์๋ฒ ์ก์ ์ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ UI๋ฟ ์๋๋ผ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์๋ฒ ๋ก์ง๊น์ง ํญ๋๊ฒ ๋ด๋นํ ์ ์๋ ๊ธฐ๋ฐ์ ๋ง๋ค์ด ์ฃผ์์ต๋๋ค. ์ฌ๋งํผ ๋ณต์กํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋ ์ด์ DB๊ฐ ์กด์ฌํ๋๋ผ๋ ์ด์ ๋ ๋ฆฝ์ ์ธ ๋ฐฑ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ด ๊ฐ๋ฐ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ ๊ฐ๋ฐ์์๊ฒ ํจ์จ์ ์ธ ๊ฐ๋ฐ ๊ฒฝํ์ ์ ๊ณตํ์ง๋ง, ๋์์ ๋ ๋ง์ ๋ณต์ก์ฑ๊ณผ ๋ณด์์ ๋ํ ์ฑ ์์ด ๋ฐ๋ฆ ๋๋ค.

AI ์๋์ ๋ณด์๊ณผ Next.js
AI๊ฐ ์ฃผ๋ชฉ๋ฐ๋ ์๋๊ฐ ์ค๋ฉด์ ์ฃผ์ ํ๋ ์์ํฌ์ ์์ ์ฑ๊ณผ ๋ณด์์ ๋์ฑ ์ค์ํด์ง๊ณ ์์ต๋๋ค. AI ์ญ์ ํ๋ก ํธ์๋ ์๋ฒ ์ฌ์ด๋ ๋๊ตฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ํ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ฏ๋ก, ํ๋ ์์ํฌ์ ๊ณ ์์ค์ ์ถ์ํ์ ๋ฐ๋ฅธ ๋ณด์์ ์ค์๋ฅผ ํ ์ ์๋ ๊ตฌ์กฐ๋ AI๋ฅผ ํตํด ๋ ํฐ ์ํ์ ์ด๋ํ ์ ์์ต๋๋ค.
์์ผ๋ก์ ์น ํ๊ฒฝ์ AI ๋ฑ ๋ค์ํ ๊ธฐ์ ๊ณผ์ ์ตํฉ์ผ๋ก ๋ณต์ก์ฑ์ด ์ฆ๊ฐํ ๊ฒ์ ๋๋ค. ์ด ๊ณผ์ ์์ Next.js์ ๊ฐ์ ๋๋ฆฌ ์ฌ์ฉํ๋ ํ๋ก ํธ์๋ ํ๋ ์์ํฌ๋ค์ ๋ณด์๊ณผ ์์ ์ฑ ๋ฉด์์ ๊ณ์ ๋ฐ์ ํ ํ์๊ฐ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฌด์๋ณด๋ค AI ๊ธฐ์ ๊ณผ์ ์ตํฉ์ด ์ฌํ๋ ์๋ก ๊ฐ๋ฐ์ ์ค์ค๋ก์ ๋ณด์ ์ง์๊ณผ ๊ฐ๋ ์ด ๋งค์ฐ ์ค์ํ๋ฉฐ, ๋ ์ ๊ฒฝ ์จ์ผ ํ๋ค๋ ์ ์ ์์ง ๋ง์์ผ ํฉ๋๋ค.
