서버 액션이란?
서버 액션은 Next.js에서 제공하는 기능으로, 브라우저에서 직접 호출할 수 있는 서버 측 비동기 함수이다. 이를 통해 별도의 API 엔드포인트를 만들지 않고도 클라이언트에서 서버 측 로직을 실행할 수 있다.
서버 액션을 사용하려면 함수 내부에 "use server" 지시어를 추가하면 된다.
export default function Page() {
const saveName = async (formData: FormData) => {
"use server";
const name = formData.get("name");
await sql`INSERT INTO Names (name) VALUES (${name})`;
};
return (
<form action={saveName}>
<input name="name" />
<button type="submit">제출</button>
</form>
);
};
saveName함수는 서버 액션으로 정의됨- 폼 제출 시 이 함수가 서버에서 실행됨
- 클라이언트에서 직접 데이터베이스 쿼리를 실행하지 않아 보안이 강화됨
재검증 방식
서버 액션 실행 후 데이터 변경을 화면에 반영하기 위해 Next.js는 다양한 재검증 방식을 제공한다.
revalidatePath
특정 경로의 캐시를 무효화하고 데이터를 다시 가져오도록 한다.
import { revalidatePath } from "next/cache";
export async function createReviewAction(formData: FormData) {
// 서버 액션 로직..
revalidatePath(`/book/${bookId}`);
};
revalidatePath의 다양한 사용방법
1. 특정 주소에 해당하는 페이지만 재검증
revalidatePath(`/book/${bookId}`);
2. 특정 경로의 모든 동적 페이지를 재검증
revalidatePath('/book/[id]', 'page');
3. 특정 레이아웃을 갖는 모든 페이지 재검증
revalidatePath('/(with-searchbar)', 'layout');
4. 모든 데이터 재검증
revalidatePath('/', 'layout');
revalidatePath 사용 시 주의사항
- 서버 컴포넌트 또는 서버 액션 내부에서만 호출 가능하다.
- 해당 경로의 페이지 전체가 재검증된다.
즉, 페이지 내 모든 컴포넌트가 재렌더링되며 데이터 페칭도 다시 수행된다. - 데이터 캐시와 풀 라우트 매시가 모두 삭제된다.
(cache: 'force-cache'설정이 있어도 무효화) generateStaticParams로 생성된 정적 페이지에도 영향을 미친다.- 재검증 직후에는 새 데이터가 페이지에 반영되지만, 풀 라우트 캐시는 갱신되지 않는다.
- 다음 페이지 방문 시 동적 렌더링이 발생하며, 이때 풀 라우트 캐시가 최신 데이터로 업데이트된다.
revalidateTag
태그 값을 기준으로 데이터 캐시를 재검증한다. 페이지 전체가 아닌 특정 데이터만 선택적으로 재검증할 수 있다.
import { revalidateTag } from "next/cache";
export async function createReviewAction(formData: FormData) {
// 서버 액션 로직...
revalidateTag(`review-${bookId}`);
};
// 데이터 페칭 시 next.tags 옵션을 사용하여 해당 데이터에 태그를 지정해야 한다.
async function fetchReviews(bookId: string) {
const response = await fetch(`/api/reviews/${bookId}`, {
next: { tags: [`review-${bookId}`] } // 데이터에 태그 지정
});
// 응답 처리 로직...
};
클라이언트 컴포넌트에서의 서버 액션
useActionState 훅
React 19에서 추가된 useActionState 훅은 form 태그의 상태를 쉽게 핸들링할 수 있게 해준다.
const [state, formAction, isPending] = useActionState(createReviewAction, null);
<form action={formAction}>
{/* 폼 내용 */}
</form>
서버 액션 구현
"use server";
export async function createReviewAction(state: any, formData: FormData) {
// formData에서 필요한 데이터 추출
try {
// API 호출 또는 데이터 처리 로직
return { status: true, error: "" };
} catch (err) {
return { status: false, error: `에러 메시지: ${err}` };
}
};
isPending 활용
다음과 같이 서버 액션 실행 중 상태를 표시하고, UI 요소의 동작을 제어할 수 있다.
<button disabled={isPending} type="submit">
{isPending ? "..." : "작성하기"}
</button>
- 버튼의 텍스트를 동적으로 변경
- 서버 액션 실행 중에는 버튼을 비활성화
에러 핸들링
다음과 같이 서버 액션의 결과에 따른 에러 처리를 할 수 있다.
useEffect(() => {
if (state && !state.status) alert(state.error);
}, [state]);'Frontend > Next.js' 카테고리의 다른 글
| Next.js의 이미지 최적화 (0) | 2025.11.13 |
|---|---|
| Next.js 앱 라우터 고급 라우팅 패턴 (0) | 2025.11.13 |
| Next.js 앱 라우터의 에러 핸들링 (0) | 2025.11.13 |
| 스트리밍 (Streaming) (0) | 2025.11.13 |
| 라우트 세그먼트 옵션과 클라이언트 라우터 캐시 (0) | 2025.11.13 |
