본문 바로가기
C.W.K.
Stream
Lesson 01 of 08 · published

서버 액션은 함수로 표현한 변경 엔드포인트야

~20 min · Server Action, use server, mutations

Level 0호기심
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

클라이언트에서 부르지만 서버에서 실행돼

서버 액션은 서버에서 실행되는 async 함수야. 클라이언트 컴포넌트에서는 일반 함수처럼 참조하지만, Next.js가 뒤에서 고유한 POST 엔드포인트와 연결해 줘. 내부 변경 작업을 위해 URL과 JSON 배관을 따로 만들지 않아도 되는 이유야.

선언 방식은 두 가지야

방식선언법
파일 단위파일 첫 줄에 'use server'를 두면 그 파일의 모든 내보내기가 액션이 돼.
함수 단위서버 컴포넌트 안의 비동기 함수 본문 첫 줄에 'use server'를 둬.

내부 CRUD의 반복 배관을 없애

/api/.../route.ts를 만들고, 클라이언트에서 fetch()하고, 양쪽에서 JSON을 해석하는 흐름을 한 함수로 줄여. CSRF 방어, 암호화된 액션 ID, 쓰이지 않는 액션의 빌드 제외도 프레임워크가 제공해.

공개 HTTP 계약은 대신하지 않아

외부 서비스가 호출하는 API, webhook, 장기적으로 안정된 URL이 필요한 연동은 라우트 핸들러의 책임이야. 서버 액션은 앱 내부 UI가 서버 변경을 부르는 경계로 써.

변경 함수를 만들 때 입력 검증, 세션 확인, 권한 검사, DB 쓰기, 캐시 무효화의 순서를 한곳에서 읽을 수 있게 해. UI가 여러 곳이어도 같은 도메인 변경을 공유하도록 액션을 별도 서버 파일에 두고, 반환 상태만 폼마다 필요한 모양으로 어댑트해. 실패한 쓰기 뒤에는 무효화가 실행되지 않아야 해.

서버 액션이 함수처럼 보인다고 로컬 함수는 아니야. 네트워크를 건너는 POST이고 중복 제출·지연·실패가 생길 수 있어. 한 번만 실행된다고 가정하지 말고 idempotency가 필요한 결제나 주문에는 요청 키와 DB 제약을 함께 둬.

같은 내부 변경을 라우트 핸들러+fetch와 서버 액션으로 각각 만들어 요청·직렬화·오류 코드 양을 비교해. 미사용 액션이 build에서 빠지는지, 액션이 POST로만 도달하는지 확인하고 외부 curl 소비자가 필요해지는 순간 어느 쪽이 맞는지도 설명해. 액션 이름은 saveData보다 publishPost, transferBalance처럼 도메인 결과를 말하게 지어. HTTP URL이 사라진 만큼 함수 이름과 타입이 변경 계약을 설명하는 주된 표면이 되기 때문이야.

Code

파일 단위 액션 모듈·ts
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';

export async function createPost(formData: FormData) {
  const title = formData.get('title') as string;
  const content = formData.get('content') as string;
  await db.post.create({ data: { title, content } });
  revalidatePath('/posts');
}
서버 컴포넌트 안의 인라인 액션·tsx
// app/page.tsx
export default function Page() {
  async function handleSubmit(formData: FormData) {
    'use server';
    await db.post.create({ data: { title: formData.get('title') as string } });
  }
  return (
    <form action={handleSubmit}>
      <input name="title" required />
      <button>Create</button>
    </form>
  );
}

External links

Exercise

내부 CRUD 하나를 서버 액션으로 구현해. 기존 API+fetch 방식과 비교해 줄어든 배관과 그대로 남아야 하는 검증·인증을 표시해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.