stack-analysis
CHAPTER 14 / 90
읽기 약 2분
FUNCTION
서버 액션(Server Actions): 폼 처리의 미래
핵심 개념
"use server"·revalidatePath·낙관적 UI — REST API 없이 폼 처리.
본문
Server Action 기본
// app/actions/posts.ts
'use server';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { z } from 'zod';
const PostSchema = z.object({
title: z.string().min(1).max(200),
content: z.string().min(1),
});
export async function createPost(formData: FormData) {
const parsed = PostSchema.safeParse({
title: formData.get('title'),
content: formData.get('content'),
});
if (!parsed.success) {
return { error: parsed.error.flatten().fieldErrors };
}
const post = await db.post.create({ data: parsed.data });
revalidatePath('/posts'); // 캐시 무효화
redirect(`/posts/${post.id}`);
}
// app/posts/new/page.tsx — 서버 컴포넌트
import { createPost } from '@/app/actions/posts';
export default function NewPost() {
return (
<form action={createPost}>
<input name="title" required />
<textarea name="content" required />
<button type="submit">저장</button>
</form>
);
}useActionState (React 19)
'use client';
import { useActionState } from 'react';
import { createPost } from '@/app/actions/posts';
export function PostForm() {
const [state, action, isPending] = useActionState(
async (prevState: any, formData: FormData) => {
return await createPost(formData);
},
null
);
return (
<form action={action}>
<input name="title" />
{state?.error?.title && <p>{state.error.title}</p>}
<textarea name="content" />
<button disabled={isPending}>
{isPending ? '저장 중...' : '저장'}
</button>
</form>
);
}낙관적 업데이트 (useOptimistic)
'use client';
import { useOptimistic } from 'react';
import { addComment } from '@/app/actions/comments';
export function CommentList({ comments }: { comments: Comment[] }) {
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(state, newComment: Comment) => [...state, { ...newComment, pending: true }]
);
async function handleSubmit(formData: FormData) {
const text = formData.get('text') as string;
addOptimistic({ id: 'temp', text, author: '나' });
await addComment(formData);
}
return (
<>
<ul>
{optimisticComments.map(c => (
<li key={c.id} style={{ opacity: c.pending ? 0.5 : 1 }}>
{c.text}
</li>
))}
</ul>
<form action={handleSubmit}>
<input name="text" />
<button>등록</button>
</form>
</>
);
}다음 챕터
CH.15 "ISR + 온디맨드 재검증" — 캐시 전략.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 Server Actions 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
Server Actions 관련 인기 라이브러리/패턴 5개를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 Server Actions 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 프론트엔드 시장의 Server Actions 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
서버 액션(Server Actions): 폼 처리의 미래는 이 3가지만 확실히 잡으세요
1.Server Actions = REST API 없이 폼 처리 + 자동 진행 상태 + 타입 안전
2.revalidatePath/revalidateTag로 정확한 캐시 무효화
3.useOptimistic으로 즉시 UI 반영 + 실패 시 자동 롤백
공유하기
진행도 14 / 90